X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fsgen-os-posix.c;h=276923779f9e9b5b7034ab00f9936d860e96f0d8;hb=ec2bf6b59b0923fbf195948164ae4fed2d8605b1;hp=49b7deff50cae62a57876855930d2e8e05cde1ba;hpb=517f0cb5c4b793477769ad8d6a2e2e9582ed2f89;p=mono.git diff --git a/mono/metadata/sgen-os-posix.c b/mono/metadata/sgen-os-posix.c index 49b7deff50c..276923779f9 100644 --- a/mono/metadata/sgen-os-posix.c +++ b/mono/metadata/sgen-os-posix.c @@ -51,6 +51,7 @@ static MonoSemType suspend_ack_semaphore; static MonoSemType *suspend_ack_semaphore_ptr; static sigset_t suspend_signal_mask; +static sigset_t suspend_ack_signal_mask; static void suspend_thread (SgenThreadInfo *info, void *context) @@ -67,12 +68,12 @@ suspend_thread (SgenThreadInfo *info, void *context) info->stopped_domain = mono_domain_get (); info->stopped_ip = context ? (gpointer) ARCH_SIGCTX_IP (context) : NULL; - stop_count = mono_sgen_global_stop_count; + stop_count = sgen_global_stop_count; /* duplicate signal */ if (0 && info->stop_count == stop_count) return; - mono_sgen_fill_thread_info_for_suspend (info); + sgen_fill_thread_info_for_suspend (info); stack_start = context ? (char*) ARCH_SIGCTX_SP (context) - REDZONE_SIZE : NULL; /* If stack_start is not within the limits, then don't set it @@ -104,6 +105,14 @@ suspend_thread (SgenThreadInfo *info, void *context) mono_gc_get_gc_callbacks ()->thread_suspend_func (info->runtime_data, context); DEBUG (4, fprintf (gc_debug_file, "Posting suspend_ack_semaphore for suspend from %p %p\n", info, (gpointer)mono_native_thread_id_get ())); + + /* + Block the restart signal. + We need to block the restart signal while posting to the suspend_ack semaphore or we race to sigsuspend, + which might miss the signal and get stuck. + */ + pthread_sigmask (SIG_BLOCK, &suspend_ack_signal_mask, NULL); + /* notify the waiting thread */ MONO_SEM_POST (suspend_ack_semaphore_ptr); info->stop_count = stop_count; @@ -114,6 +123,9 @@ suspend_thread (SgenThreadInfo *info, void *context) sigsuspend (&suspend_signal_mask); } while (info->signal != restart_signal_num && info->doing_handshake); + /* Unblock the restart signal. */ + pthread_sigmask (SIG_UNBLOCK, &suspend_ack_signal_mask, NULL); + DEBUG (4, fprintf (gc_debug_file, "Posting suspend_ack_semaphore for resume from %p %p\n", info, (gpointer)mono_native_thread_id_get ())); /* notify the waiting thread */ MONO_SEM_POST (suspend_ack_semaphore_ptr); @@ -145,6 +157,15 @@ restart_handler (int sig) int old_errno = errno; info = mono_thread_info_current (); + /* + If the thread info is null is means we're currently in the process of cleaning up, + the pthread destructor has already kicked in and it has explicitly invoked the suspend handler. + + This means this thread has been suspended, TLS is dead, so the only option we have is to + rely on pthread_self () and seatch over the thread list. + */ + if (!info) + info = mono_thread_info_lookup (pthread_self ()); /* * If a thread is dying there might be no thread info. In @@ -154,24 +175,23 @@ restart_handler (int sig) info->signal = restart_signal_num; DEBUG (4, fprintf (gc_debug_file, "Restart handler in %p %p\n", info, (gpointer)mono_native_thread_id_get ())); } - errno = old_errno; } gboolean -mono_sgen_resume_thread (SgenThreadInfo *info) +sgen_resume_thread (SgenThreadInfo *info) { return mono_threads_pthread_kill (info, restart_signal_num) == 0; } gboolean -mono_sgen_suspend_thread (SgenThreadInfo *info) +sgen_suspend_thread (SgenThreadInfo *info) { return mono_threads_pthread_kill (info, suspend_signal_num) == 0; } void -mono_sgen_wait_for_suspend_ack (int count) +sgen_wait_for_suspend_ack (int count) { int i, result; @@ -185,7 +205,7 @@ mono_sgen_wait_for_suspend_ack (int count) } gboolean -mono_sgen_park_current_thread_if_doing_handshake (SgenThreadInfo *p) +sgen_park_current_thread_if_doing_handshake (SgenThreadInfo *p) { if (!p->doing_handshake) return FALSE; @@ -195,7 +215,7 @@ mono_sgen_park_current_thread_if_doing_handshake (SgenThreadInfo *p) } int -mono_sgen_thread_handshake (BOOL suspend) +sgen_thread_handshake (BOOL suspend) { int count, result; SgenThreadInfo *info; @@ -208,6 +228,8 @@ mono_sgen_thread_handshake (BOOL suspend) if (mono_native_thread_id_equals (mono_thread_info_get_tid (info), me)) { continue; } + if (info->gc_disabled) + continue; /*if (signum == suspend_signal_num && info->stop_count == global_stop_count) continue;*/ if (suspend) { @@ -225,13 +247,13 @@ mono_sgen_thread_handshake (BOOL suspend) } } END_FOREACH_THREAD_SAFE - mono_sgen_wait_for_suspend_ack (count); + sgen_wait_for_suspend_ack (count); return count; } void -mono_sgen_os_init (void) +sgen_os_init (void) { struct sigaction sinfo; @@ -252,6 +274,10 @@ mono_sgen_os_init (void) sigfillset (&suspend_signal_mask); sigdelset (&suspend_signal_mask, restart_signal_num); + + sigemptyset (&suspend_ack_signal_mask); + sigaddset (&suspend_ack_signal_mask, restart_signal_num); + } int