public inbox for java-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Keith Seitz <keiths@redhat.com>
To: Hans Boehm <Hans.Boehm@hp.com>
Cc: gc@napali.hpl.hp.com, Java Patch List <java-patches@gcc.gnu.org>
Subject: Re: External thread suspension (again)
Date: Mon, 05 Jun 2006 20:43:00 -0000	[thread overview]
Message-ID: <44849755.2050803@redhat.com> (raw)
In-Reply-To: <Pine.GHP.4.58.0606032136390.6233@tomil.hpl.hp.com>

[-- Attachment #1: Type: text/plain, Size: 2115 bytes --]

Hans Boehm wrote:

> Some comments/questions:
> 
> 1) I don't see where the SUSPENDED flag gets set in response to
> GC_suspend_thread.  It gets set in GC_suspend_self(), but I don't
> think you get there unless it has already been set?

That gets set in GC_suspend_self. When GC_stop_world is called, 
GC_suspend_all will not signal the externally suspended thread (because 
GC_start_blocking will set thread_blocked).

> 2) You should probably call GC_brief_async_signal_safe_sleep().
> Last time I looked nanosleep wasn't technically async-signal-safe,
> but I think select() always has been.

I've changed that. Thanks.

> 3) Have you thought about the various possible signal races, and which
> signals are masked at what point?  I haven't yet had a chance to.  It
> may be fine, but if there's an obvious argument that it is, a
> comment would be great.

I've thought about it a bit, and the only problem that I see is in the 
signal handler code. *If* a non-blocked signal were to make it to an 
externally suspended thread (and we ended up in our signal handler), it 
would GC_suspend_self itself again. In which case, we would need to 
differentiate between a thread that is supposed to suspend itself and a 
thread which is already suspended.

But since we only install a signal handler for SUSPEND and THR_RESTART, 
so it shouldn't be an issue. A suspended thread should not get 
THR_RESTART, since blocked_thread is set by GC_start_blocking.

Or at least, that's all I could divine.

> 4) IIRC, GC_start_blocking() has a fundamental issue in that there isn't
> really a good way to guarantee that all callee-saves registers are visible
> onthe stack at the right point.  The result might be very occasional
> failures.  So long as this is used only for debugging, and since this
> is fixed with an interface change in 7.0, which can be easily accomodated
> by your patch, I'd lean towards ignoring this for now.  The more
> ambitious, and more correct, solution would be to backport the gc7
> do_blocking() code.

Okay, I will keep that in mind.

I've attached the latest revision of this patch.

Keith

[-- Attachment #2: external-suspend.patch --]
[-- Type: text/x-patch, Size: 3338 bytes --]

Index: include/gc.h
===================================================================
--- include/gc.h	(revision 114118)
+++ include/gc.h	(working copy)
@@ -1040,4 +1040,15 @@
     }  /* 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_self GC_PROTO((void));
+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: include/private/pthread_support.h
===================================================================
--- include/private/pthread_support.h	(revision 114118)
+++ include/private/pthread_support.h	(working copy)
@@ -33,6 +33,7 @@
 #	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: pthread_stop_world.c
===================================================================
--- pthread_stop_world.c	(revision 114118)
+++ pthread_stop_world.c	(working copy)
@@ -127,9 +127,14 @@
 
 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)
+    GC_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 +142,14 @@
 /* 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)
+    GC_suspend_self();
+  else {
+    int old_errno = errno;
+    GC_suspend_handler_inner((ptr_t)(word)sig);
+    errno = old_errno;
+  }
 }
 #endif
 
@@ -430,6 +440,33 @@
     GC_stopping_thread = 0;  /* debugging only */
 }
 
+void GC_suspend_self() {
+  GC_thread me = GC_lookup_thread(pthread_self());
+  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) {
+  int result;
+  GC_thread t = GC_lookup_thread(thread);
+  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);
+  t -> flags &= ~SUSPENDED;
+}
+
 /* Caller holds allocation lock, and has held it continuously since	*/
 /* the world stopped.							*/
 void GC_start_world()

  reply	other threads:[~2006-06-05 20:43 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-05-26 21:43 Keith Seitz
2006-06-04  4:47 ` Hans Boehm
2006-06-05 20:43   ` Keith Seitz [this message]
2006-06-09 20:13     ` Bryce McKinlay
2006-06-09 21:10       ` Keith Seitz
2006-06-09 21:24         ` Keith Seitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=44849755.2050803@redhat.com \
    --to=keiths@redhat.com \
    --cc=Hans.Boehm@hp.com \
    --cc=gc@napali.hpl.hp.com \
    --cc=java-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).