[TSan] Tackle MonoPerfCounters (#5413)
authorArmin Hasitzka <cherusker@users.noreply.github.com>
Fri, 8 Sep 2017 09:20:28 +0000 (11:20 +0200)
committermonojenkins <jo.shields+jenkins@xamarin.com>
Fri, 8 Sep 2017 09:20:28 +0000 (11:20 +0200)
[TSan] Tackle MonoPerfCounters

With `MonoPerfCounters` taking part in many races, I thought it's finally time to attend to it. If I am not mistaken, most (if not all) load / store operations can be interlocked. If I am wrong, I would kindly ask to quickly comment the respective perf. critial operations and I will change them to `Unlocked* ()`.

Furthermore, a few details:

* updated all fields to signed types as `Interlocked* ()` functions exist for these types already
* upgraded a few values to `64-bit` as other `64-bit` values are assigned to them
* fixed a few `FIXME`s in `predef_writable_update ()` that were connected to `Interlocked* ()` functions

14 files changed:
mono/metadata/boehm-gc.c
mono/metadata/class-internals.h
mono/metadata/domain.c
mono/metadata/image.c
mono/metadata/monitor.c
mono/metadata/mono-perfcounters-def.h
mono/metadata/mono-perfcounters.c
mono/metadata/null-gc-handles.c
mono/metadata/object.c
mono/metadata/sgen-client-mono.h
mono/metadata/sgen-mono.c
mono/mini/mini-exceptions.c
mono/mini/mini.c
mono/utils/unlocked.h

index 33ccf0294164002e9d62603d38005b5244c1b29e..482a7425d030caa2a41fde1ec756c1aa187c35ee 100644 (file)
@@ -278,7 +278,7 @@ void
 mono_gc_collect (int generation)
 {
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->gc_induced++;
+       InterlockedIncrement (&mono_perfcounters->gc_induced);
 #endif
        GC_gcollect ();
 }
@@ -457,7 +457,7 @@ on_gc_notification (GC_EventType event)
                MONO_GC_BEGIN (1);
 #ifndef DISABLE_PERFCOUNTERS
                if (mono_perfcounters)
-                       mono_perfcounters->gc_collections0++;
+                       InterlockedIncrement (&mono_perfcounters->gc_collections0);
 #endif
                InterlockedIncrement (&gc_stats.major_gc_count);
                gc_start_time = mono_100ns_ticks ();
@@ -477,10 +477,11 @@ on_gc_notification (GC_EventType event)
                if (mono_perfcounters) {
                        guint64 heap_size = GC_get_heap_size ();
                        guint64 used_size = heap_size - GC_get_free_bytes ();
-                       mono_perfcounters->gc_total_bytes = used_size;
-                       mono_perfcounters->gc_committed_bytes = heap_size;
-                       mono_perfcounters->gc_reserved_bytes = heap_size;
-                       mono_perfcounters->gc_gen0size = heap_size;
+                       /* FIXME: change these to InterlockedWrite64 () */
+                       UnlockedWrite64 (&mono_perfcounters->gc_total_bytes, used_size);
+                       UnlockedWrite64 (&mono_perfcounters->gc_committed_bytes, heap_size);
+                       UnlockedWrite64 (&mono_perfcounters->gc_reserved_bytes, heap_size);
+                       UnlockedWrite64 (&mono_perfcounters->gc_gen0size, heap_size);
                }
 #endif
                UnlockedAdd64 (&gc_stats.major_gc_time, mono_100ns_ticks () - gc_start_time);
@@ -522,9 +523,10 @@ on_gc_heap_resize (size_t new_size)
        guint64 heap_size = GC_get_heap_size ();
 #ifndef DISABLE_PERFCOUNTERS
        if (mono_perfcounters) {
-               mono_perfcounters->gc_committed_bytes = heap_size;
-               mono_perfcounters->gc_reserved_bytes = heap_size;
-               mono_perfcounters->gc_gen0size = heap_size;
+               /* FIXME: change these to InterlockedWrite64 () */
+               UnlockedWrite64 (&mono_perfcounters->gc_committed_bytes, heap_size);
+               UnlockedWrite64 (&mono_perfcounters->gc_reserved_bytes, heap_size);
+               UnlockedWrite64 (&mono_perfcounters->gc_gen0size, heap_size);
        }
 #endif
 
@@ -1736,7 +1738,7 @@ alloc_handle (HandleData *handles, MonoObject *obj, gboolean track)
        }
 
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->gc_num_handles++;
+       InterlockedIncrement (&mono_perfcounters->gc_num_handles);
 #endif
        unlock_handles (handles);
        res = MONO_GC_HANDLE (slot, handles->type);
@@ -1934,7 +1936,7 @@ mono_gchandle_free (guint32 gchandle)
                /* print a warning? */
        }
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->gc_num_handles--;
+       InterlockedDecrement (&mono_perfcounters->gc_num_handles);
 #endif
        /*g_print ("freed entry %d of type %d\n", slot, handles->type);*/
        unlock_handles (handles);
index 67f360e975e3bd44ed0f3f8213170d341c133904..2b3a0b42aa31a9359c2bd01ed41803e6beda8942 100644 (file)
@@ -792,78 +792,78 @@ typedef struct {
  */
 typedef struct {
        /* JIT category */
-       guint32 jit_methods;
-       guint32 jit_bytes;
-       guint32 jit_time;
-       guint32 jit_failures;
+       gint32 jit_methods;
+       gint32 jit_bytes;
+       gint32 jit_time;
+       gint32 jit_failures;
        /* Exceptions category */
-       guint32 exceptions_thrown;
-       guint32 exceptions_filters;
-       guint32 exceptions_finallys;
-       guint32 exceptions_depth;
-       guint32 aspnet_requests_queued;
-       guint32 aspnet_requests;
+       gint32 exceptions_thrown;
+       gint32 exceptions_filters;
+       gint32 exceptions_finallys;
+       gint32 exceptions_depth;
+       gint32 aspnet_requests_queued;
+       gint32 aspnet_requests;
        /* Memory category */
-       guint32 gc_collections0;
-       guint32 gc_collections1;
-       guint32 gc_collections2;
-       guint32 gc_promotions0;
-       guint32 gc_promotions1;
-       guint32 gc_promotion_finalizers;
-       guint32 gc_gen0size;
-       guint32 gc_gen1size;
-       guint32 gc_gen2size;
-       guint32 gc_lossize;
-       guint32 gc_fin_survivors;
-       guint32 gc_num_handles;
-       guint32 gc_allocated;
-       guint32 gc_induced;
-       guint32 gc_time;
-       guint32 gc_total_bytes;
-       guint32 gc_committed_bytes;
-       guint32 gc_reserved_bytes;
-       guint32 gc_num_pinned;
-       guint32 gc_sync_blocks;
+       gint32 gc_collections0;
+       gint32 gc_collections1;
+       gint32 gc_collections2;
+       gint32 gc_promotions0;
+       gint32 gc_promotions1;
+       gint32 gc_promotion_finalizers;
+       gint64 gc_gen0size;
+       gint64 gc_gen1size;
+       gint64 gc_gen2size;
+       gint32 gc_lossize;
+       gint32 gc_fin_survivors;
+       gint32 gc_num_handles;
+       gint32 gc_allocated;
+       gint32 gc_induced;
+       gint32 gc_time;
+       gint64 gc_total_bytes;
+       gint64 gc_committed_bytes;
+       gint64 gc_reserved_bytes;
+       gint32 gc_num_pinned;
+       gint32 gc_sync_blocks;
        /* Remoting category */
-       guint32 remoting_calls;
-       guint32 remoting_channels;
-       guint32 remoting_proxies;
-       guint32 remoting_classes;
-       guint32 remoting_objects;
-       guint32 remoting_contexts;
+       gint32 remoting_calls;
+       gint32 remoting_channels;
+       gint32 remoting_proxies;
+       gint32 remoting_classes;
+       gint32 remoting_objects;
+       gint32 remoting_contexts;
        /* Loader category */
-       guint32 loader_classes;
-       guint32 loader_total_classes;
-       guint32 loader_appdomains;
-       guint32 loader_total_appdomains;
-       guint32 loader_assemblies;
-       guint32 loader_total_assemblies;
-       guint32 loader_failures;
-       guint32 loader_bytes;
-       guint32 loader_appdomains_uloaded;
+       gint32 loader_classes;
+       gint32 loader_total_classes;
+       gint32 loader_appdomains;
+       gint32 loader_total_appdomains;
+       gint32 loader_assemblies;
+       gint32 loader_total_assemblies;
+       gint32 loader_failures;
+       gint32 loader_bytes;
+       gint32 loader_appdomains_uloaded;
        /* Threads and Locks category  */
-       guint32 thread_contentions;
-       guint32 thread_queue_len;
-       guint32 thread_queue_max;
-       guint32 thread_num_logical;
-       guint32 thread_num_physical;
-       guint32 thread_cur_recognized;
-       guint32 thread_num_recognized;
+       gint32 thread_contentions;
+       gint32 thread_queue_len;
+       gint32 thread_queue_max;
+       gint32 thread_num_logical;
+       gint32 thread_num_physical;
+       gint32 thread_cur_recognized;
+       gint32 thread_num_recognized;
        /* Interop category */
-       guint32 interop_num_ccw;
-       guint32 interop_num_stubs;
-       guint32 interop_num_marshals;
+       gint32 interop_num_ccw;
+       gint32 interop_num_stubs;
+       gint32 interop_num_marshals;
        /* Security category */
-       guint32 security_num_checks;
-       guint32 security_num_link_checks;
-       guint32 security_time;
-       guint32 security_depth;
-       guint32 unused;
+       gint32 security_num_checks;
+       gint32 security_num_link_checks;
+       gint32 security_time;
+       gint32 security_depth;
+       gint32 unused;
        /* Threadpool */
-       guint64 threadpool_workitems;
-       guint64 threadpool_ioworkitems;
-       guint threadpool_threads;
-       guint threadpool_iothreads;
+       gint64 threadpool_workitems;
+       gint64 threadpool_ioworkitems;
+       gint32 threadpool_threads;
+       gint32 threadpool_iothreads;
 } MonoPerfCounters;
 
 extern MonoPerfCounters *mono_perfcounters;
index de2a6970f73c52d51acec59ab9e4a6416549dab8..b0e7068104da81833aea19ca355510216da3032f 100644 (file)
@@ -430,8 +430,8 @@ mono_domain_create (void)
        mono_appdomains_unlock ();
 
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->loader_appdomains++;
-       mono_perfcounters->loader_total_appdomains++;
+       InterlockedIncrement (&mono_perfcounters->loader_appdomains);
+       InterlockedIncrement (&mono_perfcounters->loader_total_appdomains);
 #endif
 
        mono_debug_domain_create (domain);
@@ -1171,7 +1171,8 @@ mono_domain_free (MonoDomain *domain, gboolean force)
                mono_code_manager_invalidate (domain->code_mp);
        } else {
 #ifndef DISABLE_PERFCOUNTERS
-               mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (domain->mp);
+               /* FIXME: use an explicit subtraction method as soon as it's available */
+               InterlockedAdd (&mono_perfcounters->loader_bytes, -1 * mono_mempool_get_allocated (domain->mp));
 #endif
                mono_mempool_destroy (domain->mp);
                domain->mp = NULL;
@@ -1218,7 +1219,7 @@ mono_domain_free (MonoDomain *domain, gboolean force)
        mono_gc_free_fixed (domain);
 
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->loader_appdomains--;
+       InterlockedDecrement (&mono_perfcounters->loader_appdomains);
 #endif
 
        if (domain == mono_root_domain)
@@ -1286,7 +1287,7 @@ mono_domain_alloc (MonoDomain *domain, guint size)
 
        mono_domain_lock (domain);
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->loader_bytes += size;
+       InterlockedAdd (&mono_perfcounters->loader_bytes, size);
 #endif
        res = mono_mempool_alloc (domain->mp, size);
        mono_domain_unlock (domain);
@@ -1306,7 +1307,7 @@ mono_domain_alloc0 (MonoDomain *domain, guint size)
 
        mono_domain_lock (domain);
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->loader_bytes += size;
+       InterlockedAdd (&mono_perfcounters->loader_bytes, size);
 #endif
        res = mono_mempool_alloc0 (domain->mp, size);
        mono_domain_unlock (domain);
index 3f4dd249c6d1b189901384dd07c1e8868ac638e9..6ec372bbe9f2548318b6f68216c2658d8db43176 100644 (file)
@@ -2172,7 +2172,8 @@ mono_image_close_finish (MonoImage *image)
        mono_image_close_all (image->modules, image->module_count);
 
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (image->mempool);
+       /* FIXME: use an explicit subtraction method as soon as it's available */
+       InterlockedAdd (&mono_perfcounters->loader_bytes, -1 * mono_mempool_get_allocated (image->mempool));
 #endif
 
        if (!image_is_dynamic (image)) {
@@ -2707,7 +2708,7 @@ mono_image_alloc (MonoImage *image, guint size)
        gpointer res;
 
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->loader_bytes += size;
+       InterlockedAdd (&mono_perfcounters->loader_bytes, size);
 #endif
        mono_image_lock (image);
        res = mono_mempool_alloc (image->mempool, size);
@@ -2722,7 +2723,7 @@ mono_image_alloc0 (MonoImage *image, guint size)
        gpointer res;
 
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->loader_bytes += size;
+       InterlockedAdd (&mono_perfcounters->loader_bytes, size);
 #endif
        mono_image_lock (image);
        res = mono_mempool_alloc0 (image->mempool, size);
@@ -2737,7 +2738,7 @@ mono_image_strdup (MonoImage *image, const char *s)
        char *res;
 
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->loader_bytes += strlen (s);
+       InterlockedAdd (&mono_perfcounters->loader_bytes, strlen (s));
 #endif
        mono_image_lock (image);
        res = mono_mempool_strdup (image->mempool, s);
@@ -2754,7 +2755,7 @@ mono_image_strdup_vprintf (MonoImage *image, const char *format, va_list args)
        buf = mono_mempool_strdup_vprintf (image->mempool, format, args);
        mono_image_unlock (image);
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->loader_bytes += strlen (buf);
+       InterlockedAdd (&mono_perfcounters->loader_bytes, strlen (buf));
 #endif
        return buf;
 }
index 702a47c654f285402c0cad5bb601f345e3a78ef1..c371f0f3c476c0e6756c97460e5c37e9cd3e1bc5 100644 (file)
@@ -373,7 +373,7 @@ mon_finalize (MonoThreadsSync *mon)
        mon->data = monitor_freelist;
        monitor_freelist = mon;
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->gc_sync_blocks--;
+       InterlockedDecrement (&mono_perfcounters->gc_sync_blocks);
 #endif
 }
 
@@ -445,7 +445,7 @@ mon_new (gsize id)
        new_->data = NULL;
        
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->gc_sync_blocks++;
+       InterlockedIncrement (&mono_perfcounters->gc_sync_blocks);
 #endif
        return new_;
 }
@@ -792,7 +792,7 @@ retry:
 
        /* The object must be locked by someone else... */
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->thread_contentions++;
+       InterlockedIncrement (&mono_perfcounters->thread_contentions);
 #endif
 
        /* If ms is 0 we don't block, but just fail straight away */
@@ -874,8 +874,8 @@ retry_contended:
        waitms = ms;
        
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->thread_queue_len++;
-       mono_perfcounters->thread_queue_max++;
+       InterlockedIncrement (&mono_perfcounters->thread_queue_len);
+       InterlockedIncrement (&mono_perfcounters->thread_queue_max);
 #endif
        thread = mono_thread_internal_current ();
 
@@ -909,7 +909,7 @@ retry_contended:
 
 done_waiting:
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->thread_queue_len--;
+       InterlockedDecrement (&mono_perfcounters->thread_queue_len);
 #endif
 
        if (wait_ret == MONO_SEM_TIMEDWAIT_RET_ALERTED && !allow_interruption) {
index c72b708532af58969d727a03353bda785727f477..3a4dbc89110f50d9e12e6100502fa7fa228b25f9 100644 (file)
@@ -59,18 +59,18 @@ PERFCTR_COUNTER(GC_PROM1, "Promoted Memory from Gen 1", "", NumberOfItems32, gc_
 PERFCTR_COUNTER(GC_PROM0SEC, "Gen 0 Promoted Bytes/Sec", "", RateOfCountsPerSecond32, gc_promotions0)
 PERFCTR_COUNTER(GC_PROM1SEC, "Gen 1 Promoted Bytes/Sec", "", RateOfCountsPerSecond32, gc_promotions1)
 PERFCTR_COUNTER(GC_PROMFIN, "Promoted Finalization-Memory from Gen 0", "", NumberOfItems32, gc_promotion_finalizers)
-PERFCTR_COUNTER(GC_GEN0SIZE, "Gen 0 heap size", "", NumberOfItems32, gc_gen0size)
-PERFCTR_COUNTER(GC_GEN1SIZE, "Gen 1 heap size", "", NumberOfItems32, gc_gen1size)
-PERFCTR_COUNTER(GC_GEN2SIZE, "Gen 2 heap size", "", NumberOfItems32, gc_gen2size)
+PERFCTR_COUNTER(GC_GEN0SIZE, "Gen 0 heap size", "", NumberOfItems64, gc_gen0size)
+PERFCTR_COUNTER(GC_GEN1SIZE, "Gen 1 heap size", "", NumberOfItems64, gc_gen1size)
+PERFCTR_COUNTER(GC_GEN2SIZE, "Gen 2 heap size", "", NumberOfItems64, gc_gen2size)
 PERFCTR_COUNTER(GC_LOSIZE, "Large Object Heap size", "", NumberOfItems32, gc_lossize)
 PERFCTR_COUNTER(GC_FINSURV, "Finalization Survivors", "", NumberOfItems32, gc_fin_survivors)
 PERFCTR_COUNTER(GC_NHANDLES, "# GC Handles", "", NumberOfItems32, gc_num_handles)
 PERFCTR_COUNTER(GC_BYTESSEC, "Allocated Bytes/sec", "", RateOfCountsPerSecond32, gc_allocated)
 PERFCTR_COUNTER(GC_INDGC, "# Induced GC", "", NumberOfItems32, gc_induced)
 PERFCTR_COUNTER(GC_PERCTIME, "% Time in GC", "", RawFraction, gc_time)
-PERFCTR_COUNTER(GC_BYTES, "# Bytes in all Heaps", "", NumberOfItems32, gc_total_bytes)
-PERFCTR_COUNTER(GC_COMMBYTES, "# Total committed Bytes", "", NumberOfItems32, gc_committed_bytes)
-PERFCTR_COUNTER(GC_RESBYTES, "# Total reserved Bytes", "", NumberOfItems32, gc_reserved_bytes)
+PERFCTR_COUNTER(GC_BYTES, "# Bytes in all Heaps", "", NumberOfItems64, gc_total_bytes)
+PERFCTR_COUNTER(GC_COMMBYTES, "# Total committed Bytes", "", NumberOfItems64, gc_committed_bytes)
+PERFCTR_COUNTER(GC_RESBYTES, "# Total reserved Bytes", "", NumberOfItems64, gc_reserved_bytes)
 PERFCTR_COUNTER(GC_PINNED, "# of Pinned Objects", "", NumberOfItems32, gc_num_pinned)
 PERFCTR_COUNTER(GC_SYNKB, "# of Sink Blocks in use", "", NumberOfItems32, gc_sync_blocks)
 
index f4ec3e34c2b9a8633eec90b1aa16bf6a02a9b7f6..1a3123a30aad58811bbf8d07c6d0581ac029474e 100644 (file)
@@ -48,6 +48,7 @@
 #include "utils/mono-networkinterfaces.h"
 #include "utils/mono-error-internals.h"
 #include "utils/atomic.h"
+#include "utils/unlocked.h"
 
 /* map of CounterSample.cs */
 struct _MonoCounterSample {
@@ -1073,52 +1074,52 @@ predef_writable_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounter
        case CATEGORY_EXC:
                switch (id) {
                case COUNTER_EXC_THROWN:
-                       sample->rawValue = mono_perfcounters->exceptions_thrown;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->exceptions_thrown);
                        return TRUE;
                }
                break;
        case CATEGORY_ASPNET:
                switch (id) {
                case COUNTER_ASPNET_REQ_Q:
-                       sample->rawValue = mono_perfcounters->aspnet_requests_queued;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->aspnet_requests_queued);
                        return TRUE;
                case COUNTER_ASPNET_REQ_TOTAL:
-                       sample->rawValue = mono_perfcounters->aspnet_requests;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->aspnet_requests);
                        return TRUE;
                }
                break;
        case CATEGORY_THREADPOOL:
                switch (id) {
                case COUNTER_THREADPOOL_WORKITEMS:
-                       sample->rawValue = mono_perfcounters->threadpool_workitems;
+                       sample->rawValue = InterlockedRead64 (&mono_perfcounters->threadpool_workitems);
                        return TRUE;
                case COUNTER_THREADPOOL_IOWORKITEMS:
-                       sample->rawValue = mono_perfcounters->threadpool_ioworkitems;
+                       sample->rawValue = InterlockedRead64 (&mono_perfcounters->threadpool_ioworkitems);
                        return TRUE;
                case COUNTER_THREADPOOL_THREADS:
-                       sample->rawValue = mono_perfcounters->threadpool_threads;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->threadpool_threads);
                        return TRUE;
                case COUNTER_THREADPOOL_IOTHREADS:
-                       sample->rawValue = mono_perfcounters->threadpool_iothreads;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->threadpool_iothreads);
                        return TRUE;
                }
                break;
        case CATEGORY_JIT:
                switch (id) {
                case COUNTER_JIT_BYTES:
-                       sample->rawValue = mono_perfcounters->jit_bytes;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->jit_bytes);
                        return TRUE;
                case COUNTER_JIT_METHODS:
-                       sample->rawValue = mono_perfcounters->jit_methods;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->jit_methods);
                        return TRUE;
                case COUNTER_JIT_TIME:
-                       sample->rawValue = mono_perfcounters->jit_time;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->jit_time);
                        return TRUE;
                case COUNTER_JIT_BYTES_PSEC:
-                       sample->rawValue = mono_perfcounters->jit_bytes;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->jit_bytes);
                        return TRUE;
                case COUNTER_JIT_FAILURES:
-                       sample->rawValue = mono_perfcounters->jit_failures;
+                       sample->rawValue = InterlockedRead (&mono_perfcounters->jit_failures);
                        return TRUE;
                }
                break;
@@ -1129,7 +1130,7 @@ predef_writable_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounter
 static gint64
 predef_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value)
 {
-       guint32 *volatile ptr = NULL;
+       gint32 *volatile ptr = NULL;
        gint64 *volatile ptr64 = NULL;
        int cat_id = GPOINTER_TO_INT (vtable->arg);
        int id = cat_id >> 16;
@@ -1143,8 +1144,8 @@ predef_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value)
                break;
        case CATEGORY_THREADPOOL:
                switch (id) {
-               case COUNTER_THREADPOOL_WORKITEMS: ptr64 = (gint64 *) &mono_perfcounters->threadpool_workitems; break;
-               case COUNTER_THREADPOOL_IOWORKITEMS: ptr64 = (gint64 *) &mono_perfcounters->threadpool_ioworkitems; break;
+               case COUNTER_THREADPOOL_WORKITEMS: ptr64 = &mono_perfcounters->threadpool_workitems; break;
+               case COUNTER_THREADPOOL_IOWORKITEMS: ptr64 = &mono_perfcounters->threadpool_ioworkitems; break;
                case COUNTER_THREADPOOL_THREADS: ptr = &mono_perfcounters->threadpool_threads; break;
                case COUNTER_THREADPOOL_IOTHREADS: ptr = &mono_perfcounters->threadpool_iothreads; break;
                }
@@ -1153,29 +1154,23 @@ predef_writable_update (ImplVtable *vtable, MonoBoolean do_incr, gint64 value)
        if (ptr) {
                if (do_incr) {
                        if (value == 1)
-                               return InterlockedIncrement ((gint32 *) ptr); /* FIXME: sign */
+                               return InterlockedIncrement (ptr);
                        if (value == -1)
-                               return InterlockedDecrement ((gint32 *) ptr); /* FIXME: sign */
+                               return InterlockedDecrement (ptr);
 
-                       *ptr += value;
-                       return *ptr;
+                       return InterlockedAdd(ptr, value);
                }
                /* this can be non-atomic */
                *ptr = value;
                return value;
        } else if (ptr64) {
                if (do_incr) {
-                       /* FIXME: we need to do this atomically */
-                       /* No InterlockedIncrement64() yet */
-                       /*
                        if (value == 1)
-                               return InterlockedIncrement64 (ptr);
+                               return UnlockedIncrement64 (ptr64); /* FIXME: use InterlockedIncrement64 () */
                        if (value == -1)
-                               return InterlockedDecrement64 (ptr);
-                       */
+                               return UnlockedDecrement64 (ptr64); /* FIXME: use InterlockedDecrement64 () */
 
-                       *ptr64 += value;
-                       return *ptr64;
+                       return UnlockedAdd64 (ptr64, value); /* FIXME: use InterlockedAdd64 () */
                }
                /* this can be non-atomic */
                *ptr64 = value;
index caa0616464d4863525c2d15b81333eec5005b611..8bad1701b2507b3ad65f2b4069118d09b2ebd23c 100644 (file)
@@ -220,7 +220,7 @@ alloc_handle (HandleData *handles, MonoObject *obj, gboolean track)
        }
 
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->gc_num_handles++;
+       InterlockedIncrement (&mono_perfcounters->gc_num_handles);
 #endif
        unlock_handles (handles);
        res = MONO_GC_HANDLE (slot, handles->type);
@@ -412,7 +412,7 @@ mono_gchandle_free (guint32 gchandle)
                /* print a warning? */
        }
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->gc_num_handles--;
+       InterlockedDecrement (&mono_perfcounters->gc_num_handles);
 #endif
        /*g_print ("freed entry %d of type %d\n", slot, handles->type);*/
        unlock_handles (handles);
index 4ebc52bca25fdeb0a644e042c1b45fa89af53009..38dfb764e46f92ef329aed59ab559b4c070a3faf 100644 (file)
@@ -2565,7 +2565,7 @@ mono_remote_class (MonoDomain *domain, MonoStringHandle class_name, MonoClass *p
        rc->xdomain_vtable = NULL;
        rc->proxy_class_name = name;
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->loader_bytes += mono_string_length (MONO_HANDLE_RAW (class_name)) + 1;
+       InterlockedAdd (&mono_perfcounters->loader_bytes, mono_string_length (MONO_HANDLE_RAW (class_name)) + 1);
 #endif
 
        g_hash_table_insert (domain->proxy_vtable_hash, key, rc);
index a5ec02d480e21cb4477a3cf7e5f1eb4416465d0a..b163dcfee81dd909909271e3137a40a015113d9a 100644 (file)
@@ -297,9 +297,9 @@ sgen_client_binary_protocol_collection_begin (int minor_gc_count, int generation
 
 #ifndef DISABLE_PERFCOUNTERS
        if (generation == GENERATION_NURSERY)
-               mono_perfcounters->gc_collections0++;
+               InterlockedIncrement (&mono_perfcounters->gc_collections0);
        else
-               mono_perfcounters->gc_collections1++;
+               InterlockedIncrement (&mono_perfcounters->gc_collections1);
 #endif
 }
 
index 7f2a233401d7da565051c04dbd08f7faf851c95d..4cd30493fff80524e3b60b368623d7e2d35563c7 100644 (file)
@@ -2803,7 +2803,7 @@ void
 sgen_client_gchandle_created (int handle_type, GCObject *obj, guint32 handle)
 {
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->gc_num_handles++;
+       InterlockedIncrement (&mono_perfcounters->gc_num_handles);
 #endif
 
        MONO_PROFILER_RAISE (gc_handle_created, (handle, handle_type, obj));
@@ -2813,7 +2813,7 @@ void
 sgen_client_gchandle_destroyed (int handle_type, guint32 handle)
 {
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->gc_num_handles--;
+       InterlockedDecrement (&mono_perfcounters->gc_num_handles);
 #endif
 
        MONO_PROFILER_RAISE (gc_handle_deleted, (handle, handle_type));
index f15af494bb150609956f9baf5570fc1ed08ed9a3..611201eecd7f6a490714df7889f2431ed1d7209b 100644 (file)
@@ -1700,7 +1700,7 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi
 
                                if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
 #ifndef DISABLE_PERFCOUNTERS
-                                       mono_perfcounters->exceptions_filters++;
+                                       InterlockedIncrement (&mono_perfcounters->exceptions_filters);
 #endif
 
 #ifndef MONO_CROSS_COMPILE
@@ -2153,7 +2153,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                                        }
                                        mono_set_lmf (lmf);
 #ifndef DISABLE_PERFCOUNTERS
-                                       mono_perfcounters->exceptions_depth += frame_count;
+                                       InterlockedAdd (&mono_perfcounters->exceptions_depth, frame_count);
 #endif
                                        if (obj == (MonoObject *)domain->stack_overflow_ex)
                                                jit_tls->handling_stack_ovf = FALSE;
@@ -2175,7 +2175,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                                        MONO_PROFILER_RAISE (exception_clause, (method, i, ei->flags, ex_obj));
                                        jit_tls->orig_ex_ctx_set = FALSE;
 #ifndef DISABLE_PERFCOUNTERS
-                                       mono_perfcounters->exceptions_finallys++;
+                                       InterlockedIncrement (&mono_perfcounters->exceptions_finallys);
 #endif
                                }
                                if (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT || ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
@@ -2277,7 +2277,7 @@ mono_handle_exception (MonoContext *ctx, MonoObject *obj)
        MONO_REQ_GC_UNSAFE_MODE;
 
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->exceptions_thrown++;
+       InterlockedIncrement (&mono_perfcounters->exceptions_thrown);
 #endif
 
        return mono_handle_exception_internal (ctx, obj, FALSE, NULL);
index ee6ec6659bf1455c4c23f5703106ad311e2eafe1..4cfe898b0a085c284912893fd16961e504021ee3 100644 (file)
@@ -3875,8 +3875,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
 
        /* collect statistics */
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->jit_methods++;
-       mono_perfcounters->jit_bytes += header->code_size;
+       InterlockedIncrement (&mono_perfcounters->jit_methods);
+       InterlockedAdd (&mono_perfcounters->jit_bytes, header->code_size);
 #endif
        mono_jit_stats.allocated_code_size += cfg->code_len;
        code_size_ratio = cfg->code_len;
index a989dafdbc7f0b7fdb143bbf4974658ba5608ffd..6c4abcf468286674a1738b8276e37e9b9bd3e0ba 100644 (file)
@@ -31,6 +31,20 @@ UnlockedIncrement (gint32 *val)
        return ++*val;
 }
 
+MONO_UNLOCKED_ATTRS
+gint64
+UnlockedIncrement64 (gint64 *val)
+{
+       return ++*val;
+}
+
+MONO_UNLOCKED_ATTRS
+gint64
+UnlockedDecrement64 (gint64 *val)
+{
+       return --*val;
+}
+
 MONO_UNLOCKED_ATTRS
 gint32
 UnlockedDecrement (gint32 *val)
@@ -66,6 +80,13 @@ UnlockedWrite (gint32 *dest, gint32 val)
        *dest = val;
 }
 
+MONO_UNLOCKED_ATTRS
+void
+UnlockedWrite64 (gint64 *dest, gint64 val)
+{
+       *dest = val;
+}
+
 MONO_UNLOCKED_ATTRS
 gint32
 UnlockedRead (gint32 *src)