2011-05-16 Ivan Maidanski <ivmai@mail.ru>
+ * pthread_stop_world.c (pthread_sigmask): Undefine even if not
+ DEBUG_THREADS.
+ * pthread_stop_world.c (GC_unblock_gc_signals): New function (only
+ if GC_EXPLICIT_SIGNALS_UNBLOCK).
+ * pthread_support.c (GC_unblock_gc_signals): New prototype.
+ * pthread_support.c (GC_register_my_thread_inner,
+ GC_register_my_thread): Call GC_unblock_gc_signals (only if
+ GC_EXPLICIT_SIGNALS_UNBLOCK); add comment.
+ * include/private/gcconfig.h (GC_EXPLICIT_SIGNALS_UNBLOCK): New
+ macro.
+
+2011-05-16 Ivan Maidanski <ivmai@mail.ru>
+
* pthread_stop_world.c (GC_suspend_handler_inner): Remove "dummy",
"sig" local variables; rename my_thread local variable to "self".
# define SUNOS5SIGS
#endif
+#if !defined(GC_EXPLICIT_SIGNALS_UNBLOCK) && defined(SUNOS5SIGS) \
+ && !defined(GC_NO_PTHREAD_SIGMASK)
+# define GC_EXPLICIT_SIGNALS_UNBLOCK
+#endif
+
#ifdef GC_NETBSD_THREADS
# define SIGRTMIN 33
# define SIGRTMAX 63
#include <unistd.h>
#include "atomic_ops.h"
+/* It's safe to call original pthread_sigmask() here. */
+#undef pthread_sigmask
+
#ifdef DEBUG_THREADS
# ifndef NSIG
# if defined(MAXSIG)
# endif
# endif /* NSIG */
- /* It's safe to call original pthread_sigmask() here. */
-# undef pthread_sigmask
-
void GC_print_sig_mask(void)
{
sigset_t blocked;
# endif
#endif
+#ifdef GC_EXPLICIT_SIGNALS_UNBLOCK
+ /* Some targets (eg., Solaris) might require this to be called when */
+ /* doing thread registering from the thread destructor. */
+ GC_INNER void GC_unblock_gc_signals(void)
+ {
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set, SIG_SUSPEND);
+ sigaddset(&set, SIG_THR_RESTART);
+ if (pthread_sigmask(SIG_UNBLOCK, &set, NULL) != 0)
+ ABORT("pthread_sigmask failed");
+ }
+#endif /* GC_EXPLICIT_SIGNALS_UNBLOCK */
+
STATIC sem_t GC_suspend_ack_sem;
#ifdef GC_NETBSD_THREADS
}
}
# ifdef GC_NETBSD_THREADS_WORKAROUND
- for (i = 0; i < n_live_threads; i++)
- while (0 != (code = sem_wait(&GC_restart_ack_sem)))
- if (errno != EINTR) {
- if (GC_print_stats)
- GC_log_printf("sem_wait() returned %d\n", code);
- ABORT("sem_wait() for restart handler failed");
- }
+ for (i = 0; i < n_live_threads; i++) {
+ while (0 != (code = sem_wait(&GC_restart_ack_sem))) {
+ if (errno != EINTR) {
+ if (GC_print_stats)
+ GC_log_printf("sem_wait() returned %d\n", code);
+ ABORT("sem_wait() for restart handler failed");
+ }
+ }
+ }
# endif
# ifdef DEBUG_THREADS
GC_log_printf("World started\n");
# endif
}
+#ifdef GC_EXPLICIT_SIGNALS_UNBLOCK
+ GC_INNER void GC_unblock_gc_signals(void); /* from pthread_stop_world.c */
+#endif
+
STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb,
pthread_t my_pthread)
{
me -> stop_info.mach_thread = mach_thread_self();
# endif
GC_record_stack_base(me, sb);
+# ifdef GC_EXPLICIT_SIGNALS_UNBLOCK
+ /* Since this could be executed from a detached thread */
+ /* destructor, our signals might already be blocked. */
+ GC_unblock_gc_signals();
+# endif
return me;
}
if (me == 0) {
me = GC_register_my_thread_inner(sb, self);
} else {
+ /* This code is executed when a thread is registered from the */
+ /* client thread key destructor. */
GC_record_stack_base(me, sb);
me -> flags &= ~FINISHED;
+# ifdef GC_EXPLICIT_SIGNALS_UNBLOCK
+ /* Since this could be executed from a thread destructor, */
+ /* our signals might be blocked. */
+ GC_unblock_gc_signals();
+# endif
}
me -> flags |= DETACHED;
/* Treat as detached, since we do not need to worry about */