Ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e0ba6b95ab71a441357ed5484e33498)
debug_counter.c
1/**********************************************************************
2
3 debug_counter.c -
4
5 created at: Tue Feb 21 16:51:18 2017
6
7 Copyright (C) 2017 Koichi Sasada
8
9**********************************************************************/
10
11#include "debug_counter.h"
12#include "internal.h"
13#include <stdio.h>
14#include <locale.h>
15#include "ruby/thread_native.h"
16
17#if USE_DEBUG_COUNTER
18
19static const char *const debug_counter_names[] = {
20 ""
21#define RB_DEBUG_COUNTER(name) #name,
22#include "debug_counter.h"
23#undef RB_DEBUG_COUNTER
24};
25
26MJIT_SYMBOL_EXPORT_BEGIN
27size_t rb_debug_counter[numberof(debug_counter_names)];
28void rb_debug_counter_add_atomic(enum rb_debug_counter_type type, int add);
29MJIT_SYMBOL_EXPORT_END
30
31rb_nativethread_lock_t debug_counter_lock;
32
33__attribute__((constructor))
34static void
35debug_counter_setup(void)
36{
37 rb_nativethread_lock_initialize(&debug_counter_lock);
38}
39
40void
41rb_debug_counter_add_atomic(enum rb_debug_counter_type type, int add)
42{
43 rb_nativethread_lock_lock(&debug_counter_lock);
44 {
45 rb_debug_counter[(int)type] += add;
46 }
47 rb_nativethread_lock_unlock(&debug_counter_lock);
48}
49
50int debug_counter_disable_show_at_exit = 0;
51
52// note that this operation is not atomic.
53void
54ruby_debug_counter_reset(void)
55{
56 for (int i = 0; i < RB_DEBUG_COUNTER_MAX; i++) {
57 switch (i) {
58 case RB_DEBUG_COUNTER_mjit_length_unit_queue:
59 case RB_DEBUG_COUNTER_mjit_length_active_units:
60 case RB_DEBUG_COUNTER_mjit_length_compact_units:
61 case RB_DEBUG_COUNTER_mjit_length_stale_units:
62 // These counters may be decreased and should not be reset.
63 break;
64 default:
65 rb_debug_counter[i] = 0;
66 break;
67 }
68 }
69}
70
71// note that this operation is not atomic.
72size_t
73ruby_debug_counter_get(const char **names_ptr, size_t *counters_ptr)
74{
75 int i;
76 if (names_ptr != NULL) {
77 for (i=0; i<RB_DEBUG_COUNTER_MAX; i++) {
78 names_ptr[i] = debug_counter_names[i];
79 }
80 }
81 if (counters_ptr != NULL) {
82 for (i=0; i<RB_DEBUG_COUNTER_MAX; i++) {
83 counters_ptr[i] = rb_debug_counter[i];
84 }
85 }
86
87 return RB_DEBUG_COUNTER_MAX;
88}
89
90void
91ruby_debug_counter_show_at_exit(int enable)
92{
93 debug_counter_disable_show_at_exit = !enable;
94}
95
96void
97rb_debug_counter_show_results(const char *msg)
98{
99 const char *env = getenv("RUBY_DEBUG_COUNTER_DISABLE");
100
101 setlocale(LC_NUMERIC, "");
102
103 if (env == NULL || strcmp("1", env) != 0) {
104 int i;
105 fprintf(stderr, "[RUBY_DEBUG_COUNTER]\t%d %s\n", getpid(), msg);
106 for (i=0; i<RB_DEBUG_COUNTER_MAX; i++) {
107 fprintf(stderr, "[RUBY_DEBUG_COUNTER]\t%-30s\t%'14"PRIuSIZE"\n",
108 debug_counter_names[i],
109 rb_debug_counter[i]);
110 }
111 }
112}
113
114VALUE
115rb_debug_counter_show(RB_UNUSED_VAR(VALUE klass))
116{
117 rb_debug_counter_show_results("show_debug_counters");
118 ruby_debug_counter_show_at_exit(FALSE);
119 return Qnil;
120}
121
122VALUE
123rb_debug_counter_reset(RB_UNUSED_VAR(VALUE klass))
124{
125 ruby_debug_counter_reset();
126 return Qnil;
127}
128
129__attribute__((destructor))
130static void
131debug_counter_show_results_at_exit(void)
132{
133 if (debug_counter_disable_show_at_exit == 0) {
134 rb_debug_counter_show_results("normal exit.");
135 }
136}
137
138#else
139
140void
141rb_debug_counter_show_results(const char *msg)
142{
143}
144
145size_t
146ruby_debug_counter_get(const char **names_ptr, size_t *counters_ptr)
147{
148 return 0;
149}
150void
151ruby_debug_counter_reset(void)
152{
153}
154
155void
156ruby_debug_counter_show_at_exit(int enable)
157{
158}
159
160#endif /* USE_DEBUG_COUNTER */
#define Qnil
Old name of RUBY_Qnil.
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:56
void rb_nativethread_lock_lock(rb_nativethread_lock_t *lock)
Blocks until the current thread obtains a lock.
Definition: thread.c:440
void rb_nativethread_lock_unlock(rb_nativethread_lock_t *lock)
Releases a lock.
Definition: thread.c:446
void rb_nativethread_lock_initialize(rb_nativethread_lock_t *lock)
Fills the passed lock with an initial value.
Definition: thread.c:428