This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC] GC: external thread suspension


Keith Seitz wrote:

What do others think? Despite the one restriction (the GC will not run on a blocked thread), I think I am beginning to like the GC_start/end_blocking approach. It seems much simpler than what I've come up with.

BTW, I've attached a prototype patch for this route. I just whacked this together and tested it a (very, very) little. It seems to work with my (simple) JDWP breakpoint tests.


As you can see, it is a whole lot less invasive than my other patch.

So now there are two routes. One (complex) patch which allows garbage collection to run on suspended threads (or at least I think it does!) and one (simple) patch which suspends garbage collection while the thread is externally suspended.

Let me know what you'd like me to do.

Keith
Index: include/private/pthread_support.h
===================================================================
--- include/private/pthread_support.h	(revision 112226)
+++ 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 113828)
+++ pthread_stop_world.c	(working copy)
@@ -13,6 +13,10 @@
   /* Doesn't exist on HP/UX 11.11. */
 #endif
 
+void GC_suspend_self();
+void GC_suspend_thread(pthread_t);
+void GC_resume_thread(pthread_t);
+
 #if DEBUG_THREADS
 
 #ifndef NSIG
@@ -127,9 +131,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 -> thread_blocked)
+    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 +146,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 +444,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()

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]