2011-05-16 Ivan Maidanski <ivmai@mail.ru>
authorivmai <ivmai>
Mon, 16 May 2011 13:12:14 +0000 (13:12 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:59 +0000 (21:06 +0400)
* 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.

ChangeLog
include/private/gcconfig.h
pthread_stop_world.c
pthread_support.c

index d96748e..3eef929 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 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".
 
index 54d9364..9e277e5 100644 (file)
 # 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
index dfb0d8a..9302f93 100644 (file)
@@ -43,6 +43,9 @@ int GC_nacl_thread_used[MAX_NACL_GC_THREADS];
 #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)
@@ -56,9 +59,6 @@ int GC_nacl_thread_used[MAX_NACL_GC_THREADS];
 #   endif
 # endif /* NSIG */
 
-  /* It's safe to call original pthread_sigmask() here. */
-# undef pthread_sigmask
-
   void GC_print_sig_mask(void)
   {
     sigset_t blocked;
@@ -141,6 +141,20 @@ STATIC volatile AO_t GC_world_is_stopped = FALSE;
 #  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
@@ -769,13 +783,15 @@ GC_INNER void GC_start_world(void)
       }
     }
 #   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");
index 175663c..4f3be43 100644 (file)
@@ -1358,6 +1358,10 @@ GC_INLINE void GC_record_stack_base(GC_thread me,
 #   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)
 {
@@ -1372,6 +1376,11 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb,
       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;
 }
 
@@ -1398,8 +1407,15 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb)
         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     */