This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
External thread suspension (again)
- From: Keith Seitz <keiths at redhat dot com>
- To: gc at napali dot hpl dot hp dot com
- Cc: Java Patch List <java-patches at gcc dot gnu dot org>
- Date: Fri, 26 May 2006 14:41:47 -0700
- Subject: External thread suspension (again)
Including GC list
-------- Original Message --------
Subject: Re: [RFC] GC: external thread suspension
Date: Thu, 25 May 2006 12:39:58 -0700
From: Keith Seitz <keiths@redhat.com>
To: Java Patch List <java-patches@gcc.gnu.org>
Okay, since it has been relatively quiet for the past week, I thought I
would turn this into an official RFA.
I'm going to be conservative, and offer up for approval the patch
suggested by Hans Boehm, using GC_start/end_blocking. It is much simpler
than my original patch.
In order to modify gc.h, it looks like I need to ifdef stuff. Since I've
only done this for pthreads, I've made a best guess as to the proper
conditions. Let me know if there are any problems with this.
Keith
ChangeLog
2006-05-25 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.
(GC_suspend_self): New function.
(GC_suspend_thread): New function.
(GC_resume_thread): New function.
* include/gc.h (GC_suspend_self): Declare.
(GC_suspend_thread): Declare.
(GC_resumet_thread): Declare.
* include/private/pthread_support.h (SUSPENDED): New GC_thread
flag.
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,36 @@
GC_stopping_thread = 0; /* debugging only */
}
+void GC_suspend_self() {
+ GC_thread me = GC_lookup_thread(pthread_self());
+ struct timespec t;
+ t.tv_sec = 0;
+ t.tv_nsec = 1000 * 1000 * 50;
+ me -> flags |= SUSPENDED;
+ GC_start_blocking();
+ while (me -> flags & SUSPENDED)
+ nanosleep(&t, NULL);
+ 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()