-/*
- * mono-perfcounters.c
+/**
+ * \file
*
* Performance counters support.
*
#include <mach/message.h>
#include <mach/mach_host.h>
#include <mach/host_info.h>
+#include <sys/sysctl.h>
#endif
-#if defined (__NetBSD__) || defined (__APPLE__)
+#if defined (__NetBSD__)
+#include <sys/param.h>
#include <sys/sysctl.h>
+#include <sys/vmmeter.h>
#endif
#include "metadata/mono-perfcounters.h"
#include "metadata/appdomain.h"
#include "utils/mono-networkinterfaces.h"
#include "utils/mono-error-internals.h"
#include "utils/atomic.h"
-#include <mono/io-layer/io-layer.h>
+#include "utils/unlocked.h"
/* map of CounterSample.cs */
struct _MonoCounterSample {
int mib[2] = {
CTL_HW,
#ifdef __NetBSD__
- HW_PHYSMEM
+ HW_PHYSMEM64
#else
HW_MEMSIZE
#endif
#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();
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;
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;
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;
}
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;
SharedInstance* inst;
char *name;
- mono_error_init (error);
+ error_init (error);
scounter = find_custom_counter (cat, counter);
if (!scounter)
return NULL;
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;
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;
}
/*
return FALSE;
}
+/* this is an icall */
MonoArray*
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;
}
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;
}
}
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;
}
{
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) {
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;
}
{
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;
int res;
void **buf = NULL;
MonoArray *array;
- mono_error_init (error);
+ error_init (error);
do {
count *= 2;
g_free (buf);
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;
}
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);
{
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);
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);
}
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);