Merge pull request #1949 from lewurm/fixtype
[mono.git] / mono / metadata / sgen-stw.c
index 8da80f9751796c931a6ee16b5d92c758bbc5abc0..17d86487cb3f54ed069f287d39fdc8436fe521ee 100644 (file)
 #include "config.h"
 #ifdef HAVE_SGEN_GC
 
-#include "metadata/sgen-gc.h"
-#include "metadata/sgen-protocol.h"
-#include "metadata/sgen-memory-governor.h"
-#include "metadata/sgen-thread-pool.h"
+#include "sgen/sgen-gc.h"
+#include "sgen/sgen-protocol.h"
+#include "sgen/sgen-memory-governor.h"
+#include "sgen/sgen-thread-pool.h"
 #include "metadata/profiler-private.h"
-#include "metadata/sgen-client.h"
-#include "utils/mono-time.h"
+#include "sgen/sgen-client.h"
+#include "metadata/sgen-bridge-internal.h"
+#include "metadata/gc-internal.h"
 
 #define TV_DECLARE SGEN_TV_DECLARE
 #define TV_GETTIME SGEN_TV_GETTIME
 #define TV_ELAPSED SGEN_TV_ELAPSED
 
-static int sgen_unified_suspend_restart_world (void);
-static int sgen_unified_suspend_stop_world (void);
+static void sgen_unified_suspend_restart_world (void);
+static void sgen_unified_suspend_stop_world (void);
+
+unsigned int sgen_global_stop_count = 0;
 
 inline static void*
 align_pointer (void *ptr)
@@ -66,18 +69,18 @@ update_current_thread_stack (void *start)
 #endif
        SgenThreadInfo *info = mono_thread_info_current ();
        
-       info->stack_start = align_pointer (&stack_guard);
-       g_assert (info->stack_start >= info->stack_start_limit && info->stack_start < info->stack_end);
+       info->client_info.stack_start = align_pointer (&stack_guard);
+       g_assert (info->client_info.stack_start >= info->client_info.stack_start_limit && info->client_info.stack_start < info->client_info.stack_end);
 #ifdef USE_MONO_CTX
        MONO_CONTEXT_GET_CURRENT (cur_thread_ctx);
-       memcpy (&info->ctx, &cur_thread_ctx, sizeof (MonoContext));
+       memcpy (&info->client_info.ctx, &cur_thread_ctx, sizeof (MonoContext));
        if (mono_gc_get_gc_callbacks ()->thread_suspend_func)
-               mono_gc_get_gc_callbacks ()->thread_suspend_func (info->runtime_data, NULL, &info->ctx);
+               mono_gc_get_gc_callbacks ()->thread_suspend_func (info->client_info.runtime_data, NULL, &info->client_info.ctx);
 #else
        ARCH_STORE_REGS (reg_ptr);
-       memcpy (&info->regs, reg_ptr, sizeof (info->regs));
+       memcpy (&info->client_info.regs, reg_ptr, sizeof (info->client_info.regs));
        if (mono_gc_get_gc_callbacks ()->thread_suspend_func)
-               mono_gc_get_gc_callbacks ()->thread_suspend_func (info->runtime_data, NULL, NULL);
+               mono_gc_get_gc_callbacks ()->thread_suspend_func (info->client_info.runtime_data, NULL, NULL);
 #endif
 }
 
@@ -120,17 +123,18 @@ 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->client_info.gc_disabled || info->client_info.suspend_done)
                                continue;
-                       if (mono_thread_info_is_live (info) && (!info->stack_start || info->in_critical_region || info->info.inside_critical_region ||
-                                       is_ip_in_managed_allocator (info->stopped_domain, info->stopped_ip))) {
+                       if (mono_thread_info_is_live (info) &&
+                                       (!info->client_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->info.native_handle);
+                               SGEN_LOG (3, "thread %p resumed.", (void*) (size_t) info->client_info.info.native_handle);
                                result = sgen_resume_thread (info);
                                if (result) {
                                        ++restart_count;
                                } else {
-                                       info->skip = 1;
+                                       info->client_info.skip = 1;
                                }
                        } else {
                                /* we set the stopped_ip to
@@ -138,9 +142,9 @@ restart_threads_until_none_in_managed_allocator (void)
                                   we're not restarting so
                                   that we can easily identify
                                   the others */
-                               info->stopped_ip = NULL;
-                               info->stopped_domain = NULL;
-                               info->suspend_done = TRUE;
+                               info->client_info.stopped_ip = NULL;
+                               info->client_info.stopped_domain = NULL;
+                               info->client_info.suspend_done = TRUE;
                        }
                } END_FOREACH_THREAD_SAFE
                /* if no threads were restarted, we're done */
