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 <[email protected]>
Signed-off-by: Pekka Enberg <[email protected]>
---
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/jatovm-devel