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()
next prev parent 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).