2006-03-29 Chris Toshok <toshok@ximian.com>
[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 void
18 mono_counters_enable (int section_mask)
19 {
20         valid_mask = section_mask & MONO_COUNTER_SECTION_MASK;
21 }
22
23 void 
24 mono_counters_register (const char* name, int type, void *addr)
25 {
26         MonoCounter *counter;
27         if (!(type & valid_mask))
28                 return;
29         counter = malloc (sizeof (MonoCounter));
30         if (!counter)
31                 return;
32         counter->name = name;
33         counter->type = type;
34         counter->addr = addr;
35         counter->next = NULL;
36
37         /* Append */
38         if (counters) {
39                 MonoCounter *item = counters;
40                 while (item->next)
41                         item = item->next;
42                 item->next = counter;
43         } else {
44                 counters = counter;
45         }
46 }
47
48 typedef int (*IntFunc) (void);
49 typedef guint (*UIntFunc) (void);
50 typedef gint64 (*LongFunc) (void);
51 typedef guint64 (*ULongFunc) (void);
52 typedef gssize (*PtrFunc) (void);
53 typedef double (*DoubleFunc) (void);
54 typedef char* (*StrFunc) (void);
55
56 #define ENTRY_FMT "%-24s : "
57 static void
58 dump_counter (MonoCounter *counter, FILE *outfile) {
59         int intval;
60         guint uintval;
61         gint64 int64val;
62         guint64 uint64val;
63         gssize wordval;
64         double dval;
65         const char *str;
66         switch (counter->type & MONO_COUNTER_TYPE_MASK) {
67         case MONO_COUNTER_INT:
68               if (counter->type & MONO_COUNTER_CALLBACK)
69                       intval = ((IntFunc)counter->addr) ();
70               else
71                       intval = *(int*)counter->addr;
72               fprintf (outfile, ENTRY_FMT "%d\n", counter->name, intval);
73               break;
74         case MONO_COUNTER_UINT:
75               if (counter->type & MONO_COUNTER_CALLBACK)
76                       uintval = ((UIntFunc)counter->addr) ();
77               else
78                       uintval = *(guint*)counter->addr;
79               fprintf (outfile, ENTRY_FMT "%u\n", counter->name, uintval);
80               break;
81         case MONO_COUNTER_LONG:
82               if (counter->type & MONO_COUNTER_CALLBACK)
83                       int64val = ((LongFunc)counter->addr) ();
84               else
85                       int64val = *(gint64*)counter->addr;
86               fprintf (outfile, ENTRY_FMT "%lld\n", counter->name, int64val);
87               break;
88         case MONO_COUNTER_ULONG:
89               if (counter->type & MONO_COUNTER_CALLBACK)
90                       uint64val = ((ULongFunc)counter->addr) ();
91               else
92                       uint64val = *(guint64*)counter->addr;
93               fprintf (outfile, ENTRY_FMT "%llu\n", counter->name, uint64val);
94               break;
95         case MONO_COUNTER_WORD:
96               if (counter->type & MONO_COUNTER_CALLBACK)
97                       wordval = ((PtrFunc)counter->addr) ();
98               else
99                       wordval = *(gssize*)counter->addr;
100 #if SIZEOF_VOID_P == 8
101               fprintf (outfile, ENTRY_FMT "%lld\n", counter->name, (gint64)wordval);
102 #else
103               fprintf (outfile, ENTRY_FMT "%d\n", counter->name, wordval);
104 #endif
105               break;
106         case MONO_COUNTER_DOUBLE:
107               if (counter->type & MONO_COUNTER_CALLBACK)
108                       dval = ((DoubleFunc)counter->addr) ();
109               else
110                       dval = *(double*)counter->addr;
111               fprintf (outfile, ENTRY_FMT "%.2f\n", counter->name, dval);
112               break;
113         case MONO_COUNTER_STRING:
114               if (counter->type & MONO_COUNTER_CALLBACK)
115                       str = ((StrFunc)counter->addr) ();
116               else
117                       str = *(char**)counter->addr;
118               fprintf (outfile, ENTRY_FMT "%s\n", counter->name, str);
119               break;
120         }
121 }
122
123 static const char
124 section_names [][10] = {
125         "JIT",
126         "GC",
127         "Metadata",
128         "Generics",
129         "Security"
130 };
131
132 static void
133 mono_counters_dump_section (int section, FILE *outfile)
134 {
135         MonoCounter *counter = counters;
136         while (counter) {
137                 if (counter->type & section)
138                         dump_counter (counter, outfile);
139                 counter = counter->next;
140         }
141 }
142
143 void
144 mono_counters_dump (int section_mask, FILE *outfile)
145 {
146         int i, j;
147         section_mask &= valid_mask;
148         if (!counters)
149                 return;
150         for (j = 0, i = MONO_COUNTER_JIT; i < MONO_COUNTER_LAST_SECTION; j++, i <<= 1) {
151                 if (section_mask & i) {
152                         fprintf (outfile, "\n%s statistics\n", section_names [j]);
153                         mono_counters_dump_section (i, outfile);
154                 }
155         }
156 }
157