@@ -161,14 +165,14 @@ restart_threads_until_none_in_managed_allocator (void)
                /* stop them again */
                FOREACH_THREAD (info) {
                        gboolean result;
-                       if (info->skip || 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 */
@@ -202,11 +206,10 @@ static guint64 time_stop_world;
 static guint64 time_restart_world;
 
 /* LOCKING: assumes the GC lock is held */
-int
+void
 sgen_client_stop_world (int generation)
 {
        TV_DECLARE (end_handshake);
-       int count, dead;
 
        /* notify the profiler of the leftovers */
        /* FIXME this is the wrong spot at we can STW for non collection reasons. */
@@ -218,23 +221,23 @@ sgen_client_stop_world (int generation)
        /* We start to scan after locks are taking, this ensures we won't be interrupted. */
        sgen_process_togglerefs ();
 
-       update_current_thread_stack (&count);
+       update_current_thread_stack (&generation);
 
        sgen_global_stop_count++;
        SGEN_LOG (3, "stopping world n %d from %p %p", sgen_global_stop_count, mono_thread_info_current (), (gpointer)mono_native_thread_id_get ());
        TV_GETTIME (stop_world_time);
 
        if (mono_thread_info_unified_management_enabled ()) {
-               count = sgen_unified_suspend_stop_world ();
+               sgen_unified_suspend_stop_world ();
        } else {
+               int count, dead;
                count = sgen_thread_handshake (TRUE);
                dead = restart_threads_until_none_in_managed_allocator ();
                if (count < dead)
                        g_error ("More threads have died (%d) that been initialy suspended %d", dead, count);
-               count -= dead;
        }
 
-       SGEN_LOG (3, "world stopped %d thread(s)", count);
+       SGEN_LOG (3, "world stopped");
 
        TV_GETTIME (end_handshake);
        time_stop_world += TV_ELAPSED (stop_world_time, end_handshake);
@@ -242,15 +245,12 @@ sgen_client_stop_world (int generation)
        sgen_memgov_collection_start (generation);
        if (sgen_need_bridge_processing ())
                sgen_bridge_reset_data ();
-
-       return count;
 }
 
 /* LOCKING: assumes the GC lock is held */
-int
+void
 sgen_client_restart_world (int generation, GGTimingInfo *timing)
 {
-       int count;
        SgenThreadInfo *info;
        TV_DECLARE (end_sw);
        TV_DECLARE (start_handshake);
@@ -263,28 +263,27 @@ sgen_client_restart_world (int generation, GGTimingInfo *timing)
                mono_sgen_gc_event_moves ();
 
        FOREACH_THREAD (info) {
-               info->stack_start = NULL;
+               info->client_info.stack_start = NULL;
 #ifdef USE_MONO_CTX
-               memset (&info->ctx, 0, sizeof (MonoContext));
+               memset (&info->client_info.ctx, 0, sizeof (MonoContext));
 #else
-               memset (&info->regs, 0, sizeof (info->regs));
+               memset (&info->client_info.regs, 0, sizeof (info->client_info.regs));
 #endif
        } END_FOREACH_THREAD
 
        TV_GETTIME (start_handshake);
 
        if (mono_thread_info_unified_management_enabled ())
-               count = sgen_unified_suspend_restart_world ();
+               sgen_unified_suspend_restart_world ();
        else
-               count = sgen_thread_handshake (FALSE);
-
+               sgen_thread_handshake (FALSE);
 
        TV_GETTIME (end_sw);
        time_restart_world += TV_ELAPSED (start_handshake, end_sw);
        usec = TV_ELAPSED (stop_world_time, end_sw);
        max_pause_usec = MAX (usec, max_pause_usec);
 
-       SGEN_LOG (2, "restarted %d thread(s) (pause time: %d usec, max: %d)", count, (int)usec, (int)max_pause_usec);
+       SGEN_LOG (2, "restarted (pause time: %d usec, max: %d)", (int)usec, (int)max_pause_usec);
 
        /*
         * We must release the thread info suspend lock after doing
@@ -305,8 +304,6 @@ sgen_client_restart_world (int generation, GGTimingInfo *timing)
                timing [0].stw_time = usec;
                timing [0].bridge_time = bridge_usec;
        }
-
-       return count;
 }
 
 void
@@ -326,7 +323,7 @@ sgen_is_thread_in_current_stw (SgenThreadInfo *info)
        This is used by TP and finalizer threads.
        FIXME Use an atomic variable for this to avoid everyone taking the GC LOCK.
        */
-       if (info->gc_disabled) {
+       if (info->client_info.gc_disabled) {
                return FALSE;
        }
 
@@ -334,7 +331,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;
        }
 
@@ -370,54 +367,51 @@ update_sgen_info (SgenThreadInfo *info)
        char *stack_start;
 
        /* Once we remove the old suspend code, we should move sgen to directly access the state in MonoThread */
-       info->stopped_domain = mono_thread_info_tls_get (info, TLS_KEY_DOMAIN);
-       info->stopped_ip = (gpointer) MONO_CONTEXT_GET_IP (&mono_thread_info_get_suspend_state (info)->ctx);
+       info->client_info.stopped_domain = mono_thread_info_tls_get (info, TLS_KEY_DOMAIN);
+       info->client_info.stopped_ip = (gpointer) MONO_CONTEXT_GET_IP (&mono_thread_info_get_suspend_state (info)->ctx);
        stack_start = (char*)MONO_CONTEXT_GET_SP (&mono_thread_info_get_suspend_state (info)->ctx) - REDZONE_SIZE;
 
        /* altstack signal handler, sgen can't handle them, mono-threads should have handled this. */
-       if (stack_start < (char*)info->stack_start_limit || stack_start >= (char*)info->stack_end)
+       if (stack_start < (char*)info->client_info.stack_start_limit || stack_start >= (char*)info->client_info.stack_end)
                g_error ("BAD STACK");
 
-       info->stack_start = stack_start;
+       info->client_info.stack_start = stack_start;
 #ifdef USE_MONO_CTX
-       info->ctx = mono_thread_info_get_suspend_state (info)->ctx;
+       info->client_info.ctx = mono_thread_info_get_suspend_state (info)->ctx;
 #else
        g_assert_not_reached ();
 #endif
 }
 
-static int
+static void
 sgen_unified_suspend_stop_world (void)
 {
        int restart_counter;
        SgenThreadInfo *info;
-       int count = 0;
        int sleep_duration = -1;
 
        mono_threads_begin_global_suspend ();
        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)
-                               ++count;
+                       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);
                } else {
-                       THREADS_STW_DEBUG ("[GC-STW-BEGIN-SUSPEND] IGNORE thread %p skip %d\n", mono_thread_info_get_tid (info), info->skip);
+                       THREADS_STW_DEBUG ("[GC-STW-BEGIN-SUSPEND] IGNORE thread %p skip %d\n", mono_thread_info_get_tid (info), info->client_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 +423,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 +432,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 +461,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,28 +471,24 @@ 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
-
-       return count;
 }
 
-static int
+static void
 sgen_unified_suspend_restart_world (void)
 {
        SgenThreadInfo *info;
-       int count = 0;
 
        THREADS_STW_DEBUG ("[GC-STW-END] *** BEGIN RESUME ***\n");
        FOREACH_THREAD_SAFE (info) {
                if (sgen_is_thread_in_current_stw (info)) {
                        g_assert (mono_thread_info_begin_resume (info));
                        THREADS_STW_DEBUG ("[GC-STW-RESUME-WORLD] RESUME thread %p\n", mono_thread_info_get_tid (info));
-                       ++count;
                } else {
                        THREADS_STW_DEBUG ("[GC-STW-RESUME-WORLD] IGNORE thread %p\n", mono_thread_info_get_tid (info));
                }
@@ -506,6 +496,5 @@ sgen_unified_suspend_restart_world (void)
 
        mono_threads_wait_pending_operations ();
        mono_threads_end_global_suspend ();
-       return count;
 }
 #endif