sgen-major-copy-object.h - Correct assertion test
sgen-os-posix.c - Prevent race condition between restarting and suspending a thread
#define s390_is_uimm12(val) ((glong)val >= 0 && (glong)val <= 4095)
#define STK_BASE s390_r15
#define s390_is_uimm12(val) ((glong)val >= 0 && (glong)val <= 4095)
#define STK_BASE s390_r15
+#define S390_SP s390_r15
+#define S390_FP s390_r11
#define S390_MINIMAL_STACK_SIZE 160
#define S390_REG_SAVE_OFFSET 48
#define S390_PARM_SAVE_OFFSET 16
#define S390_MINIMAL_STACK_SIZE 160
#define S390_REG_SAVE_OFFSET 48
#define S390_PARM_SAVE_OFFSET 16
*/
if ((forwarded = SGEN_OBJECT_IS_FORWARDED (obj))) {
*/
if ((forwarded = SGEN_OBJECT_IS_FORWARDED (obj))) {
- DEBUG (9, g_assert (((MonoVTable*)SGEN_LOAD_VTABLE(obj))->gc_descr));
+ DEBUG (9, g_assert ((*(MonoVTable**)SGEN_LOAD_VTABLE(obj))->gc_descr));
DEBUG (9, fprintf (gc_debug_file, " (already forwarded to %p)\n", forwarded));
HEAVY_STAT (++stat_nursery_copy_object_failed_forwarded);
*obj_slot = forwarded;
DEBUG (9, fprintf (gc_debug_file, " (already forwarded to %p)\n", forwarded));
HEAVY_STAT (++stat_nursery_copy_object_failed_forwarded);
*obj_slot = forwarded;
static MonoSemType *suspend_ack_semaphore_ptr;
static sigset_t suspend_signal_mask;
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)
static void
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 ()));
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;
/* notify the waiting thread */
MONO_SEM_POST (suspend_ack_semaphore_ptr);
info->stop_count = stop_count;
sigsuspend (&suspend_signal_mask);
} while (info->signal != restart_signal_num && info->doing_handshake);
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);
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);
int old_errno = errno;
info = mono_thread_info_current ();
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
/*
* If a thread is dying there might be no thread info. In
info->signal = restart_signal_num;
DEBUG (4, fprintf (gc_debug_file, "Restart handler in %p %p\n", info, (gpointer)mono_native_thread_id_get ()));
}
info->signal = restart_signal_num;
DEBUG (4, fprintf (gc_debug_file, "Restart handler in %p %p\n", info, (gpointer)mono_native_thread_id_get ()));
}
sigfillset (&suspend_signal_mask);
sigdelset (&suspend_signal_mask, restart_signal_num);
sigfillset (&suspend_signal_mask);
sigdelset (&suspend_signal_mask, restart_signal_num);
+
+ sigemptyset (&suspend_ack_signal_mask);
+ sigaddset (&suspend_ack_signal_mask, restart_signal_num);
+