4 * Performance counters support.
6 * Author: Paolo Molaro (lupus@ximian.com)
8 * Copyright 2008-2009 Novell, Inc (http://www.novell.com)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20 #if defined (__OpenBSD__)
21 #include <sys/param.h>
23 #ifdef HAVE_SYS_TYPES_H
24 #include <sys/types.h>
26 #ifdef HAVE_SYS_TIME_H
29 #if defined (__APPLE__)
30 #include <mach/message.h>
31 #include <mach/mach_host.h>
32 #include <mach/host_info.h>
33 #include <sys/sysctl.h>
35 #if defined (__NetBSD__)
36 #include <sys/param.h>
37 #include <sys/sysctl.h>
38 #include <sys/vmmeter.h>
40 #include "metadata/mono-perfcounters.h"
41 #include "metadata/appdomain.h"
42 #include "metadata/object-internals.h"
44 #include "metadata/class-internals.h"
45 #include "utils/mono-time.h"
46 #include "utils/mono-mmap.h"
47 #include "utils/mono-proclib.h"
48 #include "utils/mono-networkinterfaces.h"
49 #include "utils/mono-error-internals.h"
50 #include "utils/atomic.h"
52 /* map of CounterSample.cs */
53 struct _MonoCounterSample {
56 gint64 counterFrequency;
57 gint64 systemFrequency;
59 gint64 timeStamp100nSec;
60 gint64 counterTimeStamp;
64 #ifndef DISABLE_PERFCOUNTERS
65 /* map of PerformanceCounterType.cs */
67 NumberOfItemsHEX32=0x00000000,
68 NumberOfItemsHEX64=0x00000100,
69 NumberOfItems32=0x00010000,
70 NumberOfItems64=0x00010100,
71 CounterDelta32=0x00400400,
72 CounterDelta64=0x00400500,
73 SampleCounter=0x00410400,
74 CountPerTimeInterval32=0x00450400,
75 CountPerTimeInterval64=0x00450500,
76 RateOfCountsPerSecond32=0x10410400,
77 RateOfCountsPerSecond64=0x10410500,
78 RawFraction=0x20020400,
79 CounterTimer=0x20410500,
80 Timer100Ns=0x20510500,
81 SampleFraction=0x20C20400,
82 CounterTimerInverse=0x21410500,
83 Timer100NsInverse=0x21510500,
84 CounterMultiTimer=0x22410500,
85 CounterMultiTimer100Ns=0x22510500,
86 CounterMultiTimerInverse=0x23410500,
87 CounterMultiTimer100NsInverse=0x23510500,
88 AverageTimer32=0x30020400,
89 ElapsedTime=0x30240500,
90 AverageCount64=0x40020500,
91 SampleBase=0x40030401,
92 AverageBase=0x40030402,
94 CounterMultiBase=0x42030500
97 /* maps a small integer type to the counter types above */
99 simple_type_to_type [] = {
100 NumberOfItemsHEX32, NumberOfItemsHEX64,
101 NumberOfItems32, NumberOfItems64,
102 CounterDelta32, CounterDelta64,
103 SampleCounter, CountPerTimeInterval32,
104 CountPerTimeInterval64, RateOfCountsPerSecond32,
105 RateOfCountsPerSecond64, RawFraction,
106 CounterTimer, Timer100Ns,
107 SampleFraction, CounterTimerInverse,
108 Timer100NsInverse, CounterMultiTimer,
109 CounterMultiTimer100Ns, CounterMultiTimerInverse,
110 CounterMultiTimer100NsInverse, AverageTimer32,
111 ElapsedTime, AverageCount64,
112 SampleBase, AverageBase,
113 RawBase, CounterMultiBase
127 NetworkInterfaceInstance,
131 #define PERFCTR_CAT(id,name,help,type,inst,first_counter) CATEGORY_ ## id,
132 #define PERFCTR_COUNTER(id,name,help,type,field)
134 #include "mono-perfcounters-def.h"
139 #undef PERFCTR_COUNTER
140 #define PERFCTR_CAT(id,name,help,type,inst,first_counter) CATEGORY_START_ ## id = -1,
141 #define PERFCTR_COUNTER(id,name,help,type,field) COUNTER_ ## id,
142 /* each counter is assigned an id starting from 0 inside the category */
144 #include "mono-perfcounters-def.h"
149 #undef PERFCTR_COUNTER
150 #define PERFCTR_CAT(id,name,help,type,inst,first_counter)
151 #define PERFCTR_COUNTER(id,name,help,type,field) CCOUNTER_ ## id,
152 /* this is used just to count the number of counters */
154 #include "mono-perfcounters-def.h"
158 static mono_mutex_t perfctr_mutex;
159 #define perfctr_lock() mono_os_mutex_lock (&perfctr_mutex)
160 #define perfctr_unlock() mono_os_mutex_unlock (&perfctr_mutex)
165 unsigned short counters_start;
166 unsigned short counters_size;
167 unsigned short data_start;
168 MonoPerfCounters counters;
173 binary format of custom counters in shared memory, starting from MonoSharedArea* + data_start;
175 struct stanza_header {
176 byte stanza_type; // FTYPE_*
178 ushort stanza_length; // includeas header
183 // perfcat and perfinstance are 4-bytes aligned
187 ushort length; // includes the counters
189 ushort counters_data_size;
191 char name[]; // null terminated
192 char help[]; // null terminated
193 // perfcounters follow
196 char name[]; // null terminated
197 char help[]; // null terminated
202 struct perfinstance {
204 byte data_offset; // offset of counters from beginning of struct
206 uint category_offset; // offset of category in the shared area
207 char name[]; // null terminated
208 // data follows: this is always 8-byte aligned
214 FTYPE_CATEGORY = 'C',
216 FTYPE_PREDEF_INSTANCE = 'P', // an instance of a predef counter
217 FTYPE_INSTANCE = 'I',
230 unsigned short num_counters;
231 unsigned short counters_data_size;
233 /* variable length data follows */
237 // SharedCounter counters_info [num_counters]
242 unsigned int category_offset;
243 /* variable length data follows */
244 char instance_name [1];
251 /* variable length data follows */
262 unsigned int instance_type : 6;
270 unsigned short offset; // offset inside MonoPerfCounters
275 #undef PERFCTR_COUNTER
276 #define PERFCTR_CAT(id,name,help,type,inst,first_counter) {name, help, CATEGORY_ ## id, type, inst ## Instance, CCOUNTER_ ## first_counter},
277 #define PERFCTR_COUNTER(id,name,help,type,field)
278 static const CategoryDesc
279 predef_categories [] = {
280 #include "mono-perfcounters-def.h"
281 {NULL, NULL, NUM_CATEGORIES, -1, 0, NUM_COUNTERS}
285 #undef PERFCTR_COUNTER
286 #define PERFCTR_CAT(id,name,help,type,inst,first_counter)
287 #define PERFCTR_COUNTER(id,name,help,type,field) {name, help, COUNTER_ ## id, G_STRUCT_OFFSET (MonoPerfCounters, field), type},
288 static const CounterDesc
289 predef_counters [] = {
290 #include "mono-perfcounters-def.h"
291 {NULL, NULL, -1, 0, 0}
295 * We have several different classes of counters:
297 * *) runtime counters
299 * *) user-defined counters
300 * *) windows counters (the implementation on windows will use this)
302 * To easily handle the differences we create a vtable for each class that contains the
303 * function pointers with the actual implementation to access the counters.
305 typedef struct _ImplVtable ImplVtable;
307 typedef MonoBoolean (*SampleFunc) (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample* sample);
308 typedef gint64 (*UpdateFunc) (ImplVtable *vtable, MonoBoolean do_incr, gint64 value);
309 typedef void (*CleanupFunc) (ImplVtable *vtable);
325 MonoPerfCounters *counters;
331 SharedInstance *instance_desc;
332 SharedCounter *counter_desc;
336 create_vtable (void *arg, SampleFunc sample, UpdateFunc update)
338 ImplVtable *vtable = g_new0 (ImplVtable, 1);
340 vtable->sample = sample;
341 vtable->update = update;
345 MonoPerfCounters *mono_perfcounters = NULL;
346 static MonoSharedArea *shared_area = NULL;
353 /* maps a pid to a ExternalSArea pointer */
354 static GHashTable *pid_to_shared_area = NULL;
356 static MonoSharedArea *
357 load_sarea_for_pid (int pid)
360 MonoSharedArea *area = NULL;
363 if (pid_to_shared_area == NULL)
364 pid_to_shared_area = g_hash_table_new (NULL, NULL);
365 data = (ExternalSArea *)g_hash_table_lookup (pid_to_shared_area, GINT_TO_POINTER (pid));
367 area = (MonoSharedArea *)mono_shared_area_for_pid (GINT_TO_POINTER (pid));
369 data = g_new (ExternalSArea, 1);
372 g_hash_table_insert (pid_to_shared_area, GINT_TO_POINTER (pid), data);
375 area = (MonoSharedArea *)data->sarea;
383 unref_pid_unlocked (int pid)
386 data = (ExternalSArea *)g_hash_table_lookup (pid_to_shared_area, GINT_TO_POINTER (pid));
389 if (!data->refcount) {
390 g_hash_table_remove (pid_to_shared_area, GINT_TO_POINTER (pid));
391 mono_shared_area_unload (data->sarea);
398 predef_cleanup (ImplVtable *vtable)
400 PredefVtable *vt = (PredefVtable*)vtable;
401 /* ExternalSArea *data; */
404 if (!pid_to_shared_area) {
408 unref_pid_unlocked (vt->pid);
413 mono_determine_physical_ram_size (void)
415 #if defined (TARGET_WIN32)
416 MEMORYSTATUSEX memstat;
418 memstat.dwLength = sizeof (memstat);
419 GlobalMemoryStatusEx (&memstat);
420 return (guint64)memstat.ullTotalPhys;
421 #elif defined (__NetBSD__) || defined (__APPLE__)
435 size_t size_sys = sizeof (value);
437 sysctl (mib, 2, &value, &size_sys, NULL, 0);
441 return (guint64)value;
442 #elif defined (HAVE_SYSCONF)
443 guint64 page_size = 0, num_pages = 0;
445 /* sysconf works on most *NIX operating systems, if your system doesn't have it or if it
446 * reports invalid values, please add your OS specific code below. */
448 page_size = (guint64)sysconf (_SC_PAGESIZE);
451 #ifdef _SC_PHYS_PAGES
452 num_pages = (guint64)sysconf (_SC_PHYS_PAGES);
455 if (!page_size || !num_pages) {
456 g_warning ("Your operating system's sysconf (3) function doesn't correctly report physical memory size!");
460 return page_size * num_pages;
467 mono_determine_physical_ram_available_size (void)
469 #if defined (TARGET_WIN32)
470 MEMORYSTATUSEX memstat;
472 memstat.dwLength = sizeof (memstat);
473 GlobalMemoryStatusEx (&memstat);
474 return (guint64)memstat.ullAvailPhys;
476 #elif defined (__NetBSD__)
477 struct vmtotal vm_total;
485 len = sizeof (vm_total);
486 sysctl (mib, 2, &vm_total, &len, NULL, 0);
489 mib[1] = HW_PAGESIZE;
491 len = sizeof (page_size);
492 sysctl (mib, 2, &page_size, &len, NULL, 0);
494 return ((guint64) vm_total.t_free * page_size) / 1024;
495 #elif defined (__APPLE__)
496 mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
497 mach_port_t host = mach_host_self();
499 vm_statistics_data_t vmstat;
502 ret = host_statistics(host, HOST_VM_INFO, (host_info_t)&vmstat, &count);
503 } while (ret == KERN_ABORTED);
505 if (ret != KERN_SUCCESS) {
506 g_warning ("Mono was unable to retrieve memory usage!");
510 host_page_size(host, &page_size);
511 return (guint64) vmstat.free_count * page_size;
513 #elif defined (HAVE_SYSCONF)
514 guint64 page_size = 0, num_pages = 0;
516 /* sysconf works on most *NIX operating systems, if your system doesn't have it or if it
517 * reports invalid values, please add your OS specific code below. */
519 page_size = (guint64)sysconf (_SC_PAGESIZE);
522 #ifdef _SC_AVPHYS_PAGES
523 num_pages = (guint64)sysconf (_SC_AVPHYS_PAGES);
526 if (!page_size || !num_pages) {
527 g_warning ("Your operating system's sysconf (3) function doesn't correctly report physical memory size!");
531 return page_size * num_pages;
538 mono_perfcounters_init (void)
540 int d_offset = G_STRUCT_OFFSET (MonoSharedArea, data);
544 mono_os_mutex_init_recursive (&perfctr_mutex);
546 shared_area = (MonoSharedArea *)mono_shared_area ();
547 shared_area->counters_start = G_STRUCT_OFFSET (MonoSharedArea, counters);
548 shared_area->counters_size = sizeof (MonoPerfCounters);
549 shared_area->data_start = d_offset;
550 shared_area->size = 4096;
551 mono_perfcounters = &shared_area->counters;
555 perfctr_type_compress (int type)
558 for (i = 0; i < G_N_ELEMENTS (simple_type_to_type); ++i) {
559 if (simple_type_to_type [i] == type)
562 /* NumberOfItems32 */
567 shared_data_reserve_room (int size, int ftype)
569 SharedHeader* header;
570 unsigned char *p = (unsigned char *)shared_area + shared_area->data_start;
571 unsigned char *end = (unsigned char *)shared_area + shared_area->size;
576 unsigned short *next;
577 if (*p == FTYPE_END) {
578 if (size < (end - p))
584 next = (unsigned short*)(p + 2);
585 if (*p == FTYPE_DELETED) {
586 /* we reuse only if it's the same size */
596 header = (SharedHeader*)p;
597 header->ftype = ftype;
598 header->extra = 0; /* data_offset could overflow here, so we leave this field unused */
604 typedef gboolean (*SharedFunc) (SharedHeader *header, void *data);
607 foreach_shared_item_in_area (unsigned char *p, unsigned char *end, SharedFunc func, void *data)
610 unsigned short *next;
613 next = (unsigned short*)(p + 2);
614 if (!func ((SharedHeader*)p, data))
623 foreach_shared_item (SharedFunc func, void *data)
625 unsigned char *p = (unsigned char *)shared_area + shared_area->data_start;
626 unsigned char *end = (unsigned char *)shared_area + shared_area->size;
628 foreach_shared_item_in_area (p, end, func, data);
632 mono_string_compare_ascii (MonoString *str, const char *ascii_str)
634 /* FIXME: make this case insensitive */
635 guint16 *strc = mono_string_chars (str);
636 while (*strc == *ascii_str++) {
641 return *strc - *(const unsigned char *)(ascii_str - 1);
650 category_search (SharedHeader *header, void *data)
652 CatSearch *search = (CatSearch *)data;
653 if (header->ftype == FTYPE_CATEGORY) {
654 SharedCategory *cat = (SharedCategory*)header;
655 if (mono_string_compare_ascii (search->name, cat->name) == 0) {
663 static SharedCategory*
664 find_custom_category (MonoString *name)
669 foreach_shared_item (category_search, &search);
674 category_collect (SharedHeader *header, void *data)
676 GSList **list = (GSList **)data;
677 if (header->ftype == FTYPE_CATEGORY) {
678 *list = g_slist_prepend (*list, header);
684 get_custom_categories (void) {
686 foreach_shared_item (category_collect, &list);
691 custom_category_counters (SharedCategory* cat)
693 char *p = cat->name + strlen (cat->name) + 1;
694 p += strlen (p) + 1; /* skip category help */
698 static SharedCounter*
699 find_custom_counter (SharedCategory* cat, MonoString *name)
702 char *p = custom_category_counters (cat);
703 for (i = 0; i < cat->num_counters; ++i) {
704 SharedCounter *counter = (SharedCounter*)p;
705 if (mono_string_compare_ascii (name, counter->name) == 0)
707 p += 2; /* skip counter type */
708 p += strlen (p) + 1; /* skip counter name */
709 p += strlen (p) + 1; /* skip counter help */
715 unsigned int cat_offset;
718 SharedInstance* result;
723 instance_search (SharedHeader *header, void *data)
725 InstanceSearch *search = (InstanceSearch *)data;
726 if (header->ftype == FTYPE_INSTANCE) {
727 SharedInstance *ins = (SharedInstance*)header;
728 if (search->cat_offset == ins->category_offset) {
730 if (strcmp (search->name, ins->instance_name) == 0) {
731 search->result = ins;
735 search->list = g_slist_prepend (search->list, ins);
742 static SharedInstance*
743 find_custom_instance (SharedCategory* cat, char *name)
745 InstanceSearch search;
746 search.cat_offset = (char*)cat - (char*)shared_area;
750 search.result = NULL;
751 foreach_shared_item (instance_search, &search);
752 return search.result;
756 get_custom_instances_list (SharedCategory* cat)
758 InstanceSearch search;
759 search.cat_offset = (char*)cat - (char*)shared_area;
763 search.result = NULL;
764 foreach_shared_item (instance_search, &search);
769 custom_category_help (SharedCategory* cat)
771 return cat->name + strlen (cat->name) + 1;
774 static const CounterDesc*
775 get_counter_in_category (const CategoryDesc *desc, MonoString *counter)
777 const CounterDesc *cdesc = &predef_counters [desc->first_counter];
778 const CounterDesc *end = &predef_counters [desc [1].first_counter];
779 for (; cdesc < end; ++cdesc) {
780 if (mono_string_compare_ascii (counter, cdesc->name) == 0)
786 /* fill the info in sample (except the raw value) */
788 fill_sample (MonoCounterSample *sample)
790 sample->timeStamp = mono_100ns_ticks ();
791 sample->timeStamp100nSec = sample->timeStamp;
792 sample->counterTimeStamp = sample->timeStamp;
793 sample->counterFrequency = 10000000;
794 sample->systemFrequency = 10000000;
795 // the real basevalue needs to be get from a different counter...
796 sample->baseValue = 0;
800 id_from_string (const gchar *id_str, gboolean is_process)
803 if (strcmp("", id_str) != 0) {
805 id = strtol (id_str, &end, 0);
806 if (end == id_str && !is_process)
813 get_cpu_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *sample)
815 MonoProcessError error;
816 int id = GPOINTER_TO_INT (vtable->arg);
820 fill_sample (sample);
821 sample->baseValue = 1;
823 sample->counterType = predef_counters [predef_categories [CATEGORY_CPU].first_counter + id].type;
825 case COUNTER_CPU_USER_TIME:
826 sample->rawValue = mono_cpu_get_data (pid, MONO_CPU_USER_TIME, &error);
828 case COUNTER_CPU_PRIV_TIME:
829 sample->rawValue = mono_cpu_get_data (pid, MONO_CPU_PRIV_TIME, &error);
831 case COUNTER_CPU_INTR_TIME:
832 sample->rawValue = mono_cpu_get_data (pid, MONO_CPU_INTR_TIME, &error);
834 case COUNTER_CPU_DCP_TIME:
835 sample->rawValue = mono_cpu_get_data (pid, MONO_CPU_DCP_TIME, &error);
837 case COUNTER_CPU_PROC_TIME:
838 sample->rawValue = mono_cpu_get_data (pid, MONO_CPU_IDLE_TIME, &error);
845 cpu_get_impl (MonoString* counter, const gchar* instance, int *type, MonoBoolean *custom)
847 int id = id_from_string (instance, FALSE) << 5;
848 const CounterDesc *cdesc;
850 /* increase the shift above and the mask also in the implementation functions */
851 //g_assert (32 > desc [1].first_counter - desc->first_counter);
852 if ((cdesc = get_counter_in_category (&predef_categories [CATEGORY_CPU], counter))) {
854 return create_vtable (GINT_TO_POINTER (id | cdesc->id), get_cpu_counter, NULL);
860 get_network_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *sample)
862 MonoNetworkError error = MONO_NETWORK_ERROR_OTHER;
863 NetworkVtableArg *narg = (NetworkVtableArg*) vtable->arg;
865 fill_sample (sample);
868 sample->counterType = predef_counters [predef_categories [CATEGORY_NETWORK].first_counter + narg->id].type;
870 case COUNTER_NETWORK_BYTESRECSEC:
871 sample->rawValue = mono_network_get_data (narg->name, MONO_NETWORK_BYTESREC, &error);
873 case COUNTER_NETWORK_BYTESSENTSEC:
874 sample->rawValue = mono_network_get_data (narg->name, MONO_NETWORK_BYTESSENT, &error);
876 case COUNTER_NETWORK_BYTESTOTALSEC:
877 sample->rawValue = mono_network_get_data (narg->name, MONO_NETWORK_BYTESTOTAL, &error);
881 if (error == MONO_NETWORK_ERROR_NONE)
888 network_cleanup (ImplVtable *vtable)
890 NetworkVtableArg *narg;
895 narg = (NetworkVtableArg *)vtable->arg;
906 network_get_impl (MonoString* counter, const gchar* instance, int *type, MonoBoolean *custom)
908 const CounterDesc *cdesc;
909 NetworkVtableArg *narg;
914 if ((cdesc = get_counter_in_category (&predef_categories [CATEGORY_NETWORK], counter))) {
915 instance_name = g_strdup (instance);
916 narg = g_new0 (NetworkVtableArg, 1);
917 narg->id = cdesc->id;
918 narg->name = instance_name;
920 vtable = create_vtable (narg, get_network_counter, NULL);
921 vtable->cleanup = network_cleanup;
928 get_process_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *sample)
930 int id = GPOINTER_TO_INT (vtable->arg);
936 fill_sample (sample);
937 sample->baseValue = 1;
939 sample->counterType = predef_counters [predef_categories [CATEGORY_PROC].first_counter + id].type;
941 case COUNTER_PROC_USER_TIME:
942 sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_USER_TIME);
944 case COUNTER_PROC_PRIV_TIME:
945 sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_SYSTEM_TIME);
947 case COUNTER_PROC_PROC_TIME:
948 sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_TOTAL_TIME);
950 case COUNTER_PROC_THREADS:
951 sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_NUM_THREADS);
953 case COUNTER_PROC_VBYTES:
954 sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_VIRTUAL_BYTES);
956 case COUNTER_PROC_WSET:
957 sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_WORKING_SET);
959 case COUNTER_PROC_PBYTES:
960 sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_PRIVATE_BYTES);
967 process_get_impl (MonoString* counter, const gchar* instance, int *type, MonoBoolean *custom)
969 int id = id_from_string (instance, TRUE) << 5;
970 const CounterDesc *cdesc;
972 /* increase the shift above and the mask also in the implementation functions */
973 //g_assert (32 > desc [1].first_counter - desc->first_counter);
974 if ((cdesc = get_counter_in_category (&predef_categories [CATEGORY_PROC], counter))) {
976 return create_vtable (GINT_TO_POINTER (id | cdesc->id), get_process_counter, NULL);
982 mono_mem_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *sample)
984 int id = GPOINTER_TO_INT (vtable->arg);
986 fill_sample (sample);
987 sample->baseValue = 1;
989 sample->counterType = predef_counters [predef_categories [CATEGORY_MONO_MEM].first_counter + id].type;
991 case COUNTER_MEM_NUM_OBJECTS:
992 sample->rawValue = 0;
994 case COUNTER_MEM_PHYS_TOTAL:
995 sample->rawValue = mono_determine_physical_ram_size ();;
997 case COUNTER_MEM_PHYS_AVAILABLE:
998 sample->rawValue = mono_determine_physical_ram_available_size ();;
1005 mono_mem_get_impl (MonoString* counter, const gchar* instance, int *type, MonoBoolean *custom)
1007 const CounterDesc *cdesc;
1009 if ((cdesc = get_counter_in_category (&predef_categories [CATEGORY_MONO_MEM], counter))) {
1010 *type = cdesc->type;
1011 return create_vtable (GINT_TO_POINTER ((gint) cdesc->id), mono_mem_counter, NULL);
1017 predef_readonly_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *sample)
1019 PredefVtable *vt = (PredefVtable *)vtable;
1020 const CounterDesc *desc;
1021 int cat_id = GPOINTER_TO_INT (vtable->arg);
1022 int id = cat_id >> 16;
1025 fill_sample (sample);
1026 sample->baseValue = 1;
1028 desc = &predef_counters [predef_categories [cat_id].first_counter + id];
1029 sample->counterType = desc->type;
1030 /* FIXME: check that the offset fits inside imported counters */
1031 /*g_print ("loading %s at %d\n", desc->name, desc->offset);*/
1032 sample->rawValue = *(guint32*)((char*)vt->counters + desc->offset);
1037 predef_vtable (void *arg, const gchar *pids)
1039 MonoSharedArea *area;
1040 PredefVtable *vtable;
1044 area = load_sarea_for_pid (pid);
1048 vtable = g_new (PredefVtable, 1);
1049 vtable->vtable.arg = arg;
1050 vtable->vtable.sample = predef_readonly_counter;
1051 vtable->vtable.cleanup = predef_cleanup;
1052 vtable->counters = (MonoPerfCounters*)((char*)area + area->counters_start);
1055 return (ImplVtable*)vtable;
1058 /* consider storing the pointer directly in vtable->arg, so the runtime overhead is lower:
1059 * this needs some way to set sample->counterType as well, though.
1062 predef_writable_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *sample)
1064 int cat_id = GPOINTER_TO_INT (vtable->arg);
1065 int id = cat_id >> 16;
1068 fill_sample (sample);
1069 sample->baseValue = 1;
1071 sample->counterType = predef_counters [predef_categories [cat_id].first_counter + id].type;
1075 case COUNTER_EXC_THROWN:
1076 sample->rawValue = mono_perfcounters->exceptions_thrown;
1080 case CATEGORY_ASPNET:
1082 case COUNTER_ASPNET_REQ_Q:
1083 sample->rawValue = mono_perfcounters->aspnet_requests_queued;
1085 case COUNTER_ASPNET_REQ_TOTAL:
1086 sample->rawValue = mono_perfcounters->aspnet_requests;
1090 case CATEGORY_THREADPOOL:
1092 case COUNTER_THREADPOOL_WORKITEMS:
1093 sample->rawValue = mono_perfcounters->threadpool_workitems;
1095 case COUNTER_THREADPOOL_IOWORKITEMS:
1096 sample->rawValue = mono_perfcounters->threadpool_ioworkitems;
1098 case COUNTER_THREADPOOL_THREADS:
1099 sample->rawValue = mono_perfcounters->threadpool_threads;
1101 case COUNTER_THREADPOOL_IOTHREADS:
1102 sample->rawValue = mono_perfcounters->threadpool_iothreads;
1108 case COUNTER_JIT_BYTES:
1109 sample->rawValue = mono_perfcounters->jit_bytes;
1111 case COUNTER_JIT_METHODS:
1112 sample->rawValue = mono_perfcounters->jit_methods;
1114 case COUNTER_JIT_TIME:
1115 sample->rawValue = mono_perfcounters->jit_time;
1117 case COUNTER_JIT_BYTES_PSEC:
1118 sample->rawValue = mono_perfcounters->jit_bytes;
1120 case COUNTER_JIT_FAILURES:
1121 sample->rawValue = mono_perfcounters->jit_failures;
1130 predef_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value)
1132 guint32 *volatile ptr = NULL;
1133 gint64 *volatile ptr64 = NULL;
1134 int cat_id = GPOINTER_TO_INT (vtable->arg);
1135 int id = cat_id >> 16;
1138 case CATEGORY_ASPNET:
1140 case COUNTER_ASPNET_REQ_Q: ptr = &mono_perfcounters->aspnet_requests_queued; break;
1141 case COUNTER_ASPNET_REQ_TOTAL: ptr = &mono_perfcounters->aspnet_requests; break;
1144 case CATEGORY_THREADPOOL:
1146 case COUNTER_THREADPOOL_WORKITEMS: ptr64 = (gint64 *) &mono_perfcounters->threadpool_workitems; break;
1147 case COUNTER_THREADPOOL_IOWORKITEMS: ptr64 = (gint64 *) &mono_perfcounters->threadpool_ioworkitems; break;
1148 case COUNTER_THREADPOOL_THREADS: ptr = &mono_perfcounters->threadpool_threads; break;
1149 case COUNTER_THREADPOOL_IOTHREADS: ptr = &mono_perfcounters->threadpool_iothreads; break;
1156 return InterlockedIncrement ((gint32 *) ptr); /* FIXME: sign */
1158 return InterlockedDecrement ((gint32 *) ptr); /* FIXME: sign */
1163 /* this can be non-atomic */
1168 /* FIXME: we need to do this atomically */
1169 /* No InterlockedIncrement64() yet */
1172 return InterlockedIncrement64 (ptr);
1174 return InterlockedDecrement64 (ptr);
1180 /* this can be non-atomic */
1188 predef_writable_get_impl (int cat, MonoString* counter, const gchar *instance, int *type, MonoBoolean *custom)
1190 const CounterDesc *cdesc;
1192 if ((cdesc = get_counter_in_category (&predef_categories [cat], counter))) {
1193 *type = cdesc->type;
1194 if (instance == NULL || strcmp (instance, "") == 0)
1195 return create_vtable (GINT_TO_POINTER ((cdesc->id << 16) | cat), predef_writable_counter, predef_writable_update);
1197 return predef_vtable (GINT_TO_POINTER ((cdesc->id << 16) | cat), instance);
1203 custom_writable_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *sample)
1205 CustomVTable *counter_data = (CustomVTable *)vtable;
1207 fill_sample (sample);
1208 sample->baseValue = 1;
1210 sample->counterType = simple_type_to_type [counter_data->counter_desc->type];
1212 sample->rawValue = 0;
1214 sample->rawValue = *(guint64*)vtable->arg;
1219 custom_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value)
1221 /* FIXME: check writability */
1222 guint64 *ptr = (guint64 *)vtable->arg;
1225 /* FIXME: we need to do this atomically */
1229 /* this can be non-atomic */
1236 static SharedInstance*
1237 custom_get_instance (SharedCategory *cat, SharedCounter *scounter, char* name)
1239 SharedInstance* inst;
1242 inst = find_custom_instance (cat, name);
1245 size = sizeof (SharedInstance) + strlen (name);
1248 size += (sizeof (guint64) * cat->num_counters);
1250 inst = (SharedInstance*) shared_data_reserve_room (size, FTYPE_INSTANCE);
1256 inst->category_offset = (char*)cat - (char*)shared_area;
1257 cat->num_instances++;
1258 /* now copy the variable data */
1259 p = inst->instance_name;
1261 p += strlen (name) + 1;
1268 custom_vtable (SharedCounter *scounter, SharedInstance* inst, char *data)
1270 CustomVTable* vtable;
1271 vtable = g_new0 (CustomVTable, 1);
1272 vtable->vtable.arg = data;
1273 vtable->vtable.sample = custom_writable_counter;
1274 vtable->vtable.update = custom_writable_update;
1275 vtable->instance_desc = inst;
1276 vtable->counter_desc = scounter;
1278 return (ImplVtable*)vtable;
1282 custom_get_value_address (SharedCounter *scounter, SharedInstance* sinst)
1284 int offset = sizeof (SharedInstance) + strlen (sinst->instance_name);
1287 offset += scounter->seq_num * sizeof (guint64);
1288 return (char*)sinst + offset;
1292 custom_get_impl (SharedCategory *cat, MonoString *counter, MonoString* instance, int *type, MonoError *error)
1294 SharedCounter *scounter;
1295 SharedInstance* inst;
1299 scounter = find_custom_counter (cat, counter);
1302 name = mono_string_to_utf8_checked (counter, error);
1303 return_val_if_nok (error, NULL);
1304 *type = simple_type_to_type [scounter->type];
1305 inst = custom_get_instance (cat, scounter, name);
1309 return custom_vtable (scounter, inst, (char *)custom_get_value_address (scounter, inst));
1312 static const CategoryDesc*
1313 find_category (MonoString *category)
1316 for (i = 0; i < NUM_CATEGORIES; ++i) {
1317 if (mono_string_compare_ascii (category, predef_categories [i].name) == 0)
1318 return &predef_categories [i];
1324 mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString* instance,
1325 MonoString* machine, int *type, MonoBoolean *custom)
1328 const CategoryDesc *cdesc;
1329 void *result = NULL;
1330 /* no support for counters on other machines */
1331 if (mono_string_compare_ascii (machine, "."))
1333 cdesc = find_category (category);
1335 SharedCategory *scat = find_custom_category (category);
1339 result = custom_get_impl (scat, counter, instance, type, &error);
1340 if (mono_error_set_pending_exception (&error))
1344 gchar *c_instance = mono_string_to_utf8_checked (instance, &error);
1345 if (mono_error_set_pending_exception (&error))
1347 switch (cdesc->id) {
1349 result = cpu_get_impl (counter, c_instance, type, custom);
1352 result = process_get_impl (counter, c_instance, type, custom);
1354 case CATEGORY_MONO_MEM:
1355 result = mono_mem_get_impl (counter, c_instance, type, custom);
1357 case CATEGORY_NETWORK:
1358 result = network_get_impl (counter, c_instance, type, custom);
1363 case CATEGORY_REMOTING:
1364 case CATEGORY_LOADING:
1365 case CATEGORY_THREAD:
1366 case CATEGORY_INTEROP:
1367 case CATEGORY_SECURITY:
1368 case CATEGORY_ASPNET:
1369 case CATEGORY_THREADPOOL:
1370 result = predef_writable_get_impl (cdesc->id, counter, c_instance, type, custom);
1373 g_free (c_instance);
1378 mono_perfcounter_get_sample (void *impl, MonoBoolean only_value, MonoCounterSample *sample)
1380 ImplVtable *vtable = (ImplVtable *)impl;
1381 if (vtable && vtable->sample)
1382 return vtable->sample (vtable, only_value, sample);
1387 mono_perfcounter_update_value (void *impl, MonoBoolean do_incr, gint64 value)
1389 ImplVtable *vtable = (ImplVtable *)impl;
1390 if (vtable && vtable->update)
1391 return vtable->update (vtable, do_incr, value);
1396 mono_perfcounter_free_data (void *impl)
1398 ImplVtable *vtable = (ImplVtable *)impl;
1399 if (vtable && vtable->cleanup)
1400 vtable->cleanup (vtable);
1404 /* Category icalls */
1406 mono_perfcounter_category_del (MonoString *name)
1408 const CategoryDesc *cdesc;
1409 SharedCategory *cat;
1410 cdesc = find_category (name);
1411 /* can't delete a predefined category */
1415 cat = find_custom_category (name);
1416 /* FIXME: check the semantics, if deleting a category means also deleting the instances */
1417 if (!cat || cat->num_instances) {
1421 cat->header.ftype = FTYPE_DELETED;
1426 /* this is an icall */
1428 mono_perfcounter_category_help (MonoString *category, MonoString *machine)
1431 MonoString *result = NULL;
1432 const CategoryDesc *cdesc;
1433 error_init (&error);
1434 /* no support for counters on other machines */
1435 if (mono_string_compare_ascii (machine, "."))
1437 cdesc = find_category (category);
1439 SharedCategory *scat = find_custom_category (category);
1442 result = mono_string_new_checked (mono_domain_get (), custom_category_help (scat), &error);
1443 if (mono_error_set_pending_exception (&error))
1447 result = mono_string_new_checked (mono_domain_get (), cdesc->help, &error);
1448 if (mono_error_set_pending_exception (&error))
1454 * Check if the category named @category exists on @machine. If @counter is not NULL, return
1455 * TRUE only if a counter with that name exists in the category.
1458 mono_perfcounter_category_exists (MonoString *counter, MonoString *category, MonoString *machine)
1460 const CategoryDesc *cdesc;
1461 /* no support for counters on other machines */
1462 if (mono_string_compare_ascii (machine, "."))
1464 cdesc = find_category (category);
1466 SharedCategory *scat = find_custom_category (category);
1469 /* counter is allowed to be null */
1472 /* search through the custom category */
1473 return find_custom_counter (scat, counter) != NULL;
1475 /* counter is allowed to be null */
1478 if (get_counter_in_category (cdesc, counter))
1483 /* C map of the type with the same name */
1489 } CounterCreationData;
1492 * Since we'll keep a copy of the category per-process, we should also make sure
1493 * categories with the same name are compatible.
1496 mono_perfcounter_create (MonoString *category, MonoString *help, int type, MonoArray *items)
1501 int num_counters = mono_array_length (items);
1502 int counters_data_size;
1505 char **counter_info = NULL;
1507 SharedCategory *cat;
1509 /* FIXME: ensure there isn't a category created already */
1510 name = mono_string_to_utf8_checked (category, &error);
1511 if (!mono_error_ok (&error))
1513 chelp = mono_string_to_utf8_checked (help, &error);
1514 if (!mono_error_ok (&error))
1516 counter_info = g_new0 (char*, num_counters * 2);
1517 /* calculate the size we need structure size + name/help + 2 0 string terminators */
1518 size = G_STRUCT_OFFSET (SharedCategory, name) + strlen (name) + strlen (chelp) + 2;
1519 for (i = 0; i < num_counters; ++i) {
1520 CounterCreationData *data = mono_array_get (items, CounterCreationData*, i);
1521 counter_info [i * 2] = mono_string_to_utf8_checked (data->name, &error);
1522 if (!mono_error_ok (&error))
1524 counter_info [i * 2 + 1] = mono_string_to_utf8_checked (data->help, &error);
1525 if (!mono_error_ok (&error))
1527 size += sizeof (SharedCounter) + 1; /* 1 is for the help 0 terminator */
1529 for (i = 0; i < num_counters * 2; ++i) {
1530 if (!counter_info [i])
1532 size += strlen (counter_info [i]) + 1;
1536 counters_data_size = num_counters * 8; /* optimize for size later */
1540 cat = (SharedCategory*) shared_data_reserve_room (size, FTYPE_CATEGORY);
1545 cat->num_counters = num_counters;
1546 cat->counters_data_size = counters_data_size;
1547 /* now copy the vaiable data */
1550 p += strlen (name) + 1;
1552 p += strlen (chelp) + 1;
1553 for (i = 0; i < num_counters; ++i) {
1554 CounterCreationData *data = mono_array_get (items, CounterCreationData*, i);
1555 /* emit the SharedCounter structures */
1556 *p++ = perfctr_type_compress (data->type);
1558 strcpy (p, counter_info [i * 2]);
1559 p += strlen (counter_info [i * 2]) + 1;
1560 strcpy (p, counter_info [i * 2 + 1]);
1561 p += strlen (counter_info [i * 2 + 1]) + 1;
1568 for (i = 0; i < num_counters * 2; ++i) {
1569 g_free (counter_info [i]);
1571 g_free (counter_info);
1575 mono_error_cleanup (&error);
1580 mono_perfcounter_instance_exists (MonoString *instance, MonoString *category, MonoString *machine)
1583 const CategoryDesc *cdesc;
1584 SharedInstance *sinst;
1586 /* no support for counters on other machines */
1587 /*FIXME: machine appears to be wrong
1588 if (mono_string_compare_ascii (machine, "."))
1590 cdesc = find_category (category);
1592 SharedCategory *scat;
1593 scat = find_custom_category (category);
1596 name = mono_string_to_utf8_checked (instance, &error);
1597 if (mono_error_set_pending_exception (&error))
1599 sinst = find_custom_instance (scat, name);
1604 /* FIXME: search instance */
1609 /* this is an icall */
1611 mono_perfcounter_category_names (MonoString *machine)
1616 MonoDomain *domain = mono_domain_get ();
1617 GSList *custom_categories, *tmp;
1618 /* no support for counters on other machines */
1619 if (mono_string_compare_ascii (machine, ".")) {
1620 res = mono_array_new_checked (domain, mono_get_string_class (), 0, &error);
1621 mono_error_set_pending_exception (&error);
1625 custom_categories = get_custom_categories ();
1626 res = mono_array_new_checked (domain, mono_get_string_class (), NUM_CATEGORIES + g_slist_length (custom_categories), &error);
1627 if (mono_error_set_pending_exception (&error)) {
1632 for (i = 0; i < NUM_CATEGORIES; ++i) {
1633 const CategoryDesc *cdesc = &predef_categories [i];
1634 MonoString *name = mono_string_new_checked (domain, cdesc->name, &error);
1635 if (!is_ok (&error))
1637 mono_array_setref (res, i, name);
1639 for (tmp = custom_categories; tmp; tmp = tmp->next) {
1640 SharedCategory *scat = (SharedCategory *)tmp->data;
1641 MonoString *name = mono_string_new_checked (domain, scat->name, &error);
1642 if (!is_ok (&error))
1644 mono_array_setref (res, i, name);
1649 g_slist_free (custom_categories);
1650 mono_error_set_pending_exception (&error);
1655 mono_perfcounter_counter_names (MonoString *category, MonoString *machine)
1659 SharedCategory *scat;
1660 const CategoryDesc *cdesc;
1662 MonoDomain *domain = mono_domain_get ();
1663 /* no support for counters on other machines */
1664 if (mono_string_compare_ascii (machine, ".")) {
1665 res = mono_array_new_checked (domain, mono_get_string_class (), 0, &error);
1666 mono_error_set_pending_exception (&error);
1669 cdesc = find_category (category);
1671 res = mono_array_new_checked (domain, mono_get_string_class (), cdesc [1].first_counter - cdesc->first_counter, &error);
1672 if (mono_error_set_pending_exception (&error))
1674 for (i = cdesc->first_counter; i < cdesc [1].first_counter; ++i) {
1675 const CounterDesc *desc = &predef_counters [i];
1676 MonoString *name = mono_string_new_checked (domain, desc->name, &error);
1677 if (mono_error_set_pending_exception (&error))
1679 mono_array_setref (res, i - cdesc->first_counter, name);
1684 scat = find_custom_category (category);
1686 char *p = custom_category_counters (scat);
1688 res = mono_array_new_checked (domain, mono_get_string_class (), scat->num_counters, &error);
1689 if (mono_error_set_pending_exception (&error)) {
1694 for (i = 0; i < scat->num_counters; ++i) {
1695 MonoString *str = mono_string_new_checked (domain, p + 1, &error);
1696 if (!is_ok (&error))
1698 mono_array_setref (res, i, str);
1699 p += 2; /* skip counter type */
1700 p += strlen (p) + 1; /* skip counter name */
1701 p += strlen (p) + 1; /* skip counter help */
1704 res = mono_array_new_checked (domain, mono_get_string_class (), 0, &error);
1707 mono_error_set_pending_exception (&error);
1712 get_string_array (void **array, int count, gboolean is_process, MonoError *error)
1715 MonoDomain *domain = mono_domain_get ();
1717 MonoArray * res = mono_array_new_checked (mono_domain_get (), mono_get_string_class (), count, error);
1718 return_val_if_nok (error, NULL);
1719 for (i = 0; i < count; ++i) {
1723 char *pname = mono_process_get_name (array [i], buf, sizeof (buf));
1724 p = g_strdup_printf ("%d/%s", GPOINTER_TO_INT (array [i]), pname);
1726 sprintf (buf, "%d", GPOINTER_TO_INT (array [i]));
1729 MonoString *str = mono_string_new_checked (domain, p, error);
1732 return_val_if_nok (error, NULL);
1733 mono_array_setref (res, i, str);
1739 get_string_array_of_strings (void **array, int count, MonoError *error)
1742 MonoDomain *domain = mono_domain_get ();
1744 MonoArray * res = mono_array_new_checked (mono_domain_get (), mono_get_string_class (), count, error);
1745 return_val_if_nok (error, NULL);
1746 for (i = 0; i < count; ++i) {
1747 char* p = (char *)array[i];
1748 MonoString *str = mono_string_new_checked (domain, p, error);
1749 return_val_if_nok (error, NULL);
1750 mono_array_setref (res, i, str);
1757 get_mono_instances (MonoError *error)
1767 buf = g_new (void*, count);
1768 res = mono_shared_area_instances (buf, count);
1769 } while (res == count);
1770 array = get_string_array (buf, res, TRUE, error);
1776 get_cpu_instances (MonoError *error)
1782 count = mono_cpu_count () + 1; /* +1 for "_Total" */
1783 buf = g_new (void*, count);
1784 for (i = 0; i < count; ++i)
1785 buf [i] = GINT_TO_POINTER (i - 1); /* -1 => _Total */
1786 array = get_string_array (buf, count, FALSE, error);
1788 MonoString *total = mono_string_new_checked (mono_domain_get (), "_Total", error);
1789 return_val_if_nok (error, NULL);
1790 mono_array_setref (array, 0, total);
1795 get_processes_instances (MonoError *error)
1799 void **buf = mono_process_list (&count);
1802 return get_string_array (NULL, 0, FALSE, error);
1803 array = get_string_array (buf, count, TRUE, error);
1809 get_networkinterface_instances (MonoError *error)
1814 void **buf = mono_networkinterface_list (&count);
1816 return get_string_array_of_strings (NULL, 0, error);
1817 array = get_string_array_of_strings (buf, count, error);
1818 g_strfreev ((char **) buf);
1823 get_custom_instances (MonoString *category, MonoError *error)
1825 SharedCategory *scat;
1827 scat = find_custom_category (category);
1829 GSList *list = get_custom_instances_list (scat);
1832 MonoArray *array = mono_array_new_checked (mono_domain_get (), mono_get_string_class (), g_slist_length (list), error);
1833 if (!is_ok (error)) {
1834 g_slist_free (list);
1837 for (tmp = list; tmp; tmp = tmp->next) {
1838 SharedInstance *inst = (SharedInstance *)tmp->data;
1839 MonoString *str = mono_string_new_checked (mono_domain_get (), inst->instance_name, error);
1840 if (!is_ok (error)) {
1841 g_slist_free (list);
1844 mono_array_setref (array, i, str);
1847 g_slist_free (list);
1850 return mono_array_new_checked (mono_domain_get (), mono_get_string_class (), 0, error);
1854 mono_perfcounter_instance_names (MonoString *category, MonoString *machine)
1857 const CategoryDesc* cat;
1858 MonoArray *result = NULL;
1859 if (mono_string_compare_ascii (machine, ".")) {
1860 result = mono_array_new_checked (mono_domain_get (), mono_get_string_class (), 0, &error);
1861 mono_error_set_pending_exception (&error);
1865 cat = find_category (category);
1867 MonoArray *result = get_custom_instances (category, &error);
1868 mono_error_set_pending_exception (&error);
1871 switch (cat->instance_type) {
1873 result = get_mono_instances (&error);
1876 result = get_cpu_instances (&error);
1878 case ProcessInstance:
1879 result = get_processes_instances (&error);
1881 case NetworkInterfaceInstance:
1882 result = get_networkinterface_instances (&error);
1884 case ThreadInstance:
1886 result = mono_array_new_checked (mono_domain_get (), mono_get_string_class (), 0, &error);
1888 mono_error_set_pending_exception (&error);
1893 PerfCounterEnumCallback cb;
1895 } PerfCounterForeachData;
1898 mono_perfcounter_foreach_shared_item (SharedHeader *header, gpointer data)
1904 SharedCategory *cat;
1905 SharedCounter *counter;
1906 SharedInstance *inst;
1907 PerfCounterForeachData *foreach_data = (PerfCounterForeachData *)data;
1909 if (header->ftype == FTYPE_CATEGORY) {
1910 cat = (SharedCategory*)header;
1913 p += strlen (p) + 1; /* skip category name */
1914 p += strlen (p) + 1; /* skip category help */
1916 for (i = 0; i < cat->num_counters; ++i) {
1917 counter = (SharedCounter*) p;
1918 type = (unsigned char)*p++;
1919 /* seq_num = (int)* */ p++;
1921 p += strlen (p) + 1;
1923 p += strlen (p) + 1;
1925 inst = custom_get_instance (cat, counter, name);
1928 addr = custom_get_value_address (counter, inst);
1929 if (!foreach_data->cb (cat->name, name, type, addr ? *(gint64*)addr : 0, foreach_data->data))
1938 mono_perfcounter_foreach (PerfCounterEnumCallback cb, gpointer data)
1940 PerfCounterForeachData foreach_data = { cb, data };
1944 foreach_shared_item (mono_perfcounter_foreach_shared_item, &foreach_data);
1951 mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString* instance, MonoString* machine, int *type, MonoBoolean *custom)
1953 g_assert_not_reached ();
1957 mono_perfcounter_get_sample (void *impl, MonoBoolean only_value, MonoCounterSample *sample)
1959 g_assert_not_reached ();
1963 mono_perfcounter_update_value (void *impl, MonoBoolean do_incr, gint64 value)
1965 g_assert_not_reached ();
1969 mono_perfcounter_free_data (void *impl)
1971 g_assert_not_reached ();
1974 /* Category icalls */
1976 mono_perfcounter_category_del (MonoString *name)
1978 g_assert_not_reached ();
1982 mono_perfcounter_category_help (MonoString *category, MonoString *machine)
1984 g_assert_not_reached ();
1988 mono_perfcounter_category_exists (MonoString *counter, MonoString *category, MonoString *machine)
1990 g_assert_not_reached ();
1994 mono_perfcounter_create (MonoString *category, MonoString *help, int type, MonoArray *items)
1996 g_assert_not_reached ();
2000 mono_perfcounter_instance_exists (MonoString *instance, MonoString *category, MonoString *machine)
2002 g_assert_not_reached ();
2006 mono_perfcounter_category_names (MonoString *machine)
2008 g_assert_not_reached ();
2012 mono_perfcounter_counter_names (MonoString *category, MonoString *machine)
2014 g_assert_not_reached ();
2018 mono_perfcounter_instance_names (MonoString *category, MonoString *machine)
2020 g_assert_not_reached ();