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