X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmono-perfcounters.c;h=ec72516a2b394f8fc4db25163ad9a6354000bbf7;hb=0585e7cb9a7afdd17f3c6afdc903fd06e3e7624e;hp=44b8563b0069cce7d32c30f25f9c49a433734c17;hpb=6f5a0b555436eba699f9dd2659471044097b951b;p=mono.git diff --git a/mono/metadata/mono-perfcounters.c b/mono/metadata/mono-perfcounters.c index 44b8563b006..ec72516a2b3 100644 --- a/mono/metadata/mono-perfcounters.c +++ b/mono/metadata/mono-perfcounters.c @@ -5,23 +5,40 @@ * * Author: Paolo Molaro (lupus@ximian.com) * - * (C) 2008 Novell, Inc + * Copyright 2008-2009 Novell, Inc (http://www.novell.com) + * 2011 Xamarin, Inc */ #include "config.h" #include #include #include +#ifdef HAVE_UNISTD_H +#include +#endif +#if defined (__OpenBSD__) +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif #ifdef HAVE_SYS_TIME_H #include #endif +#if defined (__NetBSD__) || defined (__APPLE__) +#include +#endif #include "metadata/mono-perfcounters.h" #include "metadata/appdomain.h" +#include "metadata/object-internals.h" /* for mono_stats */ #include "metadata/class-internals.h" #include "utils/mono-time.h" #include "utils/mono-mmap.h" #include "utils/mono-proclib.h" +#include "utils/mono-networkinterfaces.h" +#include "utils/mono-error-internals.h" +#include "utils/atomic.h" #include /* map of CounterSample.cs */ @@ -36,6 +53,7 @@ struct _MonoCounterSample { int counterType; }; +#ifndef DISABLE_PERFCOUNTERS /* map of PerformanceCounterType.cs */ enum { NumberOfItemsHEX32=0x00000000, @@ -98,6 +116,7 @@ enum { ThreadInstance, CPUInstance, MonoInstance, + NetworkInterfaceInstance, CustomInstance }; @@ -211,11 +230,12 @@ typedef struct { SharedHeader header; unsigned int category_offset; /* variable length data follows */ - char name [1]; + char instance_name [1]; } SharedInstance; typedef struct { unsigned char type; + guint8 seq_num; /* variable length data follows */ char name [1]; } SharedCounter; @@ -281,12 +301,23 @@ struct _ImplVtable { CleanupFunc cleanup; }; +typedef struct { + int id; + char *name; +} NetworkVtableArg; + typedef struct { ImplVtable vtable; MonoPerfCounters *counters; int pid; } PredefVtable; +typedef struct { + ImplVtable vtable; + SharedInstance *instance_desc; + SharedCounter *counter_desc; +} CustomVTable; + static ImplVtable* create_vtable (void *arg, SampleFunc sample, UpdateFunc update) { @@ -335,27 +366,89 @@ load_sarea_for_pid (int pid) } static void -predef_cleanup (ImplVtable *vtable) +unref_pid_unlocked (int pid) { - PredefVtable *vt = (PredefVtable*)vtable; ExternalSArea *data; - perfctr_lock (); - if (!pid_to_shared_area) { - perfctr_unlock (); - return; - } - data = g_hash_table_lookup (pid_to_shared_area, GINT_TO_POINTER (vt->pid)); + data = g_hash_table_lookup (pid_to_shared_area, GINT_TO_POINTER (pid)); if (data) { data->refcount--; if (!data->refcount) { - g_hash_table_remove (pid_to_shared_area, GINT_TO_POINTER (vt->pid)); + g_hash_table_remove (pid_to_shared_area, GINT_TO_POINTER (pid)); mono_shared_area_unload (data->sarea); g_free (data); } } +} + +static void +predef_cleanup (ImplVtable *vtable) +{ + PredefVtable *vt = (PredefVtable*)vtable; + /* ExternalSArea *data; */ + + perfctr_lock (); + if (!pid_to_shared_area) { + perfctr_unlock (); + return; + } + unref_pid_unlocked (vt->pid); perfctr_unlock (); } +static guint64 +mono_determine_physical_ram_size (void) +{ +#if defined (TARGET_WIN32) + MEMORYSTATUSEX memstat; + + memstat.dwLength = sizeof (memstat); + GlobalMemoryStatusEx (&memstat); + return (guint64)memstat.ullTotalPhys; +#elif defined (__NetBSD__) || defined (__APPLE__) +#ifdef __NetBSD__ + unsigned long value; +#else + guint64 value; +#endif + int mib[2] = { + CTL_HW, +#ifdef __NetBSD__ + HW_PHYSMEM +#else + HW_MEMSIZE +#endif + }; + size_t size_sys = sizeof (value); + + sysctl (mib, 2, &value, &size_sys, NULL, 0); + if (value == 0) + return 134217728; + + return (guint64)value; +#elif defined (HAVE_SYSCONF) + guint64 page_size = 0, num_pages = 0; + + /* sysconf works on most *NIX operating systems, if your system doesn't have it or if it + * reports invalid values, please add your OS specific code below. */ +#ifdef _SC_PAGESIZE + page_size = (guint64)sysconf (_SC_PAGESIZE); +#endif + +#ifdef _SC_PHYS_PAGES + num_pages = (guint64)sysconf (_SC_PHYS_PAGES); +#endif + + if (!page_size || !num_pages) { + g_warning ("Your operating system's sysconf (3) function doesn't correctly report physical memory size!"); + return 134217728; + } + + return page_size * num_pages; +#else + return 134217728; +#endif +} + void mono_perfcounters_init (void) { @@ -391,8 +484,8 @@ shared_data_find_room (int size) unsigned char *p = (unsigned char *)shared_area + shared_area->data_start; unsigned char *end = (unsigned char *)shared_area + shared_area->size; - size += 3; - size &= ~3; + size += 7; + size &= ~7; while (p < end) { unsigned short *next; if (*p == FTYPE_END) { @@ -417,11 +510,8 @@ shared_data_find_room (int size) typedef gboolean (*SharedFunc) (SharedHeader *header, void *data); static void -foreach_shared_item (SharedFunc func, void *data) +foreach_shared_item_in_area (unsigned char *p, unsigned char *end, SharedFunc func, void *data) { - unsigned char *p = (unsigned char *)shared_area + shared_area->data_start; - unsigned char *end = (unsigned char *)shared_area + shared_area->size; - while (p < end) { unsigned short *next; if (p + 4 > end) @@ -435,6 +525,15 @@ foreach_shared_item (SharedFunc func, void *data) } } +static void +foreach_shared_item (SharedFunc func, void *data) +{ + unsigned char *p = (unsigned char *)shared_area + shared_area->data_start; + unsigned char *end = (unsigned char *)shared_area + shared_area->size; + + foreach_shared_item_in_area (p, end, func, data); +} + static int mono_string_compare_ascii (MonoString *str, const char *ascii_str) { @@ -517,6 +616,60 @@ find_custom_counter (SharedCategory* cat, MonoString *name) return NULL; } +typedef struct { + unsigned int cat_offset; + SharedCategory* cat; + MonoString *instance; + SharedInstance* result; + GSList *list; +} InstanceSearch; + +static gboolean +instance_search (SharedHeader *header, void *data) +{ + InstanceSearch *search = data; + if (header->ftype == FTYPE_INSTANCE) { + SharedInstance *ins = (SharedInstance*)header; + if (search->cat_offset == ins->category_offset) { + if (search->instance) { + if (mono_string_compare_ascii (search->instance, ins->instance_name) == 0) { + search->result = ins; + return FALSE; + } + } else { + search->list = g_slist_prepend (search->list, ins); + } + } + } + return TRUE; +} + +static SharedInstance* +find_custom_instance (SharedCategory* cat, MonoString *instance) +{ + InstanceSearch search; + search.cat_offset = (char*)cat - (char*)shared_area; + search.cat = cat; + search.instance = instance; + search.list = NULL; + search.result = NULL; + foreach_shared_item (instance_search, &search); + return search.result; +} + +static GSList* +get_custom_instances_list (SharedCategory* cat) +{ + InstanceSearch search; + search.cat_offset = (char*)cat - (char*)shared_area; + search.cat = cat; + search.instance = NULL; + search.list = NULL; + search.result = NULL; + foreach_shared_item (instance_search, &search); + return search.list; +} + static char* custom_category_help (SharedCategory* cat) { @@ -610,6 +763,74 @@ cpu_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoolean return NULL; } +static MonoBoolean +get_network_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *sample) +{ + MonoNetworkError error = MONO_NETWORK_ERROR_OTHER; + NetworkVtableArg *narg = (NetworkVtableArg*) vtable->arg; + if (!only_value) { + fill_sample (sample); + } + + sample->counterType = predef_counters [predef_categories [CATEGORY_NETWORK].first_counter + narg->id].type; + switch (narg->id) { + case COUNTER_NETWORK_BYTESRECSEC: + sample->rawValue = mono_network_get_data (narg->name, MONO_NETWORK_BYTESREC, &error); + break; + case COUNTER_NETWORK_BYTESSENTSEC: + sample->rawValue = mono_network_get_data (narg->name, MONO_NETWORK_BYTESSENT, &error); + break; + case COUNTER_NETWORK_BYTESTOTALSEC: + sample->rawValue = mono_network_get_data (narg->name, MONO_NETWORK_BYTESTOTAL, &error); + break; + } + + if (error == MONO_NETWORK_ERROR_NONE) + return TRUE; + else + return FALSE; +} + +static void +network_cleanup (ImplVtable *vtable) +{ + NetworkVtableArg *narg; + + if (vtable == NULL) + return; + + narg = vtable->arg; + if (narg == NULL) + return; + + g_free (narg->name); + narg->name = NULL; + g_free (narg); + vtable->arg = NULL; +} + +static void* +network_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoolean *custom) +{ + const CounterDesc *cdesc; + NetworkVtableArg *narg; + ImplVtable *vtable; + char *instance_name; + + *custom = FALSE; + if ((cdesc = get_counter_in_category (&predef_categories [CATEGORY_NETWORK], counter))) { + instance_name = mono_string_to_utf8 (instance); + narg = g_new0 (NetworkVtableArg, 1); + narg->id = cdesc->id; + narg->name = instance_name; + *type = cdesc->type; + vtable = create_vtable (narg, get_network_counter, NULL); + vtable->cleanup = network_cleanup; + return vtable; + } + return NULL; +} + static MonoBoolean get_process_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *sample) { @@ -677,6 +898,9 @@ mono_mem_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample case COUNTER_MEM_NUM_OBJECTS: sample->rawValue = mono_stats.new_object_count; return TRUE; + case COUNTER_MEM_PHYS_TOTAL: + sample->rawValue = mono_determine_physical_ram_size ();; + return TRUE; } return FALSE; } @@ -688,7 +912,7 @@ mono_mem_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoo *custom = FALSE; if ((cdesc = get_counter_in_category (&predef_categories [CATEGORY_MONO_MEM], counter))) { *type = cdesc->type; - return create_vtable (GINT_TO_POINTER (cdesc->id), mono_mem_counter, NULL); + return create_vtable (GINT_TO_POINTER ((gint) cdesc->id), mono_mem_counter, NULL); } return NULL; } @@ -752,11 +976,56 @@ predef_writable_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounter } sample->counterType = predef_counters [predef_categories [cat_id].first_counter + id].type; switch (cat_id) { + case CATEGORY_EXC: + switch (id) { + case COUNTER_EXC_THROWN: + sample->rawValue = mono_perfcounters->exceptions_thrown; + return TRUE; + } + break; case CATEGORY_ASPNET: switch (id) { case COUNTER_ASPNET_REQ_Q: sample->rawValue = mono_perfcounters->aspnet_requests_queued; return TRUE; + case COUNTER_ASPNET_REQ_TOTAL: + sample->rawValue = mono_perfcounters->aspnet_requests; + return TRUE; + } + break; + case CATEGORY_THREADPOOL: + switch (id) { + case COUNTER_THREADPOOL_WORKITEMS: + sample->rawValue = mono_perfcounters->threadpool_workitems; + return TRUE; + case COUNTER_THREADPOOL_IOWORKITEMS: + sample->rawValue = mono_perfcounters->threadpool_ioworkitems; + return TRUE; + case COUNTER_THREADPOOL_THREADS: + sample->rawValue = mono_perfcounters->threadpool_threads; + return TRUE; + case COUNTER_THREADPOOL_IOTHREADS: + sample->rawValue = mono_perfcounters->threadpool_iothreads; + return TRUE; + } + break; + case CATEGORY_JIT: + switch (id) { + case COUNTER_JIT_BYTES: + sample->rawValue = mono_perfcounters->jit_bytes; + return TRUE; + case COUNTER_JIT_METHODS: + sample->rawValue = mono_perfcounters->jit_methods; + return TRUE; + case COUNTER_JIT_TIME: + sample->rawValue = mono_perfcounters->jit_time; + return TRUE; + case COUNTER_JIT_BYTES_PSEC: + sample->rawValue = mono_perfcounters->jit_bytes; + return TRUE; + case COUNTER_JIT_FAILURES: + sample->rawValue = mono_perfcounters->jit_failures; + return TRUE; } break; } @@ -766,7 +1035,8 @@ predef_writable_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounter static gint64 predef_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value) { - guint32 *ptr = NULL; + guint32 *volatile ptr = NULL; + gint64 *volatile ptr64 = NULL; int cat_id = GPOINTER_TO_INT (vtable->arg); int id = cat_id >> 16; cat_id &= 0xffff; @@ -774,18 +1044,48 @@ predef_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value) case CATEGORY_ASPNET: switch (id) { case COUNTER_ASPNET_REQ_Q: ptr = &mono_perfcounters->aspnet_requests_queued; break; + case COUNTER_ASPNET_REQ_TOTAL: ptr = &mono_perfcounters->aspnet_requests; break; + } + 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_THREADS: ptr = &mono_perfcounters->threadpool_threads; break; + case COUNTER_THREADPOOL_IOTHREADS: ptr = &mono_perfcounters->threadpool_iothreads; break; } break; } if (ptr) { if (do_incr) { - /* FIXME: we need to do this atomically */ + if (value == 1) + return InterlockedIncrement ((gint32 *) ptr); /* FIXME: sign */ + if (value == -1) + return InterlockedDecrement ((gint32 *) ptr); /* FIXME: sign */ + *ptr += value; return *ptr; } /* 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); + if (value == -1) + return InterlockedDecrement64 (ptr); + */ + + *ptr64 += value; + return *ptr64; + } + /* this can be non-atomic */ + *ptr64 = value; + return value; } return 0; } @@ -808,22 +1108,24 @@ predef_writable_get_impl (int cat, MonoString* counter, MonoString* instance, in static MonoBoolean custom_writable_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *sample) { - SharedCounter *scounter = vtable->arg; + CustomVTable *counter_data = (CustomVTable *)vtable; if (!only_value) { fill_sample (sample); sample->baseValue = 1; } - sample->counterType = simple_type_to_type [scounter->type]; - /* FIXME */ - sample->rawValue = 0; + sample->counterType = simple_type_to_type [counter_data->counter_desc->type]; + if (!vtable->arg) + sample->rawValue = 0; + else + sample->rawValue = *(guint64*)vtable->arg; return TRUE; } static gint64 custom_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value) { - /* FIXME */ - guint32 *ptr = NULL; + /* FIXME: check writability */ + guint64 *ptr = vtable->arg; if (ptr) { if (do_incr) { /* FIXME: we need to do this atomically */ @@ -837,17 +1139,78 @@ custom_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value) return 0; } +static SharedInstance* +custom_get_instance (SharedCategory *cat, SharedCounter *scounter, MonoString* instance) +{ + SharedInstance* inst; + unsigned char *ptr; + char *p; + int size, data_offset; + char *name; + inst = find_custom_instance (cat, instance); + if (inst) + return inst; + name = mono_string_to_utf8 (instance); + size = sizeof (SharedInstance) + strlen (name); + size += 7; + size &= ~7; + data_offset = size; + size += (sizeof (guint64) * cat->num_counters); + perfctr_lock (); + ptr = shared_data_find_room (size); + if (!ptr) { + perfctr_unlock (); + g_free (name); + return NULL; + } + inst = (SharedInstance*)ptr; + inst->header.extra = 0; /* data_offset could overflow here, so we leave this field unused */ + inst->header.size = size; + inst->category_offset = (char*)cat - (char*)shared_area; + cat->num_instances++; + /* now copy the variable data */ + p = inst->instance_name; + strcpy (p, name); + p += strlen (name) + 1; + inst->header.ftype = FTYPE_INSTANCE; + perfctr_unlock (); + g_free (name); + + return inst; +} + +static ImplVtable* +custom_vtable (SharedCounter *scounter, SharedInstance* inst, char *data) +{ + CustomVTable* vtable; + vtable = g_new0 (CustomVTable, 1); + vtable->vtable.arg = data; + vtable->vtable.sample = custom_writable_counter; + vtable->vtable.update = custom_writable_update; + vtable->instance_desc = inst; + vtable->counter_desc = scounter; + + return (ImplVtable*)vtable; +} + static void* custom_get_impl (SharedCategory *cat, MonoString* counter, MonoString* instance, int *type) { SharedCounter *scounter; + SharedInstance* inst; + int size; scounter = find_custom_counter (cat, counter); if (!scounter) return NULL; *type = simple_type_to_type [scounter->type]; - /* FIXME: use instance */ - return create_vtable (scounter, custom_writable_counter, custom_writable_update); + inst = custom_get_instance (cat, scounter, instance); + if (!inst) + return NULL; + size = sizeof (SharedInstance) + strlen (inst->instance_name); + size += 7; + size &= ~7; + return custom_vtable (scounter, inst, (char*)inst + size + scounter->seq_num * sizeof (guint64)); } static const CategoryDesc* @@ -884,6 +1247,8 @@ mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString return process_get_impl (counter, instance, type, custom); case CATEGORY_MONO_MEM: return mono_mem_get_impl (counter, instance, type, custom); + case CATEGORY_NETWORK: + return network_get_impl (counter, instance, type, custom); case CATEGORY_JIT: case CATEGORY_EXC: case CATEGORY_GC: @@ -893,6 +1258,7 @@ mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString case CATEGORY_INTEROP: case CATEGORY_SECURITY: case CATEGORY_ASPNET: + case CATEGORY_THREADPOOL: return predef_writable_get_impl (cdesc->id, counter, instance, type, custom); } return NULL; @@ -1009,31 +1375,46 @@ typedef struct { MonoBoolean mono_perfcounter_create (MonoString *category, MonoString *help, int type, MonoArray *items) { + MonoError error; int result = FALSE; int i, size; int num_counters = mono_array_length (items); int counters_data_size; - char *name = mono_string_to_utf8 (category); - char *chelp = mono_string_to_utf8 (help); - char **counter_info; + char *name = NULL; + char *chelp = NULL; + char **counter_info = NULL; unsigned char *ptr; char *p; 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; + chelp = mono_string_to_utf8_checked (help, &error); + if (!mono_error_ok (&error)) + goto failure; counter_info = g_new0 (char*, num_counters * 2); /* calculate the size we need structure size + name/help + 2 0 string terminators */ size = G_STRUCT_OFFSET (SharedCategory, name) + strlen (name) + strlen (chelp) + 2; for (i = 0; i < num_counters; ++i) { CounterCreationData *data = mono_array_get (items, CounterCreationData*, i); - counter_info [i * 2] = mono_string_to_utf8 (data->name); - counter_info [i * 2 + 1] = mono_string_to_utf8 (data->help); - size += 3; /* type and two 0 string terminators */ + counter_info [i * 2] = mono_string_to_utf8_checked (data->name, &error); + if (!mono_error_ok (&error)) + goto failure; + counter_info [i * 2 + 1] = mono_string_to_utf8_checked (data->help, &error); + if (!mono_error_ok (&error)) + goto failure; + size += sizeof (SharedCounter) + 1; /* 1 is for the help 0 terminator */ } for (i = 0; i < num_counters * 2; ++i) { if (!counter_info [i]) goto failure; - size += strlen (counter_info [i]); + size += strlen (counter_info [i]) + 1; } + size += 7; + size &= ~7; counters_data_size = num_counters * 8; /* optimize for size later */ if (size > 65535) goto failure; @@ -1056,7 +1437,9 @@ mono_perfcounter_create (MonoString *category, MonoString *help, int type, MonoA p += strlen (chelp) + 1; for (i = 0; i < num_counters; ++i) { CounterCreationData *data = mono_array_get (items, CounterCreationData*, i); + /* emit the SharedCounter structures */ *p++ = perfctr_type_compress (data->type); + *p++ = i; strcpy (p, counter_info [i * 2]); p += strlen (counter_info [i * 2]) + 1; strcpy (p, counter_info [i * 2 + 1]); @@ -1067,12 +1450,15 @@ mono_perfcounter_create (MonoString *category, MonoString *help, int type, MonoA perfctr_unlock (); result = TRUE; failure: - for (i = 0; i < num_counters * 2; ++i) { - g_free (counter_info [i]); + if (counter_info) { + for (i = 0; i < num_counters * 2; ++i) { + g_free (counter_info [i]); + } + g_free (counter_info); } - g_free (counter_info); g_free (name); g_free (chelp); + mono_error_cleanup (&error); return result; } @@ -1081,11 +1467,20 @@ mono_perfcounter_instance_exists (MonoString *instance, MonoString *category, Mo { const CategoryDesc *cdesc; /* no support for counters on other machines */ + /*FIXME: machine appears to be wrong if (mono_string_compare_ascii (machine, ".")) - return FALSE; + return FALSE;*/ cdesc = find_category (category); - if (!cdesc) - return FALSE; + if (!cdesc) { + SharedCategory *scat; + scat = find_custom_category (category); + if (!scat) + return FALSE; + if (find_custom_instance (scat, instance)) + return TRUE; + } else { + /* FIXME: search instance */ + } return FALSE; } @@ -1177,6 +1572,20 @@ get_string_array (void **array, int count, gboolean is_process) return res; } +static MonoArray* +get_string_array_of_strings (void **array, int count) +{ + int i; + MonoDomain *domain = mono_domain_get (); + MonoArray * res = mono_array_new (mono_domain_get (), mono_get_string_class (), count); + for (i = 0; i < count; ++i) { + char* p = array[i]; + mono_array_setref (res, i, mono_string_new (domain, p)); + } + + return res; +} + static MonoArray* get_mono_instances (void) { @@ -1201,12 +1610,14 @@ get_cpu_instances (void) void **buf = NULL; int i, count; MonoArray *array; - count = mono_cpu_count (); + + 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); + buf [i] = GINT_TO_POINTER (i - 1); /* -1 => _Total */ array = get_string_array (buf, count, FALSE); g_free (buf); + mono_array_setref (array, 0, mono_string_new (mono_domain_get (), "_Total")); return array; } @@ -1223,6 +1634,40 @@ get_processes_instances (void) return array; } +static MonoArray* +get_networkinterface_instances (void) +{ + MonoArray *array; + int count = 0; + void **buf = mono_networkinterface_list (&count); + if (!buf) + return get_string_array_of_strings (NULL, 0); + array = get_string_array_of_strings (buf, count); + g_strfreev ((char **) buf); + return array; +} + +static MonoArray* +get_custom_instances (MonoString *category) +{ + SharedCategory *scat; + scat = find_custom_category (category); + if (scat) { + GSList *list = get_custom_instances_list (scat); + GSList *tmp; + int i = 0; + MonoArray *array = mono_array_new (mono_domain_get (), mono_get_string_class (), g_slist_length (list)); + for (tmp = list; tmp; tmp = tmp->next) { + SharedInstance *inst = tmp->data; + mono_array_setref (array, i, mono_string_new (mono_domain_get (), inst->instance_name)); + i++; + } + g_slist_free (list); + return array; + } + return mono_array_new (mono_domain_get (), mono_get_string_class (), 0); +} + MonoArray* mono_perfcounter_instance_names (MonoString *category, MonoString *machine) { @@ -1231,7 +1676,7 @@ mono_perfcounter_instance_names (MonoString *category, MonoString *machine) return mono_array_new (mono_domain_get (), mono_get_string_class (), 0); cat = find_category (category); if (!cat) - return mono_array_new (mono_domain_get (), mono_get_string_class (), 0); + return get_custom_instances (category); switch (cat->instance_type) { case MonoInstance: return get_mono_instances (); @@ -1239,10 +1684,84 @@ mono_perfcounter_instance_names (MonoString *category, MonoString *machine) return get_cpu_instances (); case ProcessInstance: return get_processes_instances (); - case CustomInstance: + case NetworkInterfaceInstance: + return get_networkinterface_instances (); case ThreadInstance: default: return mono_array_new (mono_domain_get (), mono_get_string_class (), 0); } } +#else +void* +mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString* instance, MonoString* machine, int *type, MonoBoolean *custom) +{ + g_assert_not_reached (); +} + +MonoBoolean +mono_perfcounter_get_sample (void *impl, MonoBoolean only_value, MonoCounterSample *sample) +{ + g_assert_not_reached (); +} + +gint64 +mono_perfcounter_update_value (void *impl, MonoBoolean do_incr, gint64 value) +{ + g_assert_not_reached (); +} + +void +mono_perfcounter_free_data (void *impl) +{ + g_assert_not_reached (); +} +/* Category icalls */ +MonoBoolean +mono_perfcounter_category_del (MonoString *name) +{ + g_assert_not_reached (); +} + +MonoString* +mono_perfcounter_category_help (MonoString *category, MonoString *machine) +{ + g_assert_not_reached (); +} + +MonoBoolean +mono_perfcounter_category_exists (MonoString *counter, MonoString *category, MonoString *machine) +{ + g_assert_not_reached (); +} + +MonoBoolean +mono_perfcounter_create (MonoString *category, MonoString *help, int type, MonoArray *items) +{ + g_assert_not_reached (); +} + +int +mono_perfcounter_instance_exists (MonoString *instance, MonoString *category, MonoString *machine) +{ + g_assert_not_reached (); +} + +MonoArray* +mono_perfcounter_category_names (MonoString *machine) +{ + g_assert_not_reached (); +} + +MonoArray* +mono_perfcounter_counter_names (MonoString *category, MonoString *machine) +{ + g_assert_not_reached (); +} + +MonoArray* +mono_perfcounter_instance_names (MonoString *category, MonoString *machine) +{ + g_assert_not_reached (); +} +#endif