[sgen] Move `skip` and `in_critical_region` to Mono-specific code.
authorMark Probst <mark.probst@gmail.com>
Tue, 30 Dec 2014 19:31:46 +0000 (11:31 -0800)
committerMark Probst <mark.probst@gmail.com>
Wed, 29 Apr 2015 17:57:54 +0000 (10:57 -0700)
mono/metadata/sgen-client-mono.h
mono/metadata/sgen-debug.c
mono/metadata/sgen-gc.c
mono/metadata/sgen-gc.h
mono/metadata/sgen-mono.c
mono/metadata/sgen-os-mach.c
mono/metadata/sgen-os-posix.c
mono/metadata/sgen-os-win32.c
mono/metadata/sgen-stw.c

index fc8108f6d5651d2d12073c13d22329279b236558..dea937cce44970125d96c905f94e125d1911fef2 100644 (file)
@@ -100,6 +100,13 @@ typedef struct _SgenClientThreadInfo SgenClientThreadInfo;
 struct _SgenClientThreadInfo {
        MonoThreadInfo info;
 
+       /*
+        * `skip` is set to TRUE when STW fails to suspend a thread, most probably because
+        * the underlying thread is dead.
+       */
+       gboolean skip, suspend_done;
+       volatile int in_critical_region;
+
        gpointer stopped_ip;    /* only valid if the thread is stopped */
        MonoDomain *stopped_domain; /* dsto */
 };
@@ -479,4 +486,30 @@ gboolean sgen_suspend_thread (SgenThreadInfo *info);
 gboolean sgen_resume_thread (SgenThreadInfo *info);
 void sgen_wait_for_suspend_ack (int count);
 
+#ifdef HAVE_KW_THREAD
+#define TLAB_ACCESS_INIT
+#define IN_CRITICAL_REGION sgen_thread_info->client_info.in_critical_region
+#else
+#define TLAB_ACCESS_INIT       SgenThreadInfo *__thread_info__ = mono_native_tls_get_value (thread_info_key)
+#define IN_CRITICAL_REGION (__thread_info__->client_info.in_critical_region)
+#endif
+
+#ifndef DISABLE_CRITICAL_REGION
+
+#ifdef HAVE_KW_THREAD
+#define IN_CRITICAL_REGION sgen_thread_info->client_info.in_critical_region
+#else
+#define IN_CRITICAL_REGION (__thread_info__->client_info.in_critical_region)
+#endif
+
+/* Enter must be visible before anything is done in the critical region. */
+#define ENTER_CRITICAL_REGION do { mono_atomic_store_acquire (&IN_CRITICAL_REGION, 1); } while (0)
+
+/* Exit must make sure all critical regions stores are visible before it signal the end of the region. 
+ * We don't need to emit a full barrier since we
+ */
+#define EXIT_CRITICAL_REGION  do { mono_atomic_store_release (&IN_CRITICAL_REGION, 0); } while (0)
+
+#endif
+
 #endif
