2010-06-21 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / utils / mono-counters.c
blobaf77254c9bdae864b9ed6c79c046503fc448d95e
1 #include <stdlib.h>
2 #include <glib.h>
3 #include "mono-counters.h"
5 typedef struct _MonoCounter MonoCounter;
7 struct _MonoCounter {
8 MonoCounter *next;
9 const char *name;
10 void *addr;
11 int type;
14 static MonoCounter *counters = NULL;
15 static int valid_mask = 0;
16 static int set_mask = 0;
18 /**
19 * mono_counters_enable:
20 * @section_mask: a mask listing the sections that will be displayed
22 * This is used to track which counters will be displayed.
24 void
25 mono_counters_enable (int section_mask)
27 valid_mask = section_mask & MONO_COUNTER_SECTION_MASK;
30 /**
31 * mono_counters_register:
32 * @name: The name for this counters.
33 * @type: One of the possible MONO_COUNTER types, or MONO_COUNTER_CALLBACK for a function pointer.
34 * @addr: The address to register.
36 * Register addr as the address of a counter of type type.
37 * Note that @name must be a valid string at all times until
38 * mono_counters_dump () is called.
40 * It may be a function pointer if MONO_COUNTER_CALLBACK is specified:
41 * the function should return the value and take no arguments.
43 void
44 mono_counters_register (const char* name, int type, void *addr)
46 MonoCounter *counter;
47 if (!(type & valid_mask))
48 return;
49 counter = malloc (sizeof (MonoCounter));
50 if (!counter)
51 return;
52 counter->name = name;
53 counter->type = type;
54 counter->addr = addr;
55 counter->next = NULL;
57 set_mask |= type;
59 /* Append */
60 if (counters) {
61 MonoCounter *item = counters;
62 while (item->next)
63 item = item->next;
64 item->next = counter;
65 } else {
66 counters = counter;
70 typedef int (*IntFunc) (void);
71 typedef guint (*UIntFunc) (void);
72 typedef gint64 (*LongFunc) (void);
73 typedef guint64 (*ULongFunc) (void);
74 typedef gssize (*PtrFunc) (void);
75 typedef double (*DoubleFunc) (void);
76 typedef char* (*StrFunc) (void);
78 #define ENTRY_FMT "%-36s: "
79 static void
80 dump_counter (MonoCounter *counter, FILE *outfile) {
81 int intval;
82 guint uintval;
83 gint64 int64val;
84 guint64 uint64val;
85 gssize wordval;
86 double dval;
87 const char *str;
88 switch (counter->type & MONO_COUNTER_TYPE_MASK) {
89 case MONO_COUNTER_INT:
90 if (counter->type & MONO_COUNTER_CALLBACK)
91 intval = ((IntFunc)counter->addr) ();
92 else
93 intval = *(int*)counter->addr;
94 fprintf (outfile, ENTRY_FMT "%d\n", counter->name, intval);
95 break;
96 case MONO_COUNTER_UINT:
97 if (counter->type & MONO_COUNTER_CALLBACK)
98 uintval = ((UIntFunc)counter->addr) ();
99 else
100 uintval = *(guint*)counter->addr;
101 fprintf (outfile, ENTRY_FMT "%u\n", counter->name, uintval);
102 break;
103 case MONO_COUNTER_LONG:
104 if (counter->type & MONO_COUNTER_CALLBACK)
105 int64val = ((LongFunc)counter->addr) ();
106 else
107 int64val = *(gint64*)counter->addr;
108 fprintf (outfile, ENTRY_FMT "%lld\n", counter->name, (long long)int64val);
109 break;
110 case MONO_COUNTER_ULONG:
111 if (counter->type & MONO_COUNTER_CALLBACK)
112 uint64val = ((ULongFunc)counter->addr) ();
113 else
114 uint64val = *(guint64*)counter->addr;
115 fprintf (outfile, ENTRY_FMT "%llu\n", counter->name, (unsigned long long)uint64val);
116 break;
117 case MONO_COUNTER_WORD:
118 if (counter->type & MONO_COUNTER_CALLBACK)
119 wordval = ((PtrFunc)counter->addr) ();
120 else
121 wordval = *(gssize*)counter->addr;
122 #if SIZEOF_VOID_P == 8
123 fprintf (outfile, ENTRY_FMT "%lld\n", counter->name, (gint64)wordval);
124 #else
125 fprintf (outfile, ENTRY_FMT "%d\n", counter->name, (gint)wordval);
126 #endif
127 break;
128 case MONO_COUNTER_DOUBLE:
129 if (counter->type & MONO_COUNTER_CALLBACK)
130 dval = ((DoubleFunc)counter->addr) ();
131 else
132 dval = *(double*)counter->addr;
133 fprintf (outfile, ENTRY_FMT "%.2f\n", counter->name, dval);
134 break;
135 case MONO_COUNTER_STRING:
136 if (counter->type & MONO_COUNTER_CALLBACK)
137 str = ((StrFunc)counter->addr) ();
138 else
139 str = *(char**)counter->addr;
140 fprintf (outfile, ENTRY_FMT "%s\n", counter->name, str);
141 break;
145 static const char
146 section_names [][10] = {
147 "JIT",
148 "GC",
149 "Metadata",
150 "Generics",
151 "Security"
154 static void
155 mono_counters_dump_section (int section, FILE *outfile)
157 MonoCounter *counter = counters;
158 while (counter) {
159 if (counter->type & section)
160 dump_counter (counter, outfile);
161 counter = counter->next;
166 * mono_counters_dump:
167 * @section_mask: The sections to dump counters for
168 * @outfile: a FILE to dump the results to
170 * Displays the counts of all the enabled counters registered.
172 void
173 mono_counters_dump (int section_mask, FILE *outfile)
175 int i, j;
176 section_mask &= valid_mask;
177 if (!counters)
178 return;
179 for (j = 0, i = MONO_COUNTER_JIT; i < MONO_COUNTER_LAST_SECTION; j++, i <<= 1) {
180 if ((section_mask & i) && (set_mask & i)) {
181 fprintf (outfile, "\n%s statistics\n", section_names [j]);
182 mono_counters_dump_section (i, outfile);
188 * mono_counters_cleanup:
190 * Perform any needed cleanup at process exit.
192 void
193 mono_counters_cleanup (void)
195 MonoCounter *counter = counters;
196 while (counter) {
197 MonoCounter *tmp = counters;
198 counter = counter->next;
199 free (tmp);
201 counters = NULL;