Ruby 3.2.2p53 (2023-03-30 revision e51014f9c05aa65cbf203442d37fef7c12390015)
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
19const char *const rb_debug_counter_names[] = {
20#define DEBUG_COUNTER_NAME_EMPTY "" /* Suppress -Wstring-concatenation */
21 DEBUG_COUNTER_NAME_EMPTY
22#undef DEBUG_COUNTER_NAME_EMPTY
23#define RB_DEBUG_COUNTER(name) #name,
24#include "debug_counter.h"
25#undef RB_DEBUG_COUNTER
26};
27
28MJIT_SYMBOL_EXPORT_BEGIN
29size_t rb_debug_counter[numberof(rb_debug_counter_names)];
30void rb_debug_counter_add_atomic(enum rb_debug_counter_type type, int add);
31MJIT_SYMBOL_EXPORT_END
32
33static rb_nativethread_lock_t debug_counter_lock;
34
35__attribute__((constructor))
36static void
37debug_counter_setup(void)
38{
39 rb_nativethread_lock_initialize(&debug_counter_lock);
40}
41
42void
43rb_debug_counter_add_atomic(enum rb_debug_counter_type type, int add)
44{
45 rb_nativethread_lock_lock(&debug_counter_lock);
46 {
47 rb_debug_counter[(int)type] += add;
48 }
49 rb_nativethread_lock_unlock(&debug_counter_lock);
50}
51
52static int debug_counter_disable_show_at_exit = 0;
53
54// note that this operation is not atomic.
55void
56ruby_debug_counter_reset(void)
57{
58 for (int i = 0; i < RB_DEBUG_COUNTER_MAX; i++) {
59 rb_debug_counter[i] = 0;
60 }
61}
62
63// note that this operation is not atomic.
64size_t
65ruby_debug_counter_get(const char **names_ptr, size_t *counters_ptr)
66{
67 int i;
68 if (names_ptr != NULL) {
69 for (i=0; i<RB_DEBUG_COUNTER_MAX; i++) {
70 names_ptr[i] = rb_debug_counter_names[i];
71 }
72 }
73 if (counters_ptr != NULL) {
74 for (i=0; i<RB_DEBUG_COUNTER_MAX; i++) {
75 counters_ptr[i] = rb_debug_counter[i];
76 }
77 }
78
79 return RB_DEBUG_COUNTER_MAX;
80}
81
82void
83ruby_debug_counter_show_at_exit(int enable)
84{
85 debug_counter_disable_show_at_exit = !enable;
86}
87
88void
89rb_debug_counter_show_results(const char *msg)
90{
91 const char *env = getenv("RUBY_DEBUG_COUNTER_DISABLE");
92
93 setlocale(LC_NUMERIC, "");
94
95 if (env == NULL || strcmp("1", env) != 0) {
96 int i;
97 fprintf(stderr, "[RUBY_DEBUG_COUNTER]\t%d %s\n", getpid(), msg);
98 for (i=0; i<RB_DEBUG_COUNTER_MAX; i++) {
99 fprintf(stderr, "[RUBY_DEBUG_COUNTER]\t%-30s\t%'14"PRIuSIZE"\n",
100 rb_debug_counter_names[i],
101 rb_debug_counter[i]);
102 }
103 }
104}
105
106VALUE
107rb_debug_counter_show(RB_UNUSED_VAR(VALUE klass))
108{
109 rb_debug_counter_show_results("show_debug_counters");
110 ruby_debug_counter_show_at_exit(FALSE);
111 return Qnil;
112}
113
114VALUE
115rb_debug_counter_reset(RB_UNUSED_VAR(VALUE klass))
116{
117 ruby_debug_counter_reset();
118 return Qnil;
119}
120
121__attribute__((destructor))
122static void
123debug_counter_show_results_at_exit(void)
124{
125 if (debug_counter_disable_show_at_exit == 0) {
126 rb_debug_counter_show_results("normal exit.");
127 }
128}
129
130#else
131
132void
133rb_debug_counter_show_results(const char *msg)
134{
135}
136
137size_t
138ruby_debug_counter_get(const char **names_ptr, size_t *counters_ptr)
139{
140 return 0;
141}
142void
143ruby_debug_counter_reset(void)
144{
145}
146
147void
148ruby_debug_counter_show_at_exit(int enable)
149{
150}
151
152#endif /* USE_DEBUG_COUNTER */
#define Qnil
Old name of RUBY_Qnil.
VALUE type(ANYARGS)
ANYARGS-ed function type.
void rb_nativethread_lock_lock(rb_nativethread_lock_t *lock)
Blocks until the current thread obtains a lock.
Definition thread.c:299
void rb_nativethread_lock_unlock(rb_nativethread_lock_t *lock)
Releases a lock.
Definition thread.c:305
void rb_nativethread_lock_initialize(rb_nativethread_lock_t *lock)
Fills the passed lock with an initial value.
Definition thread.c:287
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40