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