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 |   76 +++++++++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 55 insertions(+), 21 deletions(-)

diff --git a/vm/gc.c b/vm/gc.c
index 949a6c9..514b50e 100644
--- a/vm/gc.c
+++ b/vm/gc.c
@@ -20,6 +20,9 @@ static unsigned int nr_in_safepoint = 0;
 static pthread_cond_t can_continue_cond = PTHREAD_COND_INITIALIZER;
 static bool can_continue;
 
+static pthread_cond_t can_enter_cond = PTHREAD_COND_INITIALIZER;
+static bool can_enter = true;
+
 void gc_init(void)
 {
        gc_safepoint_page = alloc_guard_page(false);
@@ -53,11 +56,56 @@ static void unhide_safepoint_guard_page(void)
        unhide_guard_page(gc_safepoint_page);
 }
 
+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 == 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);
+}
+
+void gc_safepoint(void)
+{
+       pthread_mutex_lock(&safepoint_mutex);
+
+       do_gc_safepoint();
+
+       pthread_mutex_unlock(&safepoint_mutex);
+}
+
 void gc_start(void)
 {
        pthread_mutex_lock(&safepoint_mutex);
 
-       assert(nr_in_safepoint == 0);
+       /* There are no threads running during early bootstrap. */
+       if (nr_threads == 0) {
+               do_gc_reclaim();
+               goto out;
+       }
+
+       /* Wait for everyone to leave a previous safepoint.  */
+       while (!can_enter)
+               pthread_cond_wait(&can_enter_cond, &safepoint_mutex);
+
+       if (nr_in_safepoint != 0) {
+               do_gc_safepoint();
+               goto out;
+       }
+
+       ++nr_in_safepoint;
 
        can_continue = false;
        hide_safepoint_guard_page();
@@ -68,33 +116,19 @@ void gc_start(void)
        /* 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 */
+       --nr_in_safepoint;
        can_continue = true;
+       can_enter = false;
        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);
-
+       can_enter = true;
+       pthread_cond_broadcast(&can_enter_cond);
+out:
        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