Ruby  3.1.4p223 (2023-03-30 revision HEAD)
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 
19 static 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 
26 MJIT_SYMBOL_EXPORT_BEGIN
27 size_t rb_debug_counter[numberof(debug_counter_names)];
28 void rb_debug_counter_add_atomic(enum rb_debug_counter_type type, int add);
29 MJIT_SYMBOL_EXPORT_END
30 
31 rb_nativethread_lock_t debug_counter_lock;
32 
33 __attribute__((constructor))
34 static void
35 debug_counter_setup(void)
36 {
37  rb_nativethread_lock_initialize(&debug_counter_lock);
38 }
39 
40 void
41 rb_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 
50 int debug_counter_disable_show_at_exit = 0;
51 
52 // note that this operation is not atomic.
53 void
54 ruby_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.
72 size_t
73 ruby_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 
90 void
91 ruby_debug_counter_show_at_exit(int enable)
92 {
93  debug_counter_disable_show_at_exit = !enable;
94 }
95 
96 void
97 rb_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 
114 VALUE
115 rb_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 
122 VALUE
123 rb_debug_counter_reset(RB_UNUSED_VAR(VALUE klass))
124 {
125  ruby_debug_counter_reset();
126  return Qnil;
127 }
128 
129 __attribute__((destructor))
130 static void
131 debug_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 
140 void
141 rb_debug_counter_show_results(const char *msg)
142 {
143 }
144 
145 size_t
146 ruby_debug_counter_get(const char **names_ptr, size_t *counters_ptr)
147 {
148  return 0;
149 }
150 void
151 ruby_debug_counter_reset(void)
152 {
153 }
154 
155 void
156 ruby_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
uintptr_t VALUE
Type that represents a Ruby object.
Definition: value.h:40