[gc counters] avoid using Interlocked*64 functions as they are broken on some arches...
authorBernhard Urban <bernhard.urban@xamarin.com>
Mon, 28 Aug 2017 05:57:00 +0000 (07:57 +0200)
committerGitHub <noreply@github.com>
Mon, 28 Aug 2017 05:57:00 +0000 (07:57 +0200)
They are implemented via a global lock, which can lead to deadlooks in
some situations, e.g.

```
-0  0xb6c92e14 in sigsuspend () from /lib/arm-linux-gnueabi/libc.so.6
-1  0x0043f3b4 in suspend_signal_handler (_dummy=35, info=0xb4afe6d0, context=0xb4afe750) at mono-threads-posix-signals.c:177
-2  <signal handler called>
-3  0xb6de6bc4 in __pthread_mutex_unlock_usercnt () from /lib/arm-linux-gnueabi/libpthread.so.0
-4  0x00440f00 in InterlockedCompareExchange64 (dest=0x530700 <worker+64>, exch=0, comp=0) at atomic.c:578
-5  0x002f228c in InterlockedRead64 (src=0x530700 <worker+64>) at ../../mono/utils/atomic.h:398
-6  0x002f29a0 in COUNTER_READ () at threadpool-worker-default.c:194
-7  0x002f3320 in worker_park () at threadpool-worker-default.c:426
-8  0x002f3774 in worker_thread (unused=0x0) at threadpool-worker-default.c:488
-9  0x002e66b0 in start_wrapper_internal (start_info=0x0, stack_ptr=0xb4b00000) at threads.c:982
-10 0x002e6894 in start_wrapper (data=0x5a8f38) at threads.c:1044
-11 0xb6de31a8 in start_thread () from /lib/arm-linux-gnueabi/libpthread.so.0
-12 0xb6d3a1bc in ?? () from /lib/arm-linux-gnueabi/libc.so.6
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

Thread 4 (Thread 0xb40ff440 (LWP 10198)):
-0  0xb6deb56c in __lll_lock_wait () from /lib/arm-linux-gnueabi/libpthread.so.0
-1  0xb6de584c in pthread_mutex_lock () from /lib/arm-linux-gnueabi/libpthread.so.0
-2  0x00440e6c in InterlockedCompareExchange64 (dest=0x559868 <gc_stats+8>, exch=2855648, comp=2844091) at atomic.c:570
-3  0x0039bdcc in InterlockedAdd64 (dest=0x559868 <gc_stats+8>, add=11557) at ../../mono/utils/atomic.h:392
-4  0x003a1b50 in collect_nursery (reason=0x5083f4 "Nursery full", is_overflow=0, unpin_queue=0x0) at sgen-gc.c:1865
-5  0x003a3794 in sgen_perform_collection (requested_size=4096, generation_to_collect=0, reason=0x5083f4 "Nursery full", wait_to_finish=0, stw=1) at sgen-gc.c:2539
-6  0x003a35f0 in sgen_ensure_free_space (size=4096, generation=0) at sgen-gc.c:2505
-7  0x00389db0 in sgen_alloc_obj_nolock (vtable=0xb4d174d0, size=64) at sgen-alloc.c:256
-8  0x0036e330 in mono_gc_alloc_vector (vtable=0xb4d174d0, size=64, max_length=12) at sgen-mono.c:1743
-9  0xb6c16a38 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
```

fixes https://bugzilla.xamarin.com/show_bug.cgi?id=59039

mono/metadata/boehm-gc.c
mono/sgen/sgen-gc.c

index a93f04a867d0512a93bd8aafd49c19656eea153c..33ccf0294164002e9d62603d38005b5244c1b29e 100644 (file)
@@ -36,6 +36,7 @@
 #include <mono/utils/mono-os-mutex.h>
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/mono-compiler.h>
+#include <mono/utils/unlocked.h>
 
 #if HAVE_BOEHM_GC
 
@@ -482,7 +483,7 @@ on_gc_notification (GC_EventType event)
                        mono_perfcounters->gc_gen0size = heap_size;
                }
 #endif
