This patch fixes various problems with safepoints.

  (1) We must increase ->nr_in_safepoint from gc_start(); otherwise
      we'll deadlock as the tread that called gc_start() will never
      enter gc_safepoint().

  (2) Don't let threads enter gc_start() until we've returned from
      gc_start() for a previous safepoint.

  (3) Let only one thread wait in gc_start() when it's called
      concurrently. Only the first thread will wait and others will
      be be treated just as if they had entered gc_safepoint().

  (4) Fix gc_start() when called during early bootstrap code when no
      threads are started.

With the above fixes, GcTortureTest passes when gc_start() is called
from object allocator.

Cc: Vegard Nossum <vegard.nos...@gmail.com>
Signed-off-by: Pekka Enberg <penb...@cs.helsinki.fi>
---
 vm/gc.c |   99 +++++++++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 65 insertions(+), 34 deletions(-)

diff --git a/vm/gc.c b/vm/gc.c
index 949a6c9..37a2143 100644
--- a/vm/gc.c
+++ b/vm/gc.c
@@ -4,6 +4,7 @@
 #include <pthread.h>
 
 #include "lib/guard-page.h"
+#include "vm/thread.h"
 #include "vm/die.h"
 #include "vm/gc.h"
 
@@ -14,12 +15,14 @@ static pthread_mutex_t safepoint_mutex = 
PTHREAD_MUTEX_INITIALIZER;
 /* Protected by safepoint_mutex */
 static pthread_cond_t everyone_in_cond = PTHREAD_COND_INITIALIZER;
 static pthread_cond_t everyone_out_cond = PTHREAD_COND_INITIALIZER;
-static unsigned int nr_threads = 0;
 static unsigned int nr_in_safepoint = 0;
 
 static pthread_cond_t can_continue_cond = PTHREAD_COND_INITIALIZER;
 static bool can_continue;
 
+bool gc_enabled;
+bool verbose_gc;
+
 void gc_init(void)
 {
        gc_safepoint_page = alloc_guard_page(false);
@@ -29,18 +32,24 @@ void gc_init(void)
 
 void gc_attach_thread(void)
 {
-       pthread_mutex_lock(&safepoint_mutex);
-       ++nr_threads;
-       pthread_mutex_unlock(&safepoint_mutex);
 }
 
 void gc_detach_thread(void)
 {
-       assert(nr_threads > 0);
+}
 
-       pthread_mutex_lock(&safepoint_mutex);
-       --nr_threads;
-       pthread_mutex_unlock(&safepoint_mutex);
+/* Callers must hold safepoint_mutex */
+static void gc_safepoint_barrier_wait(void)
+{
+       /* Only the GC thread will be waiting for this. */
+       if (--nr_in_safepoint == 0) {
+               pthread_cond_broadcast(&everyone_out_cond);
+               return;
+       }
+
+       /* Block until GC has finished */
+       while (nr_in_safepoint > 0)
+               pthread_cond_wait(&everyone_out_cond, &safepoint_mutex);
 }
 
 static void hide_safepoint_guard_page(void)
@@ -53,48 +62,70 @@ static void unhide_safepoint_guard_page(void)
        unhide_guard_page(gc_safepoint_page);
 }
 
-void gc_start(void)
+static void do_gc_reclaim(void)
+{
+       /* TODO: Do main GC work here. */
+}
+
+/* Callers must hold safepoint_mutex */
+static void do_gc_safepoint(void)
+{
+       /* Only the GC thread will be waiting for this. */
+       if (++nr_in_safepoint == vm_nr_threads_running())
+               pthread_cond_signal(&everyone_in_cond);
+
+       /* Block until GC has finished */
+       while (!can_continue)
+               pthread_cond_wait(&can_continue_cond, &safepoint_mutex);
+}
+
+void gc_safepoint(void)
 {
        pthread_mutex_lock(&safepoint_mutex);
 
-       assert(nr_in_safepoint == 0);
+       do_gc_safepoint();
+
+       gc_safepoint_barrier_wait();
 
+       pthread_mutex_unlock(&safepoint_mutex);
+}
+
+void gc_start(void)
+{
+       pthread_mutex_lock(&safepoint_mutex);
+
+       /* There are no threads running during early bootstrap. */
+       if (vm_nr_threads_running() == 0) {
+               pthread_mutex_unlock(&safepoint_mutex);
+               return;
+       }
+
+       /*
+        * If someone entered the reclaim path before us, make the current
+        * thread enter a regular safepoint.
+        */
+       if (nr_in_safepoint != 0) {
+               do_gc_safepoint();
+               goto out;
+       }
+
+       ++nr_in_safepoint;
        can_continue = false;
        hide_safepoint_guard_page();
 
-       while (nr_in_safepoint != nr_threads)
+       while (nr_in_safepoint != vm_nr_threads_running())
                pthread_cond_wait(&everyone_in_cond, &safepoint_mutex);
 
        /* At this point, we know that everyone is in the safepoint. */
        unhide_safepoint_guard_page();
 
-       /* TODO: Do main GC work here. */
+       do_gc_reclaim();
 
        /* Resume other threads */
        can_continue = true;
        pthread_cond_broadcast(&can_continue_cond);
-
-       while (nr_in_safepoint != 0)
-               pthread_cond_wait(&everyone_out_cond, &safepoint_mutex);
-
-       pthread_mutex_unlock(&safepoint_mutex);
-}
-
-void gc_safepoint(void)
-{
-       pthread_mutex_lock(&safepoint_mutex);
-
-       /* Only the GC thread will be waiting for this. */
-       if (++nr_in_safepoint == nr_threads)
-               pthread_cond_signal(&everyone_in_cond);
-
-       /* Block until GC has finished */
-       while (!can_continue)
-               pthread_cond_wait(&can_continue_cond, &safepoint_mutex);
-
-       /* Only the GC thread will be waiting for this. */
-       if (--nr_in_safepoint == 0)
-               pthread_cond_signal(&everyone_out_cond);
+out:
+       gc_safepoint_barrier_wait();
 
        pthread_mutex_unlock(&safepoint_mutex);
 }
-- 
1.5.6.3


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to