[RFC][PATCH] gc: rewrite GC stop-the-world algorithm.

2009-12-16 Thread Tomek Grabiec
Garbage collection is done in a separate thread.

Before the main GC work is started, thread creation and destruction
must be disabled and all mutator threads must be suspended. The
SIGUSR2 signal is sent to all threads. The signal handler determines
whether a thread is running JIT code or native code. In the former
case the handler returns to let the thread reach a safepoint. In the
latter case it is put into safepoint immediately.  When thread is
suspended in safepoint it waits for another SIGUSR2 signal which is
sent by the GC thread to wake threads up.

We must not use mutexes from signal handlers because
pthread_mutex_lock() is not reentrant. Using it from a signal handler
may result in a deadlock. This approach uses semaphores to notify GC
when a thread enters or leaves a safepoint.

Signed-off-by: Tomek Grabiec tgrab...@gmail.com
---
 arch/x86/include/arch/memory.h|   13 +++
 include/vm/gc.h   |4 +-
 include/vm/thread.h   |9 ++-
 regression/jvm/GcTortureTest.java |2 +-
 vm/gc.c   |  216 ++---
 vm/signal.c   |9 +--
 vm/thread.c   |   85 +++
 7 files changed, 194 insertions(+), 144 deletions(-)

diff --git a/arch/x86/include/arch/memory.h b/arch/x86/include/arch/memory.h
index e27c31b..30f8c0f 100644
--- a/arch/x86/include/arch/memory.h
+++ b/arch/x86/include/arch/memory.h
@@ -3,6 +3,19 @@
 
 #include stdint.h
 
+/*
+ * Memory barriers.
+ */
+#ifdef CONFIG_X86_32
+#define mb() asm volatile(lock; addl $0,0(%esp))
+#define rmb() asm volatile(lock; addl $0,0(%esp))
+#define wmb() asm volatile(lock; addl $0,0(%esp))
+#else
+#define mb()   asm volatile(mfence:::memory)
+#define rmb()  asm volatile(lfence:::memory)
+#define wmb()  asm volatile(sfence ::: memory)
+#endif
+
 static inline void cpu_write_u32(unsigned char *p, uint32_t val)
 {
*((uint32_t*)p) = val;
diff --git a/include/vm/gc.h b/include/vm/gc.h
index 06bebc6..7d23f5b 100644
--- a/include/vm/gc.h
+++ b/include/vm/gc.h
@@ -13,9 +13,7 @@ void gc_init(void);
 
 void *gc_alloc(size_t size);
 
-void gc_attach_thread(void);
-void gc_detach_thread(void);
-
 void gc_safepoint(struct register_state *);
+void suspend_handler(int, siginfo_t *, void *);
 
 #endif
diff --git a/include/vm/thread.h b/include/vm/thread.h
index f6e6551..97f672e 100644
--- a/include/vm/thread.h
+++ b/include/vm/thread.h
@@ -36,7 +36,7 @@ struct vm_exec_env {
struct vm_thread *thread;
 };
 
-unsigned int vm_nr_threads_running(void);
+unsigned int vm_nr_threads(void);
 
 extern __thread struct vm_exec_env current_exec_env;
 
@@ -59,5 +59,12 @@ char *vm_thread_get_name(struct vm_thread *thread);
 bool vm_thread_is_interrupted(struct vm_thread *thread);
 bool vm_thread_interrupted(struct vm_thread *thread);
 void vm_thread_interrupt(struct vm_thread *thread);
+void vm_lock_thread_count(void);
+void vm_unlock_thread_count(void);
+
+extern struct list_head thread_list;
+extern pthread_mutex_t threads_mutex;
+
+#define vm_thread_for_each(this) list_for_each_entry(this, thread_list, 
list_node)
 
 #endif
diff --git a/regression/jvm/GcTortureTest.java 
b/regression/jvm/GcTortureTest.java
index 33eef15..9f00232 100644
--- a/regression/jvm/GcTortureTest.java
+++ b/regression/jvm/GcTortureTest.java
@@ -7,7 +7,7 @@ public class GcTortureTest {
 for (int i = 0; i  threads.length; i++) {
 threads[i] = new Thread(new Runnable() {
 public void run() {
-for (int i = 0; i  100; i++)
+for (int i = 0; i  10; i++)
   new Object();
 }
 });
diff --git a/vm/gc.c b/vm/gc.c
index 0815d59..3de8f21 100644
--- a/vm/gc.c
+++ b/vm/gc.c
@@ -1,45 +1,37 @@
 #include assert.h
+#include pthread.h
+#include semaphore.h
 #include stdbool.h
 #include stdio.h
-#include pthread.h
 
+#include arch/memory.h
 #include arch/registers.h
+#include arch/signal.h
 #include lib/guard-page.h
 #include vm/thread.h
 #include vm/stdlib.h
 #include vm/die.h
 #include vm/gc.h
+#include vm/trace.h
 
 void *gc_safepoint_page;
 
-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_exiting_safepoint;
-static unsigned int nr_in_safepoint;
+static pthread_mutex_t gc_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t gc_cond = PTHREAD_COND_INITIALIZER;
 
-static pthread_cond_t can_continue_cond = PTHREAD_COND_INITIALIZER;
-static bool can_continue = true;
+/* Protected by gc_mutex */
+static unsigned int nr_threads;
+static bool gc_started;
 
-bool verbose_gc;
-bool gc_enabled;
+static sem_t safepoint_sem;
 
-void gc_init(void)
-{
-   gc_safepoint_page = alloc_guard_page(false);
-   if (!gc_safepoint_page)
-  

[penberg/jato] 6f76d8: gc: rewrite GC stop-the-world algorithm.

2009-12-16 Thread noreply
Branch: refs/heads/master
Home:   http://github.com/penberg/jato

Commit: 6f76d8586618a09d7c8173b5aaff38b011436317

http://github.com/penberg/jato/commit/6f76d8586618a09d7c8173b5aaff38b011436317
Author: Tomek Grabiec tgrab...@gmail.com
Date:   2009-12-16 (Wed, 16 Dec 2009)

Changed paths:
  M arch/x86/include/arch/memory.h
  M include/vm/gc.h
  M include/vm/thread.h
  M vm/gc.c
  M vm/signal.c
  M vm/thread.c

Log Message:
---
gc: rewrite GC stop-the-world algorithm.

Garbage collection is done in a separate thread.

Before the main GC work is started, thread creation and destruction
must be disabled and all mutator threads must be suspended. The
SIGUSR2 signal is sent to all threads. The signal handler determines
whether a thread is running JIT code or native code. In the former
case the handler returns to let the thread reach a safepoint. In the
latter case it is put into safepoint immediately.  When thread is
suspended in safepoint it waits for another SIGUSR2 signal which is
sent by the GC thread to wake threads up.

We must not use mutexes from signal handlers because
pthread_mutex_lock() is not reentrant. Using it from a signal handler
may result in a deadlock. This approach uses semaphores to notify GC
when a thread enters or leaves a safepoint.

[ penb...@cs.helsinki.fi: Remove dubious use of 'volatile' ]
Signed-off-by: Tomek Grabiec tgrab...@gmail.com
Signed-off-by: Pekka Enberg penb...@cs.helsinki.fi



--
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
___
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel