Patchwork [gccgo] Avoid GC deadlock

login
register
mail settings
Submitter Ian Taylor
Date Aug. 26, 2010, 10:10 p.m.
Message ID <mcry6btkotd.fsf@google.com>
Download mbox | patch
Permalink /patch/62809/
State New
Headers show

Comments

Ian Taylor - Aug. 26, 2010, 10:10 p.m.
I discovered a possible deadlock in the garbage collector due to memory
profiling.  When a thread is gathering data for memory profiling, it
postpones GC until that is complete.  The same happens during memory
allocation.  However, memory profiling can actually lead to memory
allocation.  Because the code used the same variable to postpone GC,
that can cause the GC to start when the memory allocation is complete
but memory profiling is still active.  That can in turn cause a deadlock
when the GC releases memory profiling data.

This patch avoids the deadlock by using a different variable to postpone
GC while doing memory profiling.  Committed to gccgo branch.

Ian

Patch

diff -r b20eed5a1425 libgo/runtime/go-go.c
--- a/libgo/runtime/go-go.c	Wed Aug 25 16:59:52 2010 -0700
+++ b/libgo/runtime/go-go.c	Thu Aug 26 15:06:20 2010 -0700
@@ -323,7 +323,7 @@ 
       /* Similarly, we can't interrupt the thread while it is building
 	 profiling information.  Otherwise we can get into a deadlock
 	 when sweepspan calls MProf_Free.  */
-      __sync_bool_compare_and_swap (&pm->gcing, 0, 1);
+      __sync_bool_compare_and_swap (&pm->gcing_for_prof, 0, 1);
       return;
     }
 
diff -r b20eed5a1425 libgo/runtime/mprof.goc
--- a/libgo/runtime/mprof.goc	Wed Aug 25 16:59:52 2010 -0700
+++ b/libgo/runtime/mprof.goc	Thu Aug 26 15:06:20 2010 -0700
@@ -208,7 +208,7 @@ 
 	unlock(&proflock);
 	__sync_bool_compare_and_swap(&m->nomemprof, 1, 0);
 
-	if(__sync_bool_compare_and_swap(&m->gcing, 1, 0))
+	if(__sync_bool_compare_and_swap(&m->gcing_for_prof, 1, 0))
 		__go_run_goroutine_gc(100);
 }
 
@@ -230,7 +230,7 @@ 
 	unlock(&proflock);
 	__sync_bool_compare_and_swap(&m->nomemprof, 1, 0);
 
-	if(__sync_bool_compare_and_swap(&m->gcing, 1, 0))
+	if(__sync_bool_compare_and_swap(&m->gcing_for_prof, 1, 0))
 		__go_run_goroutine_gc(101);
 }
 
@@ -285,7 +285,7 @@ 
 
 	__sync_bool_compare_and_swap(&m->nomemprof, 1, 0);
 
-	if(__sync_bool_compare_and_swap(&m->gcing, 1, 0))
+	if(__sync_bool_compare_and_swap(&m->gcing_for_prof, 1, 0))
 		__go_run_goroutine_gc(102);
 }
 
diff -r b20eed5a1425 libgo/runtime/runtime.h
--- a/libgo/runtime/runtime.h	Wed Aug 25 16:59:52 2010 -0700
+++ b/libgo/runtime/runtime.h	Thu Aug 26 15:06:20 2010 -0700
@@ -94,6 +94,7 @@ 
 	int32	gcing;
 	int32	locks;
 	int32	nomemprof;
+	int32	gcing_for_prof;
 	MCache	*mcache;
 
 	/* For the list of all threads.  */