Merge pull request #2324 from akoeplinger/caching-locking
[mono.git] / mono / metadata / mono-perfcounters.c
index 7c95c69a29faa9fdf0b42979d581a6895da1e773..e622308066a44d2e8d632909c69007b00796381b 100644 (file)
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
 #endif
+#if defined (__APPLE__)
+#include <mach/message.h>
+#include <mach/mach_host.h>
+#include <mach/host_info.h>
+#endif
 #if defined (__NetBSD__) || defined (__APPLE__)
 #include <sys/sysctl.h>
 #endif
@@ -148,8 +153,8 @@ enum {
 };
 
 static mono_mutex_t perfctr_mutex;
-#define perfctr_lock() mono_mutex_lock (&perfctr_mutex)
-#define perfctr_unlock() mono_mutex_unlock (&perfctr_mutex)
+#define perfctr_lock() mono_os_mutex_lock (&perfctr_mutex)
+#define perfctr_unlock() mono_os_mutex_unlock (&perfctr_mutex)
 
 typedef struct {
        char reserved [16];
@@ -354,9 +359,9 @@ load_sarea_for_pid (int pid)
        perfctr_lock ();
        if (pid_to_shared_area == NULL)
                pid_to_shared_area = g_hash_table_new (NULL, NULL);
-       data = g_hash_table_lookup (pid_to_shared_area, GINT_TO_POINTER (pid));
+       data = (ExternalSArea *)g_hash_table_lookup (pid_to_shared_area, GINT_TO_POINTER (pid));
        if (!data) {
-               area = mono_shared_area_for_pid (GINT_TO_POINTER (pid));
+               area = (MonoSharedArea *)mono_shared_area_for_pid (GINT_TO_POINTER (pid));
                if (area) {
                        data = g_new (ExternalSArea, 1);
                        data->sarea = area;
@@ -364,7 +369,7 @@ load_sarea_for_pid (int pid)
                        g_hash_table_insert (pid_to_shared_area, GINT_TO_POINTER (pid), data);
                }
        } else {
-               area = data->sarea;
+               area = (MonoSharedArea *)data->sarea;
                data->refcount ++;
        }
        perfctr_unlock ();
@@ -375,7 +380,7 @@ static void
 unref_pid_unlocked (int pid)
 {
        ExternalSArea *data;
-       data = g_hash_table_lookup (pid_to_shared_area, GINT_TO_POINTER (pid));
+       data = (ExternalSArea *)g_hash_table_lookup (pid_to_shared_area, GINT_TO_POINTER (pid));
        if (data) {
                data->refcount--;
                if (!data->refcount) {
@@ -455,6 +460,76 @@ mono_determine_physical_ram_size (void)
 #endif
 }
 
+static guint64
+mono_determine_physical_ram_available_size (void)
+{
+#if defined (TARGET_WIN32)
+       MEMORYSTATUSEX memstat;
+
+       memstat.dwLength = sizeof (memstat);
+       GlobalMemoryStatusEx (&memstat);
+       return (guint64)memstat.ullAvailPhys;
+
+#elif defined (__NetBSD__)
+       struct vmtotal vm_total;
+       guint64 page_size;
+       int mib [2];
+       size_t len;
+
+
+       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
+       };
+       len = sizeof (page_size);
+       sysctl (mib, 2, &page_size, &len, NULL, 0
+
+       return ((guint64) value.t_free * page_size) / 1024;
+#elif defined (__APPLE__)
+       mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
+       vm_statistics_data_t vmstat;
+       if (KERN_SUCCESS != host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmstat, &count)) {
+               g_warning ("Mono was unable to retrieve memory usage!");
+               return 0;
+       }
+
+       return (guint64) vmstat.free_count;
+
+#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_AVPHYS_PAGES
+       num_pages = (guint64)sysconf (_SC_AVPHYS_PAGES);
+#endif
+
+       if (!page_size || !num_pages) {
+               g_warning ("Your operating system's sysconf (3) function doesn't correctly report physical memory size!");
+               return 0;
+       }
+
+       return page_size * num_pages;
+#else
+       return 0;
+#endif
+}
+
 void
 mono_perfcounters_init (void)
 {
@@ -462,9 +537,9 @@ mono_perfcounters_init (void)
        d_offset += 7;
        d_offset &= ~7;
 
-       mono_mutex_init_recursive (&perfctr_mutex);
+       mono_os_mutex_init_recursive (&perfctr_mutex);
 
-       shared_area = mono_shared_area ();
+       shared_area = (MonoSharedArea *)mono_shared_area ();
        shared_area->counters_start = G_STRUCT_OFFSET (MonoSharedArea, counters);
        shared_area->counters_size = sizeof (MonoPerfCounters);
        shared_area->data_start = d_offset;
@@ -570,7 +645,7 @@ typedef struct {
 static gboolean
 category_search (SharedHeader *header, void *data)
 {
-       CatSearch *search = data;
+       CatSearch *search = (CatSearch *)data;
        if (header->ftype == FTYPE_CATEGORY) {
                SharedCategory *cat = (SharedCategory*)header;
                if (mono_string_compare_ascii (search->name, cat->name) == 0) {
@@ -594,7 +669,7 @@ find_custom_category (MonoString *name)
 static gboolean
 category_collect (SharedHeader *header, void *data)
 {
-       GSList **list = data;
+       GSList **list = (GSList **)data;
        if (header->ftype == FTYPE_CATEGORY) {
                *list = g_slist_prepend (*list, header);
        }
@@ -643,7 +718,7 @@ typedef struct {
 static gboolean
 instance_search (SharedHeader *header, void *data)
 {
-       InstanceSearch *search = data;
+       InstanceSearch *search = (InstanceSearch *)data;
        if (header->ftype == FTYPE_INSTANCE) {
                SharedInstance *ins = (SharedInstance*)header;
                if (search->cat_offset == ins->category_offset) {
@@ -815,7 +890,7 @@ network_cleanup (ImplVtable *vtable)
        if (vtable == NULL)
                return;
 
-       narg = vtable->arg;
+       narg = (NetworkVtableArg *)vtable->arg;
        if (narg == NULL)
                return;
 
@@ -917,6 +992,9 @@ mono_mem_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample
        case COUNTER_MEM_PHYS_TOTAL:
                sample->rawValue = mono_determine_physical_ram_size ();;
                return TRUE;
+       case COUNTER_MEM_PHYS_AVAILABLE:
+               sample->rawValue = mono_determine_physical_ram_available_size ();;
+               return TRUE;
        }
        return FALSE;
 }
@@ -1141,7 +1219,7 @@ static gint64
 custom_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value)
 {
        /* FIXME: check writability */
-       guint64 *ptr = vtable->arg;
+       guint64 *ptr = (guint64 *)vtable->arg;
        if (ptr) {
                if (do_incr) {
                        /* FIXME: we need to do this atomically */
@@ -1160,14 +1238,13 @@ custom_get_instance (SharedCategory *cat, SharedCounter *scounter, char* name)
 {
        SharedInstance* inst;
        char *p;
-       int size, data_offset;
+       int size;
        inst = find_custom_instance (cat, name);
        if (inst)
                return inst;
        size = sizeof (SharedInstance) + strlen (name);
        size += 7;
        size &= ~7;
-       data_offset = size;
        size += (sizeof (guint64) * cat->num_counters);
        perfctr_lock ();
        inst = (SharedInstance*) shared_data_reserve_room (size, FTYPE_INSTANCE);
@@ -1227,7 +1304,7 @@ custom_get_impl (SharedCategory *cat, MonoString* counter, MonoString* instance,
        g_free (name);
        if (!inst)
                return NULL;
-       return custom_vtable (scounter, inst, custom_get_value_address (scounter, inst));
+       return custom_vtable (scounter, inst, (char *)custom_get_value_address (scounter, inst));
 }
 
 static const CategoryDesc*
@@ -1284,7 +1361,7 @@ mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString
 MonoBoolean
 mono_perfcounter_get_sample (void *impl, MonoBoolean only_value, MonoCounterSample *sample)
 {
-       ImplVtable *vtable = impl;
+       ImplVtable *vtable = (ImplVtable *)impl;
        if (vtable && vtable->sample)
                return vtable->sample (vtable, only_value, sample);
        return FALSE;
@@ -1293,7 +1370,7 @@ mono_perfcounter_get_sample (void *impl, MonoBoolean only_value, MonoCounterSamp
 gint64
 mono_perfcounter_update_value (void *impl, MonoBoolean do_incr, gint64 value)
 {
-       ImplVtable *vtable = impl;
+       ImplVtable *vtable = (ImplVtable *)impl;
        if (vtable && vtable->update)
                return vtable->update (vtable, do_incr, value);
        return 0;
@@ -1302,7 +1379,7 @@ mono_perfcounter_update_value (void *impl, MonoBoolean do_incr, gint64 value)
 void
 mono_perfcounter_free_data (void *impl)
 {
-       ImplVtable *vtable = impl;
+       ImplVtable *vtable = (ImplVtable *)impl;
        if (vtable && vtable->cleanup)
                vtable->cleanup (vtable);
        g_free (impl);
@@ -1519,7 +1596,7 @@ mono_perfcounter_category_names (MonoString *machine)
                mono_array_setref (res, i, mono_string_new (domain, cdesc->name));
        }
        for (tmp = custom_categories; tmp; tmp = tmp->next) {
-               SharedCategory *scat = tmp->data;
+               SharedCategory *scat = (SharedCategory *)tmp->data;
                mono_array_setref (res, i, mono_string_new (domain, scat->name));
                i++;
        }
@@ -1597,7 +1674,7 @@ get_string_array_of_strings (void **array, int count)
        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];
+               char* p = (char *)array[i];
                mono_array_setref (res, i, mono_string_new (domain, p));
        }
 
@@ -1676,7 +1753,7 @@ get_custom_instances (MonoString *category)
                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;
+                       SharedInstance *inst = (SharedInstance *)tmp->data;
                        mono_array_setref (array, i, mono_string_new (mono_domain_get (), inst->instance_name));
                        i++;
                }
@@ -1719,14 +1796,13 @@ static gboolean
 mono_perfcounter_foreach_shared_item (SharedHeader *header, gpointer data)
 {
        int i;
-       char *p, *name, *help;
+       char *p, *name;
        unsigned char type;
-       int seq_num;
        void *addr;
        SharedCategory *cat;
        SharedCounter *counter;
        SharedInstance *inst;
-       PerfCounterForeachData *foreach_data = data;
+       PerfCounterForeachData *foreach_data = (PerfCounterForeachData *)data;
 
        if (header->ftype == FTYPE_CATEGORY) {
                cat = (SharedCategory*)header;
@@ -1738,10 +1814,10 @@ mono_perfcounter_foreach_shared_item (SharedHeader *header, gpointer data)
                for (i = 0; i < cat->num_counters; ++i) {
                        counter = (SharedCounter*) p;
                        type = (unsigned char)*p++;
-                       seq_num = (int)*p++;
+                       /* seq_num = (int)* */ p++;
                        name = p;
                        p += strlen (p) + 1;
-                       help = p;
+                       /* help = p; */
                        p += strlen (p) + 1;
 
                        inst = custom_get_instance (cat, counter, name);