]> granicus.if.org Git - gc/commitdiff
* pthread_stop_world.c (GC_suspend_handler): Redirect to suspension
authorkseitz <kseitz@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 21 Jun 2006 20:56:37 +0000 (20:56 +0000)
committerguest <ivmai@mail.ru>
Fri, 29 Jul 2011 06:54:27 +0000 (10:54 +0400)
        routine if signal is received and thread is flagged SUSPENDED.
        (suspend_self): New function.
        (GC_suspend_thread): New function.
        (GC_resume_thread): New function.
        * include/gc.h (GC_suspend_thread): Declare.
        (GC_resumet_thread): Declare.
        * include/private/pthread_support.h (SUSPENDED): New GC_thread
        flag.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@114869 138bc75d-0d04-0410-961f-82ee72b054a4

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

index ca5f33ce61300d115678d4583b5b392b127942e3..6e2b3a86112d22c37df97c4a6c70c0d1593184fc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2006-06-21  Keith Seitz  <keiths@redhat.com>
+
+       * pthread_stop_world.c (GC_suspend_handler): Redirect to suspension
+       routine if signal is received and thread is flagged SUSPENDED.
+       (suspend_self): New function.
+       (GC_suspend_thread): New function.
+       (GC_resume_thread): New function.
+       * include/gc.h (GC_suspend_thread): Declare.
+       (GC_resumet_thread): Declare.
+       * include/private/pthread_support.h (SUSPENDED): New GC_thread
+       flag.
+
 2006-06-20  Ranjit Mathew  <rmathew@gcc.gnu.org>
        
        Backport Windows 9x/ME VirtualQuery() fix from GC 6.7.
index 3507db74dc51955e813c2f8ca43f9938ff6ea526..e6ab2c608c4a52634597d6ec6c63e6d752bdb934 100644 (file)
@@ -1040,4 +1040,14 @@ GC_API void GC_register_has_static_roots_callback
     }  /* end of extern "C" */
 #endif
 
+/* External thread suspension support. These functions do not implement
+ * suspension counts or any other higher-level abstraction. Threads which
+ * have been suspended numerous times will resume with the very first call
+ * to GC_resume_thread.
+ */
+#if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
+  && !defined(GC_WIN32_THREADS) && !defined(GC_DARWIN_THREADS)
+GC_API void GC_suspend_thread GC_PROTO((pthread_t));
+GC_API void GC_resume_thread GC_PROTO((pthread_t));
+#endif
 #endif /* _GC_H */
index 469021b407105e9805a5527f3b860926f5cec362..2186c079039f5ef27e270742946c24e1c1454cea 100644 (file)
@@ -33,6 +33,7 @@ typedef struct GC_Thread_Rep {
 #      define FINISHED 1       /* Thread has exited.   */
 #      define DETACHED 2       /* Thread is intended to be detached.   */
 #      define MAIN_THREAD 4    /* True for the original thread only.   */
+#       define SUSPENDED 8      /* True if thread was suspended externally */
     short thread_blocked;      /* Protected by GC lock.                */
                                /* Treated as a boolean value.  If set, */
                                /* thread will acquire GC lock before   */
index b9034dc7f5bfb0c5ff626f4cf65f160c74129c0d..de647769c7c24079457f9f1f890d73df5be6b8e8 100644 (file)
@@ -13,6 +13,8 @@
   /* Doesn't exist on HP/UX 11.11. */
 #endif
 
+void suspend_self();
+
 #if DEBUG_THREADS
 
 #ifndef NSIG
@@ -127,9 +129,14 @@ extern void GC_with_callee_saves_pushed();
 
 void GC_suspend_handler(int sig)
 {
-  int old_errno = errno;
-  GC_with_callee_saves_pushed(GC_suspend_handler_inner, (ptr_t)(word)sig);
-  errno = old_errno;
+  GC_thread me = GC_lookup_thread (pthread_self());
+  if (me -> flags & SUSPENDED)
+    suspend_self();
+  else {
+    int old_errno = errno;
+    GC_with_callee_saves_pushed(GC_suspend_handler_inner, (ptr_t)(word)sig);
+    errno = old_errno;
+  }
 }
 
 #else
@@ -137,9 +144,14 @@ void GC_suspend_handler(int sig)
 /* in the signal handler frame.                                                */
 void GC_suspend_handler(int sig)
 {
-  int old_errno = errno;
-  GC_suspend_handler_inner((ptr_t)(word)sig);
-  errno = old_errno;
+  GC_thread me = GC_lookup_thread(pthread_self());
+  if (me -> flags & SUSPENDED)
+    suspend_self();
+  else {
+    int old_errno = errno;
+    GC_suspend_handler_inner((ptr_t)(word)sig);
+    errno = old_errno;
+  }
 }
 #endif
 
@@ -430,6 +442,47 @@ void GC_stop_world()
     GC_stopping_thread = 0;  /* debugging only */
 }
 
+void suspend_self() {
+  GC_thread me = GC_lookup_thread(pthread_self());
+  if (me == NULL)
+    ABORT("attempting to suspend unknown thread");
+
+  me -> flags |= SUSPENDED;
+  GC_start_blocking();
+  while (me -> flags & SUSPENDED)
+    GC_brief_async_signal_safe_sleep();
+  GC_end_blocking();
+}
+
+void GC_suspend_thread(pthread_t thread) {
+  if (thread == pthread_self())
+    suspend_self();
+  else {
+    int result;
+    GC_thread t = GC_lookup_thread(thread);
+    if (t == NULL)
+      ABORT("attempting to suspend unknown thread");
+
+    t -> flags |= SUSPENDED;
+    result = pthread_kill (t -> id, SIG_SUSPEND);
+    switch (result) {
+    case ESRCH:
+    case 0:
+      break;
+    default:
+      ABORT("pthread_kill failed");
+    }
+  }
+}
+
+void GC_resume_thread(pthread_t thread) {
+  GC_thread t = GC_lookup_thread(thread);
+  if (t == NULL)
+    ABORT("attempting to resume unknown thread");
+
+  t -> flags &= ~SUSPENDED;
+}
+
 /* Caller holds allocation lock, and has held it continuously since    */
 /* the world stopped.                                                  */
 void GC_start_world()