X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmono-perfcounters.c;h=1a3123a30aad58811bbf8d07c6d0581ac029474e;hb=HEAD;hp=fb205e80eaff2781966cdb448262ac85e9bac19f;hpb=cde767b6ba11e70cddef61d297cb67626a38edc1;p=mono.git diff --git a/mono/metadata/mono-perfcounters.c b/mono/metadata/mono-perfcounters.c index fb205e80eaf..1a3123a30aa 100644 --- a/mono/metadata/mono-perfcounters.c +++ b/mono/metadata/mono-perfcounters.c @@ -1,5 +1,5 @@ -/* - * mono-perfcounters.c +/** + * \file * * Performance counters support. * @@ -30,9 +30,12 @@ #include #include #include +#include #endif -#if defined (__NetBSD__) || defined (__APPLE__) +#if defined (__NetBSD__) +#include #include +#include #endif #include "metadata/mono-perfcounters.h" #include "metadata/appdomain.h" @@ -45,7 +48,7 @@ #include "utils/mono-networkinterfaces.h" #include "utils/mono-error-internals.h" #include "utils/atomic.h" -#include +#include "utils/unlocked.h" /* map of CounterSample.cs */ struct _MonoCounterSample { @@ -425,7 +428,7 @@ mono_determine_physical_ram_size (void) int mib[2] = { CTL_HW, #ifdef __NetBSD__ - HW_PHYSMEM + HW_PHYSMEM64 #else HW_MEMSIZE #endif @@ -474,29 +477,22 @@ mono_determine_physical_ram_available_size (void) #elif defined (__NetBSD__) struct vmtotal vm_total; guint64 page_size; - int mib [2]; + int mib[2]; size_t len; + mib[0] = CTL_VM; + mib[1] = VM_METER; - mib = { - CTL_VM, -#if defined (VM_METER) - VM_METER -#else - VM_TOTAL -#endif - }; len = sizeof (vm_total); sysctl (mib, 2, &vm_total, &len, NULL, 0); - mib = { - CTL_HW, - HW_PAGESIZE - }; + mib[0] = CTL_HW; + mib[1] = HW_PAGESIZE; + len = sizeof (page_size); - sysctl (mib, 2, &page_size, &len, NULL, 0 + sysctl (mib, 2, &page_size, &len, NULL, 0); - return ((guint64) value.t_free * page_size) / 1024; + return ((guint64) vm_total.t_free * page_size) / 1024; #elif defined (__APPLE__) mach_msg_type_number_t count = HOST_VM_INFO_COUNT; mach_port_t host = mach_host_self(); @@ -802,16 +798,14 @@ fill_sample (MonoCounterSample *sample) } static int -id_from_string (MonoString *instance, gboolean is_process) +id_from_string (const gchar *id_str, gboolean is_process) { int id = -1; - if (mono_string_length (instance)) { - char *id_str = mono_string_to_utf8 (instance); + if (strcmp("", id_str) != 0) { char *end; id = strtol (id_str, &end, 0); if (end == id_str && !is_process) id = -1; - g_free (id_str); } return id; } @@ -849,7 +843,7 @@ get_cpu_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample * } static void* -cpu_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoolean *custom) +cpu_get_impl (MonoString* counter, const gchar* instance, int *type, MonoBoolean *custom) { int id = id_from_string (instance, FALSE) << 5; const CounterDesc *cdesc; @@ -910,7 +904,7 @@ network_cleanup (ImplVtable *vtable) } static void* -network_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoolean *custom) +network_get_impl (MonoString* counter, const gchar* instance, int *type, MonoBoolean *custom) { const CounterDesc *cdesc; NetworkVtableArg *narg; @@ -919,7 +913,7 @@ network_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBool *custom = FALSE; if ((cdesc = get_counter_in_category (&predef_categories [CATEGORY_NETWORK], counter))) { - instance_name = mono_string_to_utf8 (instance); + instance_name = g_strdup (instance); narg = g_new0 (NetworkVtableArg, 1); narg->id = cdesc->id; narg->name = instance_name; @@ -971,7 +965,7 @@ get_process_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSamp } static void* -process_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoolean *custom) +process_get_impl (MonoString* counter, const gchar* instance, int *type, MonoBoolean *custom) { int id = id_from_string (instance, TRUE) << 5; const CounterDesc *cdesc; @@ -1009,7 +1003,7 @@ mono_mem_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample } static void* -mono_mem_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoolean *custom) +mono_mem_get_impl (MonoString* counter, const gchar* instance, int *type, MonoBoolean *custom) { const CounterDesc *cdesc; *custom = FALSE; @@ -1041,15 +1035,13 @@ predef_readonly_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounter } static ImplVtable* -predef_vtable (void *arg, MonoString *instance) +predef_vtable (void *arg, const gchar *pids) { MonoSharedArea *area; PredefVtable *vtable; - char *pids = mono_string_to_utf8 (instance); int pid; pid = atoi (pids); - g_free (pids); area = load_sarea_for_pid (pid); if (!area) return NULL; @@ -1082,52 +1074,52 @@ predef_writable_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounter case CATEGORY_EXC: switch (id) { case COUNTER_EXC_THROWN: - sample->rawValue = mono_perfcounters->exceptions_thrown; + sample->rawValue = InterlockedRead (&mono_perfcounters->exceptions_thrown); return TRUE; } break; case CATEGORY_ASPNET: switch (id) { case COUNTER_ASPNET_REQ_Q: - sample->rawValue = mono_perfcounters->aspnet_requests_queued; + sample->rawValue = InterlockedRead (&mono_perfcounters->aspnet_requests_queued); return TRUE; case COUNTER_ASPNET_REQ_TOTAL: - sample->rawValue = mono_perfcounters->aspnet_requests; + sample->rawValue = InterlockedRead (&mono_perfcounters->aspnet_requests); return TRUE; } break; case CATEGORY_THREADPOOL: switch (id) { case COUNTER_THREADPOOL_WORKITEMS: - sample->rawValue = mono_perfcounters->threadpool_workitems; + sample->rawValue = InterlockedRead64 (&mono_perfcounters->threadpool_workitems); return TRUE; case COUNTER_THREADPOOL_IOWORKITEMS: - sample->rawValue = mono_perfcounters->threadpool_ioworkitems; + sample->rawValue = InterlockedRead64 (&mono_perfcounters->threadpool_ioworkitems); return TRUE; case COUNTER_THREADPOOL_THREADS: - sample->rawValue = mono_perfcounters->threadpool_threads; + sample->rawValue = InterlockedRead (&mono_perfcounters->threadpool_threads); return TRUE; case COUNTER_THREADPOOL_IOTHREADS: - sample->rawValue = mono_perfcounters->threadpool_iothreads; + sample->rawValue = InterlockedRead (&mono_perfcounters->threadpool_iothreads); return TRUE; } break; case CATEGORY_JIT: switch (id) { case COUNTER_JIT_BYTES: - sample->rawValue = mono_perfcounters->jit_bytes; + sample->rawValue = InterlockedRead (&mono_perfcounters->jit_bytes); return TRUE; case COUNTER_JIT_METHODS: - sample->rawValue = mono_perfcounters->jit_methods; + sample->rawValue = InterlockedRead (&mono_perfcounters->jit_methods); return TRUE; case COUNTER_JIT_TIME: - sample->rawValue = mono_perfcounters->jit_time; + sample->rawValue = InterlockedRead (&mono_perfcounters->jit_time); return TRUE; case COUNTER_JIT_BYTES_PSEC: - sample->rawValue = mono_perfcounters->jit_bytes; + sample->rawValue = InterlockedRead (&mono_perfcounters->jit_bytes); return TRUE; case COUNTER_JIT_FAILURES: - sample->rawValue = mono_perfcounters->jit_failures; + sample->rawValue = InterlockedRead (&mono_perfcounters->jit_failures); return TRUE; } break; @@ -1138,7 +1130,7 @@ predef_writable_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounter static gint64 predef_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value) { - guint32 *volatile ptr = NULL; + gint32 *volatile ptr = NULL; gint64 *volatile ptr64 = NULL; int cat_id = GPOINTER_TO_INT (vtable->arg); int id = cat_id >> 16; @@ -1152,8 +1144,8 @@ predef_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value) break; case CATEGORY_THREADPOOL: switch (id) { - case COUNTER_THREADPOOL_WORKITEMS: ptr64 = (gint64 *) &mono_perfcounters->threadpool_workitems; break; - case COUNTER_THREADPOOL_IOWORKITEMS: ptr64 = (gint64 *) &mono_perfcounters->threadpool_ioworkitems; break; + case COUNTER_THREADPOOL_WORKITEMS: ptr64 = &mono_perfcounters->threadpool_workitems; break; + case COUNTER_THREADPOOL_IOWORKITEMS: ptr64 = &mono_perfcounters->threadpool_ioworkitems; break; case COUNTER_THREADPOOL_THREADS: ptr = &mono_perfcounters->threadpool_threads; break; case COUNTER_THREADPOOL_IOTHREADS: ptr = &mono_perfcounters->threadpool_iothreads; break; } @@ -1162,29 +1154,23 @@ predef_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value) if (ptr) { if (do_incr) { if (value == 1) - return InterlockedIncrement ((gint32 *) ptr); /* FIXME: sign */ + return InterlockedIncrement (ptr); if (value == -1) - return InterlockedDecrement ((gint32 *) ptr); /* FIXME: sign */ + return InterlockedDecrement (ptr); - *ptr += value; - return *ptr; + return InterlockedAdd(ptr, value); } /* this can be non-atomic */ *ptr = value; return value; } else if (ptr64) { if (do_incr) { - /* FIXME: we need to do this atomically */ - /* No InterlockedIncrement64() yet */ - /* if (value == 1) - return InterlockedIncrement64 (ptr); + return UnlockedIncrement64 (ptr64); /* FIXME: use InterlockedIncrement64 () */ if (value == -1) - return InterlockedDecrement64 (ptr); - */ + return UnlockedDecrement64 (ptr64); /* FIXME: use InterlockedDecrement64 () */ - *ptr64 += value; - return *ptr64; + return UnlockedAdd64 (ptr64, value); /* FIXME: use InterlockedAdd64 () */ } /* this can be non-atomic */ *ptr64 = value; @@ -1194,13 +1180,13 @@ predef_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value) } static void* -predef_writable_get_impl (int cat, MonoString* counter, MonoString* instance, int *type, MonoBoolean *custom) +predef_writable_get_impl (int cat, MonoString* counter, const gchar *instance, int *type, MonoBoolean *custom) { const CounterDesc *cdesc; *custom = TRUE; if ((cdesc = get_counter_in_category (&predef_categories [cat], counter))) { *type = cdesc->type; - if (instance == NULL || mono_string_compare_ascii (instance, "") == 0) + if (instance == NULL || strcmp (instance, "") == 0) return create_vtable (GINT_TO_POINTER ((cdesc->id << 16) | cat), predef_writable_counter, predef_writable_update); else return predef_vtable (GINT_TO_POINTER ((cdesc->id << 16) | cat), instance); @@ -1298,17 +1284,19 @@ custom_get_value_address (SharedCounter *scounter, SharedInstance* sinst) } static void* -custom_get_impl (SharedCategory *cat, MonoString* counter, MonoString* instance, int *type) +custom_get_impl (SharedCategory *cat, MonoString *counter, MonoString* instance, int *type, MonoError *error) { SharedCounter *scounter; SharedInstance* inst; char *name; + error_init (error); scounter = find_custom_counter (cat, counter); if (!scounter) return NULL; + name = mono_string_to_utf8_checked (counter, error); + return_val_if_nok (error, NULL); *type = simple_type_to_type [scounter->type]; - name = mono_string_to_utf8 (counter); inst = custom_get_instance (cat, scounter, name); g_free (name); if (!inst) @@ -1331,7 +1319,9 @@ void* mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString* instance, MonoString* machine, int *type, MonoBoolean *custom) { + MonoError error; const CategoryDesc *cdesc; + void *result = NULL; /* no support for counters on other machines */ if (mono_string_compare_ascii (machine, ".")) return NULL; @@ -1341,17 +1331,27 @@ mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString if (!scat) return NULL; *custom = TRUE; - return custom_get_impl (scat, counter, instance, type); + result = custom_get_impl (scat, counter, instance, type, &error); + if (mono_error_set_pending_exception (&error)) + return NULL; + return result; } + gchar *c_instance = mono_string_to_utf8_checked (instance, &error); + if (mono_error_set_pending_exception (&error)) + return NULL; switch (cdesc->id) { case CATEGORY_CPU: - return cpu_get_impl (counter, instance, type, custom); + result = cpu_get_impl (counter, c_instance, type, custom); + break; case CATEGORY_PROC: - return process_get_impl (counter, instance, type, custom); + result = process_get_impl (counter, c_instance, type, custom); + break; case CATEGORY_MONO_MEM: - return mono_mem_get_impl (counter, instance, type, custom); + result = mono_mem_get_impl (counter, c_instance, type, custom); + break; case CATEGORY_NETWORK: - return network_get_impl (counter, instance, type, custom); + result = network_get_impl (counter, c_instance, type, custom); + break; case CATEGORY_JIT: case CATEGORY_EXC: case CATEGORY_GC: @@ -1362,9 +1362,11 @@ mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString case CATEGORY_SECURITY: case CATEGORY_ASPNET: case CATEGORY_THREADPOOL: - return predef_writable_get_impl (cdesc->id, counter, instance, type, custom); + result = predef_writable_get_impl (cdesc->id, counter, c_instance, type, custom); + break; } - return NULL; + g_free (c_instance); + return result; } MonoBoolean @@ -1416,10 +1418,14 @@ mono_perfcounter_category_del (MonoString *name) return TRUE; } +/* this is an icall */ MonoString* mono_perfcounter_category_help (MonoString *category, MonoString *machine) { + MonoError error; + MonoString *result = NULL; const CategoryDesc *cdesc; + error_init (&error); /* no support for counters on other machines */ if (mono_string_compare_ascii (machine, ".")) return NULL; @@ -1428,9 +1434,15 @@ mono_perfcounter_category_help (MonoString *category, MonoString *machine) SharedCategory *scat = find_custom_category (category); if (!scat) return NULL; - return mono_string_new (mono_domain_get (), custom_category_help (scat)); + result = mono_string_new_checked (mono_domain_get (), custom_category_help (scat), &error); + if (mono_error_set_pending_exception (&error)) + return NULL; + return result; } - return mono_string_new (mono_domain_get (), cdesc->help); + result = mono_string_new_checked (mono_domain_get (), cdesc->help, &error); + if (mono_error_set_pending_exception (&error)) + return NULL; + return result; } /* @@ -1490,7 +1502,6 @@ mono_perfcounter_create (MonoString *category, MonoString *help, int type, MonoA SharedCategory *cat; /* FIXME: ensure there isn't a category created already */ - mono_error_init (&error); name = mono_string_to_utf8_checked (category, &error); if (!mono_error_ok (&error)) goto failure; @@ -1563,6 +1574,7 @@ failure: int mono_perfcounter_instance_exists (MonoString *instance, MonoString *category, MonoString *machine) { + MonoError error; const CategoryDesc *cdesc; SharedInstance *sinst; char *name; @@ -1576,7 +1588,9 @@ mono_perfcounter_instance_exists (MonoString *instance, MonoString *category, Mo scat = find_custom_category (category); if (!scat) return FALSE; - name = mono_string_to_utf8 (instance); + name = mono_string_to_utf8_checked (instance, &error); + if (mono_error_set_pending_exception (&error)) + return FALSE; sinst = find_custom_instance (scat, name); g_free (name); if (sinst) @@ -1587,6 +1601,7 @@ mono_perfcounter_instance_exists (MonoString *instance, MonoString *category, Mo return FALSE; } +/* this is an icall */ MonoArray* mono_perfcounter_category_names (MonoString *machine) { @@ -1611,15 +1626,23 @@ mono_perfcounter_category_names (MonoString *machine) for (i = 0; i < NUM_CATEGORIES; ++i) { const CategoryDesc *cdesc = &predef_categories [i]; - mono_array_setref (res, i, mono_string_new (domain, cdesc->name)); + MonoString *name = mono_string_new_checked (domain, cdesc->name, &error); + if (!is_ok (&error)) + goto leave; + mono_array_setref (res, i, name); } for (tmp = custom_categories; tmp; tmp = tmp->next) { SharedCategory *scat = (SharedCategory *)tmp->data; - mono_array_setref (res, i, mono_string_new (domain, scat->name)); + MonoString *name = mono_string_new_checked (domain, scat->name, &error); + if (!is_ok (&error)) + goto leave; + mono_array_setref (res, i, name); i++; } +leave: perfctr_unlock (); g_slist_free (custom_categories); + mono_error_set_pending_exception (&error); return res; } @@ -1645,7 +1668,10 @@ mono_perfcounter_counter_names (MonoString *category, MonoString *machine) return NULL; for (i = cdesc->first_counter; i < cdesc [1].first_counter; ++i) { const CounterDesc *desc = &predef_counters [i]; - mono_array_setref (res, i - cdesc->first_counter, mono_string_new (domain, desc->name)); + MonoString *name = mono_string_new_checked (domain, desc->name, &error); + if (mono_error_set_pending_exception (&error)) + return NULL; + mono_array_setref (res, i - cdesc->first_counter, name); } return res; } @@ -1661,16 +1687,18 @@ mono_perfcounter_counter_names (MonoString *category, MonoString *machine) } for (i = 0; i < scat->num_counters; ++i) { - mono_array_setref (res, i, mono_string_new (domain, p + 1)); + MonoString *str = mono_string_new_checked (domain, p + 1, &error); + if (!is_ok (&error)) + goto leave; + mono_array_setref (res, i, str); p += 2; /* skip counter type */ p += strlen (p) + 1; /* skip counter name */ p += strlen (p) + 1; /* skip counter help */ } - perfctr_unlock (); - return res; - } + } else + res = mono_array_new_checked (domain, mono_get_string_class (), 0, &error); +leave: perfctr_unlock (); - res = mono_array_new_checked (domain, mono_get_string_class (), 0, &error); mono_error_set_pending_exception (&error); return res; } @@ -1680,7 +1708,7 @@ get_string_array (void **array, int count, gboolean is_process, MonoError *error { int i; MonoDomain *domain = mono_domain_get (); - mono_error_init (error); + error_init (error); MonoArray * res = mono_array_new_checked (mono_domain_get (), mono_get_string_class (), count, error); return_val_if_nok (error, NULL); for (i = 0; i < count; ++i) { @@ -1693,9 +1721,11 @@ get_string_array (void **array, int count, gboolean is_process, MonoError *error sprintf (buf, "%d", GPOINTER_TO_INT (array [i])); p = buf; } - mono_array_setref (res, i, mono_string_new (domain, p)); + MonoString *str = mono_string_new_checked (domain, p, error); if (p != buf) g_free (p); + return_val_if_nok (error, NULL); + mono_array_setref (res, i, str); } return res; } @@ -1705,12 +1735,14 @@ get_string_array_of_strings (void **array, int count, MonoError *error) { int i; MonoDomain *domain = mono_domain_get (); - mono_error_init (error); + error_init (error); MonoArray * res = mono_array_new_checked (mono_domain_get (), mono_get_string_class (), count, error); return_val_if_nok (error, NULL); for (i = 0; i < count; ++i) { char* p = (char *)array[i]; - mono_array_setref (res, i, mono_string_new (domain, p)); + MonoString *str = mono_string_new_checked (domain, p, error); + return_val_if_nok (error, NULL); + mono_array_setref (res, i, str); } return res; @@ -1723,7 +1755,7 @@ get_mono_instances (MonoError *error) int res; void **buf = NULL; MonoArray *array; - mono_error_init (error); + error_init (error); do { count *= 2; g_free (buf); @@ -1741,14 +1773,16 @@ get_cpu_instances (MonoError *error) void **buf = NULL; int i, count; MonoArray *array; - mono_error_init (error); + error_init (error); count = mono_cpu_count () + 1; /* +1 for "_Total" */ buf = g_new (void*, count); for (i = 0; i < count; ++i) buf [i] = GINT_TO_POINTER (i - 1); /* -1 => _Total */ array = get_string_array (buf, count, FALSE, error); g_free (buf); - mono_array_setref (array, 0, mono_string_new (mono_domain_get (), "_Total")); + MonoString *total = mono_string_new_checked (mono_domain_get (), "_Total", error); + return_val_if_nok (error, NULL); + mono_array_setref (array, 0, total); return array; } @@ -1758,7 +1792,7 @@ get_processes_instances (MonoError *error) MonoArray *array; int count = 0; void **buf = mono_process_list (&count); - mono_error_init (error); + error_init (error); if (!buf) return get_string_array (NULL, 0, FALSE, error); array = get_string_array (buf, count, TRUE, error); @@ -1771,7 +1805,7 @@ get_networkinterface_instances (MonoError *error) { MonoArray *array; int count = 0; - mono_error_init (error); + error_init (error); void **buf = mono_networkinterface_list (&count); if (!buf) return get_string_array_of_strings (NULL, 0, error); @@ -1784,7 +1818,7 @@ static MonoArray* get_custom_instances (MonoString *category, MonoError *error) { SharedCategory *scat; - mono_error_init (error); + error_init (error); scat = find_custom_category (category); if (scat) { GSList *list = get_custom_instances_list (scat); @@ -1797,7 +1831,12 @@ get_custom_instances (MonoString *category, MonoError *error) } for (tmp = list; tmp; tmp = tmp->next) { SharedInstance *inst = (SharedInstance *)tmp->data; - mono_array_setref (array, i, mono_string_new (mono_domain_get (), inst->instance_name)); + MonoString *str = mono_string_new_checked (mono_domain_get (), inst->instance_name, error); + if (!is_ok (error)) { + g_slist_free (list); + return NULL; + } + mono_array_setref (array, i, str); i++; } g_slist_free (list);