-               InterlockedAdd64 (&gc_stats.major_gc_time, mono_100ns_ticks () - gc_start_time);
+               UnlockedAdd64 (&gc_stats.major_gc_time, mono_100ns_ticks () - gc_start_time);
                mono_trace_message (MONO_TRACE_GC, "gc took %" G_GINT64_FORMAT " usecs", (mono_100ns_ticks () - gc_start_time) / 10);
                break;
        default:
index 54ff725b22b3c169e7234dffde1a626cf11ee9c2..beb5ce1b2580c265935db3200a138fd91f31c9a4 100644 (file)
 
 #include <mono/utils/memcheck.h>
 #include <mono/utils/mono-mmap-internals.h>
+#include <mono/utils/unlocked.h>
 
 #undef pthread_create
 #undef pthread_join
@@ -1862,7 +1863,7 @@ collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_
        major_collector.finish_nursery_collection ();
 
        TV_GETTIME (last_minor_collection_end_tv);
-       InterlockedAdd64 (&gc_stats.minor_gc_time, TV_ELAPSED (last_minor_collection_start_tv, last_minor_collection_end_tv));
+       UnlockedAdd64 (&gc_stats.minor_gc_time, TV_ELAPSED (last_minor_collection_start_tv, last_minor_collection_end_tv));
 
        sgen_debug_dump_heap ("minor", InterlockedRead (&gc_stats.minor_gc_count) - 1, NULL);
 
@@ -2356,7 +2357,7 @@ major_do_collection (const char *reason, gboolean is_overflow, gboolean forced)
        sgen_gray_object_queue_dispose (&gc_thread_gray_queue);
 
        TV_GETTIME (time_end);
-       InterlockedAdd64 (&gc_stats.major_gc_time, TV_ELAPSED (time_start, time_end));
+       UnlockedAdd64 (&gc_stats.major_gc_time, TV_ELAPSED (time_start, time_end));
 
        /* FIXME: also report this to the user, preferably in gc-end. */
        if (major_collector.get_and_reset_num_major_objects_marked)
@@ -2392,7 +2393,7 @@ major_start_concurrent_collection (const char *reason)
        num_objects_marked = major_collector.get_and_reset_num_major_objects_marked ();
 
        TV_GETTIME (time_end);
-       InterlockedAdd64 (&gc_stats.major_gc_time, TV_ELAPSED (time_start, time_end));
+       UnlockedAdd64 (&gc_stats.major_gc_time, TV_ELAPSED (time_start, time_end));
 
        current_collection_generation = -1;
 }
@@ -2420,7 +2421,7 @@ major_update_concurrent_collection (void)
        sgen_los_update_cardtable_mod_union ();
 
        TV_GETTIME (total_end);
-       InterlockedAdd64 (&gc_stats.major_gc_time, TV_ELAPSED (total_start, total_end));
+       UnlockedAdd64 (&gc_stats.major_gc_time, TV_ELAPSED (total_start, total_end));
 }
 
 static void
@@ -2442,7 +2443,7 @@ major_finish_concurrent_collection (gboolean forced)
        sgen_workers_stop_all_workers (GENERATION_OLD);
 
        SGEN_TV_GETTIME (time_major_conc_collection_end);
-       InterlockedAdd64 (&gc_stats.major_gc_time_concurrent, SGEN_TV_ELAPSED (time_major_conc_collection_start, time_major_conc_collection_end));
+       UnlockedAdd64 (&gc_stats.major_gc_time_concurrent, SGEN_TV_ELAPSED (time_major_conc_collection_start, time_major_conc_collection_end));
 
        major_collector.update_cardtable_mod_union ();
        sgen_los_update_cardtable_mod_union ();
@@ -2457,7 +2458,7 @@ major_finish_concurrent_collection (gboolean forced)
        sgen_gray_object_queue_dispose (&gc_thread_gray_queue);
 
        TV_GETTIME (total_end);
-       InterlockedAdd64 (&gc_stats.major_gc_time, TV_ELAPSED (total_start, total_end));
+       UnlockedAdd64 (&gc_stats.major_gc_time, TV_ELAPSED (total_start, total_end));
 
        current_collection_generation = -1;
 }