index ebfc9b8342a3e22f222fef8820c42bd43ee08c66..1a0a11fb0b6a17dbc81cc4d636b23e2f9e83a5f9 100644 (file)
@@ -502,7 +502,7 @@ find_pinning_ref_from_thread (char *obj, size_t size)
 
        FOREACH_THREAD (info) {
                char **start = (char**)info->stack_start;
-               if (info->skip)
+               if (info->client_info.skip)
                        continue;
                while (start < (char**)info->stack_end) {
                        if (*start >= obj && *start < endobj) {
index 82cd0da8fab9aa29878ac54e0b5cf50a88abfc87..1a139dd61f79993645c620f00f2396ed8945c395 100644 (file)
@@ -2764,7 +2764,6 @@ sgen_thread_register (SgenThreadInfo* info, void *stack_bottom_fallback)
        info->stop_count = -1;
        info->signal = 0;
 #endif
-       info->skip = 0;
        sgen_client_thread_register (info, stack_bottom_fallback);
        info->stack_start = NULL;
 #ifdef USE_MONO_CTX
index a0537ecb93d19905411640fc78748a323922ff76..6d4526a52b03f6587f345034f12986fcecee468e 100644 (file)
@@ -389,13 +389,6 @@ void sgen_init_internal_allocator (void);
 struct _SgenThreadInfo {
        SgenClientThreadInfo client_info;
 
-       /*
-       This is set to TRUE when STW fails to suspend a thread, most probably because the
-       underlying thread is dead.
-       */
-       gboolean skip, suspend_done;
-       volatile int in_critical_region;
-
        /*
        This is set the argument of mono_gc_set_skip_thread.
 
@@ -991,32 +984,6 @@ extern __thread SgenThreadInfo *sgen_thread_info;
 extern __thread char *stack_end;
 #endif
 
-#ifdef HAVE_KW_THREAD
-#define TLAB_ACCESS_INIT
-#define IN_CRITICAL_REGION sgen_thread_info->in_critical_region
-#else
-#define TLAB_ACCESS_INIT       SgenThreadInfo *__thread_info__ = mono_native_tls_get_value (thread_info_key)
-#define IN_CRITICAL_REGION (__thread_info__->in_critical_region)
-#endif
-
-#ifndef DISABLE_CRITICAL_REGION
-
-#ifdef HAVE_KW_THREAD
-#define IN_CRITICAL_REGION sgen_thread_info->in_critical_region
-#else
-#define IN_CRITICAL_REGION (__thread_info__->in_critical_region)
-#endif
-
-/* Enter must be visible before anything is done in the critical region. */
-#define ENTER_CRITICAL_REGION do { mono_atomic_store_acquire (&IN_CRITICAL_REGION, 1); } while (0)
-
-/* Exit must make sure all critical regions stores are visible before it signal the end of the region. 
- * We don't need to emit a full barrier since we
- */
-#define EXIT_CRITICAL_REGION  do { mono_atomic_store_release (&IN_CRITICAL_REGION, 0); } while (0)
-
-#endif
-
 /* Other globals */
 
 extern GCMemSection *nursery_section;
index 9669d5b3061b7314c9cfa6ea881284f9c1693f5f..e094205358d0a7430bfd615f0e87377806c2a59a 100644 (file)
@@ -1967,6 +1967,7 @@ mono_gc_walk_heap (int flags, MonoGCReferences callback, void *data)
 void
 sgen_client_thread_register (SgenThreadInfo* info, void *stack_bottom_fallback)
 {
+       info->client_info.skip = 0;
        info->client_info.stopped_ip = NULL;
        info->client_info.stopped_domain = NULL;
 }
@@ -1980,7 +1981,7 @@ is_critical_method (MonoMethod *method)
 static gboolean
 thread_in_critical_region (SgenThreadInfo *info)
 {
-       return info->in_critical_region;
+       return info->client_info.in_critical_region;
 }
 
 static void
@@ -2025,7 +2026,7 @@ sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean p
        scan_area_arg_end = end_nursery;
 
        FOREACH_THREAD (info) {
-               if (info->skip) {
+               if (info->client_info.skip) {
                        SGEN_LOG (3, "Skipping dead thread %p, range: %p-%p, size: %td", info, info->stack_start, info->stack_end, (char*)info->stack_end - (char*)info->stack_start);
                        continue;
                }
@@ -2037,7 +2038,7 @@ sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean p
                        SGEN_LOG (3, "Skipping non-running thread %p, range: %p-%p, size: %td (state %x)", info, info->stack_start, info->stack_end, (char*)info->stack_end - (char*)info->stack_start, info->client_info.info.thread_state);
                        continue;
                }
-               g_assert (info->suspend_done);
+               g_assert (info->client_info.suspend_done);
                SGEN_LOG (3, "Scanning thread %p, range: %p-%p, size: %td, pinned=%zd", info, info->stack_start, info->stack_end, (char*)info->stack_end - (char*)info->stack_start, sgen_get_pinned_count ());
                if (mono_gc_get_gc_callbacks ()->thread_mark_func && !conservative_stack_mark) {
                        mono_gc_get_gc_callbacks ()->thread_mark_func (info->runtime_data, info->stack_start, info->stack_end, precise, &ctx);
index c4111ce68d15e11a2d21df8d0bac0f05090bad8e..eed558b976be6ec783cad9c4845819f45ee53b79 100644 (file)
@@ -114,12 +114,12 @@ sgen_thread_handshake (BOOL suspend)
 
        int count = 0;
 
-       cur_thread->suspend_done = TRUE;
+       cur_thread->client_info.suspend_done = TRUE;
        FOREACH_THREAD_SAFE (info) {
                if (info == cur_thread || sgen_thread_pool_is_thread_pool_thread (mono_thread_info_get_tid (info)))
                        continue;
 
-               info->suspend_done = FALSE;
+               info->client_info.suspend_done = FALSE;
                if (info->gc_disabled)
                        continue;
 
index a80339a0389f7071a4263d4739b163dca52f1ae6..ef86a883820d6c1b29a712927f3589b8c833eac4 100644 (file)
@@ -203,12 +203,12 @@ sgen_thread_handshake (BOOL suspend)
        MonoNativeThreadId me = mono_native_thread_id_get ();
 
        count = 0;
-       mono_thread_info_current ()->suspend_done = TRUE;
+       mono_thread_info_current ()->client_info.suspend_done = TRUE;
        FOREACH_THREAD_SAFE (info) {
                if (mono_native_thread_id_equals (mono_thread_info_get_tid (info), me)) {
                        continue;
                }
-               info->suspend_done = FALSE;
+               info->client_info.suspend_done = FALSE;
                if (info->gc_disabled)
                        continue;
                /*if (signum == suspend_signal_num && info->stop_count == global_stop_count)
@@ -217,7 +217,7 @@ sgen_thread_handshake (BOOL suspend)
                if (result == 0) {
                        count++;
                } else {
-                       info->skip = 1;
+                       info->client_info.skip = 1;
                }
        } END_FOREACH_THREAD_SAFE
 
index 46e6fc095c5fce38bb755f75b14e6213db8590cf..b4927e5d5a8b934814b7ddd3f23d60804204c455 100644 (file)
@@ -127,11 +127,11 @@ sgen_thread_handshake (BOOL suspend)
        SgenThreadInfo *current = mono_thread_info_current ();
        int count = 0;
 
-       current->suspend_done = TRUE;
+       current->client_info.suspend_done = TRUE;
        FOREACH_THREAD_SAFE (info) {
                if (info == current)
                        continue;
-               info->suspend_done = FALSE;
+               info->client_info.suspend_done = FALSE;
                if (info->gc_disabled)
                        continue;
                if (suspend) {
index 905ae53038c84a634fe21f3c7e7eec38afe6e414..431eeeec319676e480cbde07ff8e623004c77166 100644 (file)
@@ -120,9 +120,10 @@ restart_threads_until_none_in_managed_allocator (void)
                   allocator */
                FOREACH_THREAD_SAFE (info) {
                        gboolean result;
-                       if (info->skip || info->gc_disabled || info->suspend_done)
+                       if (info->client_info.skip || info->gc_disabled || info->client_info.suspend_done)
                                continue;
-                       if (mono_thread_info_is_live (info) && (!info->stack_start || info->in_critical_region || info->client_info.info.inside_critical_region ||
+                       if (mono_thread_info_is_live (info) &&
+                                       (!info->stack_start || info->client_info.in_critical_region || info->client_info.info.inside_critical_region ||
                                        is_ip_in_managed_allocator (info->client_info.stopped_domain, info->client_info.stopped_ip))) {
                                binary_protocol_thread_restart ((gpointer)mono_thread_info_get_tid (info));
                                SGEN_LOG (3, "thread %p resumed.", (void*) (size_t) info->client_info.info.native_handle);
@@ -130,7 +131,7 @@ restart_threads_until_none_in_managed_allocator (void)
                                if (result) {
                                        ++restart_count;
                                } else {
-                                       info->skip = 1;
+                                       info->client_info.skip = 1;
                                }
                        } else {
                                /* we set the stopped_ip to
@@ -140,7 +141,7 @@ restart_threads_until_none_in_managed_allocator (void)
                                   the others */
                                info->client_info.stopped_ip = NULL;
                                info->client_info.stopped_domain = NULL;
-                               info->suspend_done = TRUE;
+                               info->client_info.suspend_done = TRUE;
                        }
                } END_FOREACH_THREAD_SAFE
                /* if no threads were restarted, we're done */
@@ -161,14 +162,14 @@ restart_threads_until_none_in_managed_allocator (void)
                /* stop them again */
                FOREACH_THREAD (info) {
                        gboolean result;
-                       if (info->skip || info->client_info.stopped_ip == NULL)
+                       if (info->client_info.skip || info->client_info.stopped_ip == NULL)
                                continue;
                        result = sgen_suspend_thread (info);
 
                        if (result) {
                                ++restarted_count;
                        } else {
-                               info->skip = 1;
+                               info->client_info.skip = 1;
                        }
                } END_FOREACH_THREAD
                /* some threads might have died */
@@ -334,7 +335,7 @@ sgen_is_thread_in_current_stw (SgenThreadInfo *info)
        We have detected that this thread is failing/dying, ignore it.
        FIXME: can't we merge this with thread_is_dying?
        */
-       if (info->skip) {
+       if (info->client_info.skip) {
                return FALSE;
        }
 
@@ -398,26 +399,26 @@ sgen_unified_suspend_stop_world (void)
        THREADS_STW_DEBUG ("[GC-STW-BEGIN] *** BEGIN SUSPEND *** \n");
 
        FOREACH_THREAD_SAFE (info) {
-               info->skip = FALSE;
-               info->suspend_done = FALSE;
+               info->client_info.skip = FALSE;
+               info->client_info.suspend_done = FALSE;
                if (sgen_is_thread_in_current_stw (info)) {
-                       info->skip = !mono_thread_info_begin_suspend (info, FALSE);
-                       THREADS_STW_DEBUG ("[GC-STW-BEGIN-SUSPEND] SUSPEND thread %p skip %d\n", mono_thread_info_get_tid (info), info->skip);
-                       if (!info->skip)
+                       info->client_info.skip = !mono_thread_info_begin_suspend (info, FALSE);
+                       THREADS_STW_DEBUG ("[GC-STW-BEGIN-SUSPEND] SUSPEND thread %p skip %d\n", mono_thread_info_get_tid (info), info->client_info.skip);
+                       if (!info->client_info.skip)
                                ++count;
                } else {
                        THREADS_STW_DEBUG ("[GC-STW-BEGIN-SUSPEND] IGNORE thread %p skip %d\n", mono_thread_info_get_tid (info), info->skip);
                }
        } END_FOREACH_THREAD_SAFE
 
-       mono_thread_info_current ()->suspend_done = TRUE;
+       mono_thread_info_current ()->client_info.suspend_done = TRUE;
        mono_threads_wait_pending_operations ();
 
        for (;;) {
                restart_counter = 0;
                FOREACH_THREAD_SAFE (info) {
-                       if (info->suspend_done || !sgen_is_thread_in_current_stw (info)) {
-                               THREADS_STW_DEBUG ("[GC-STW-RESTART] IGNORE thread %p not been processed done %d current %d\n", mono_thread_info_get_tid (info), info->suspend_done, !sgen_is_thread_in_current_stw (info));
+                       if (info->client_info.suspend_done || !sgen_is_thread_in_current_stw (info)) {
+                               THREADS_STW_DEBUG ("[GC-STW-RESTART] IGNORE thread %p not been processed done %d current %d\n", mono_thread_info_get_tid (info), info->client_info.suspend_done, !sgen_is_thread_in_current_stw (info));
                                continue;
                        }
 
@@ -429,7 +430,7 @@ sgen_unified_suspend_stop_world (void)
                        */
                        if (!mono_threads_core_check_suspend_result (info)) {
                                THREADS_STW_DEBUG ("[GC-STW-RESTART] SKIP thread %p failed to finish to suspend\n", mono_thread_info_get_tid (info));
-                               info->skip = TRUE;
+                               info->client_info.skip = TRUE;
                        } else if (mono_thread_info_in_critical_location (info)) {
                                gboolean res;
                                g_assert (mono_thread_info_suspend_count (info) == 1);
@@ -438,11 +439,11 @@ sgen_unified_suspend_stop_world (void)
                                if (res)
                                        ++restart_counter;
                                else
-                                       info->skip = TRUE;
+                                       info->client_info.skip = TRUE;
                        } else {
                                THREADS_STW_DEBUG ("[GC-STW-RESTART] DONE thread %p deemed fully suspended\n", mono_thread_info_get_tid (info));
-                               g_assert (!info->in_critical_region);
-                               info->suspend_done = TRUE;
+                               g_assert (!info->client_info.in_critical_region);
+                               info->client_info.suspend_done = TRUE;
                        }
                } END_FOREACH_THREAD_SAFE
 
@@ -467,7 +468,7 @@ sgen_unified_suspend_stop_world (void)
                                gboolean res = mono_thread_info_begin_suspend (info, FALSE);
                                THREADS_STW_DEBUG ("[GC-STW-RESTART] SUSPEND thread %p skip %d\n", mono_thread_info_get_tid (info), res);
                                if (!res)
-                                       info->skip = TRUE;
+                                       info->client_info.skip = TRUE;
                        }
                } END_FOREACH_THREAD_SAFE
 
@@ -477,10 +478,10 @@ sgen_unified_suspend_stop_world (void)
        FOREACH_THREAD_SAFE (info) {
                if (sgen_is_thread_in_current_stw (info)) {
                        THREADS_STW_DEBUG ("[GC-STW-SUSPEND-END] thread %p is suspended\n", mono_thread_info_get_tid (info));
-                       g_assert (info->suspend_done);
+                       g_assert (info->client_info.suspend_done);
                        update_sgen_info (info);
                } else {
-                       g_assert (!info->suspend_done || info == mono_thread_info_current ());
+                       g_assert (!info->client_info.suspend_done || info == mono_thread_info_current ());
                }
        } END_FOREACH_THREAD_SAFE