X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Futils%2Fmono-counters.c;h=e55114beee80b12b5e29c90b0a3c28b68d93bfc6;hb=17fcfee696ac813e1fff6347f2d85b8a2de4085f;hp=a12a528d6d14550007c9c918149515bf038a9fe6;hpb=64f85a65b023522d3f34e9932e6a843e0ad8fc3b;p=mono.git diff --git a/mono/utils/mono-counters.c b/mono/utils/mono-counters.c index a12a528d6d1..e55114beee8 100644 --- a/mono/utils/mono-counters.c +++ b/mono/utils/mono-counters.c @@ -1,3 +1,8 @@ +/* + * Copyright 2006-2010 Novell + * Copyright 2011 Xamarin Inc + */ + #include #include #include "mono-counters.h" @@ -13,6 +18,7 @@ struct _MonoCounter { static MonoCounter *counters = NULL; static int valid_mask = 0; +static int set_mask = 0; /** * mono_counters_enable: @@ -33,6 +39,8 @@ mono_counters_enable (int section_mask) * @addr: The address to register. * * Register addr as the address of a counter of type type. + * Note that @name must be a valid string at all times until + * mono_counters_dump () is called. * * It may be a function pointer if MONO_COUNTER_CALLBACK is specified: * the function should return the value and take no arguments. @@ -51,6 +59,8 @@ mono_counters_register (const char* name, int type, void *addr) counter->addr = addr; counter->next = NULL; + set_mask |= type; + /* Append */ if (counters) { MonoCounter *item = counters; @@ -70,7 +80,7 @@ typedef gssize (*PtrFunc) (void); typedef double (*DoubleFunc) (void); typedef char* (*StrFunc) (void); -#define ENTRY_FMT "%-24s : " +#define ENTRY_FMT "%-36s: " static void dump_counter (MonoCounter *counter, FILE *outfile) { int intval; @@ -100,14 +110,14 @@ dump_counter (MonoCounter *counter, FILE *outfile) { int64val = ((LongFunc)counter->addr) (); else int64val = *(gint64*)counter->addr; - fprintf (outfile, ENTRY_FMT "%lld\n", counter->name, int64val); + fprintf (outfile, ENTRY_FMT "%lld\n", counter->name, (long long)int64val); break; case MONO_COUNTER_ULONG: if (counter->type & MONO_COUNTER_CALLBACK) uint64val = ((ULongFunc)counter->addr) (); else uint64val = *(guint64*)counter->addr; - fprintf (outfile, ENTRY_FMT "%llu\n", counter->name, uint64val); + fprintf (outfile, ENTRY_FMT "%llu\n", counter->name, (unsigned long long)uint64val); break; case MONO_COUNTER_WORD: if (counter->type & MONO_COUNTER_CALLBACK) @@ -117,7 +127,7 @@ dump_counter (MonoCounter *counter, FILE *outfile) { #if SIZEOF_VOID_P == 8 fprintf (outfile, ENTRY_FMT "%lld\n", counter->name, (gint64)wordval); #else - fprintf (outfile, ENTRY_FMT "%d\n", counter->name, wordval); + fprintf (outfile, ENTRY_FMT "%d\n", counter->name, (gint)wordval); #endif break; case MONO_COUNTER_DOUBLE: @@ -125,7 +135,7 @@ dump_counter (MonoCounter *counter, FILE *outfile) { dval = ((DoubleFunc)counter->addr) (); else dval = *(double*)counter->addr; - fprintf (outfile, ENTRY_FMT "%.2f\n", counter->name, dval); + fprintf (outfile, ENTRY_FMT "%.4f\n", counter->name, dval); break; case MONO_COUNTER_STRING: if (counter->type & MONO_COUNTER_CALLBACK) @@ -134,6 +144,13 @@ dump_counter (MonoCounter *counter, FILE *outfile) { str = *(char**)counter->addr; fprintf (outfile, ENTRY_FMT "%s\n", counter->name, str); break; + case MONO_COUNTER_TIME_INTERVAL: + if (counter->type & MONO_COUNTER_CALLBACK) + int64val = ((LongFunc)counter->addr) (); + else + int64val = *(gint64*)counter->addr; + fprintf (outfile, ENTRY_FMT "%.2f ms\n", counter->name, (double)int64val / 1000.0); + break; } } @@ -172,10 +189,95 @@ mono_counters_dump (int section_mask, FILE *outfile) if (!counters) return; for (j = 0, i = MONO_COUNTER_JIT; i < MONO_COUNTER_LAST_SECTION; j++, i <<= 1) { - if (section_mask & i) { + if ((section_mask & i) && (set_mask & i)) { fprintf (outfile, "\n%s statistics\n", section_names [j]); mono_counters_dump_section (i, outfile); } } + + fflush (outfile); +} + +/** + * mono_counters_cleanup: + * + * Perform any needed cleanup at process exit. + */ +void +mono_counters_cleanup (void) +{ + MonoCounter *counter = counters; + while (counter) { + MonoCounter *tmp = counters; + counter = counter->next; + free (tmp); + } + counters = NULL; +} + +static MonoResourceCallback limit_reached = NULL; +static uintptr_t resource_limits [MONO_RESOURCE_COUNT * 2]; + +/** + * mono_runtime_resource_check_limit: + * @resource_type: one of the #MonoResourceType enum values + * @value: the current value of the resource usage + * + * Check if a runtime resource limit has been reached. This function + * is intended to be used by the runtime only. + */ +void +mono_runtime_resource_check_limit (int resource_type, uintptr_t value) +{ + if (!limit_reached) + return; + /* check the hard limit first */ + if (value > resource_limits [resource_type * 2 + 1]) { + limit_reached (resource_type, value, 0); + return; + } + if (value > resource_limits [resource_type * 2]) + limit_reached (resource_type, value, 1); } +/** + * mono_runtime_resource_limit: + * @resource_type: one of the #MonoResourceType enum values + * @soft_limit: the soft limit value + * @hard_limit: the hard limit value + * + * This function sets the soft and hard limit for runtime resources. When the limit + * is reached, a user-specified callback is called. The callback runs in a restricted + * environment, in which the world coult be stopped, so it can't take locks, perform + * allocations etc. The callback may be called multiple times once a limit has been reached + * if action is not taken to decrease the resource use. + * + * Returns: 0 on error or a positive integer otherwise. + */ +int +mono_runtime_resource_limit (int resource_type, uintptr_t soft_limit, uintptr_t hard_limit) +{ + if (resource_type >= MONO_RESOURCE_COUNT || resource_type < 0) + return 0; + if (soft_limit > hard_limit) + return 0; + resource_limits [resource_type * 2] = soft_limit; + resource_limits [resource_type * 2 + 1] = hard_limit; + return 1; +} + +/** + * mono_runtime_resource_set_callback: + * @callback: a function pointer + * + * Set the callback to be invoked when a resource limit is reached. + * The callback will receive the resource type, the resource amount in resource-specific + * units and a flag indicating whether the soft or hard limit was reached. + */ +void +mono_runtime_resource_set_callback (MonoResourceCallback callback) +{ + limit_reached = callback; +} + +