This patch to libgo fixes the handling of the deferring of the unlock
thread at program startup.  The code was incorrectly freeing a stack
object.  This patch also cleans up some cases of freeing a defer block
to avoid doing it when there is no Go context available.  Bootstrapped
and ran Go testsuite on x86_64-unknown-linux-gnu.  Committed to
mainline.

Ian

diff -r f3ec8ff457ec -r 9931ebbea550 libgo/runtime/go-defer.c
--- a/libgo/runtime/go-defer.c	Thu Dec 12 11:23:56 2013 -0800
+++ b/libgo/runtime/go-defer.c	Thu Dec 12 12:13:34 2013 -0800
@@ -28,6 +28,7 @@
   n->__arg = arg;
   n->__retaddr = NULL;
   n->__makefunc_can_recover = 0;
+  n->__free = 1;
   g->defer = n;
 }
 
@@ -59,7 +60,7 @@
 	 have a memory context.  Don't try to free anything in that
 	 case--the GC will release it later.  */
       m = runtime_m ();
-      if (m != NULL && m->mcache != NULL)
+      if (m != NULL && m->mcache != NULL && d->__free)
 	__go_free (d);
 
       /* Since we are executing a defer function here, we know we are
diff -r f3ec8ff457ec -r 9931ebbea550 libgo/runtime/go-defer.h
--- a/libgo/runtime/go-defer.h	Thu Dec 12 11:23:56 2013 -0800
+++ b/libgo/runtime/go-defer.h	Thu Dec 12 12:13:34 2013 -0800
@@ -40,4 +40,8 @@
      function will be somewhere in libffi, so __retaddr is not
      useful.  */
   _Bool __makefunc_can_recover;
+
+  /* Set to true if this defer stack entry should be freed when
+     done.  */
+  _Bool __free;
 };
diff -r f3ec8ff457ec -r 9931ebbea550 libgo/runtime/go-panic.c
--- a/libgo/runtime/go-panic.c	Thu Dec 12 11:23:56 2013 -0800
+++ b/libgo/runtime/go-panic.c	Thu Dec 12 12:13:34 2013 -0800
@@ -102,7 +102,7 @@
 	 have a memory context.  Don't try to free anything in that
 	 case--the GC will release it later.  */
       m = runtime_m ();
-      if (m != NULL && m->mcache != NULL)
+      if (m != NULL && m->mcache != NULL && d->__free)
 	__go_free (d);
     }
 
diff -r f3ec8ff457ec -r 9931ebbea550 libgo/runtime/go-unwind.c
--- a/libgo/runtime/go-unwind.c	Thu Dec 12 11:23:56 2013 -0800
+++ b/libgo/runtime/go-unwind.c	Thu Dec 12 12:13:34 2013 -0800
@@ -80,6 +80,7 @@
 	{
 	  struct __go_defer_stack *d;
 	  void (*pfn) (void *);
+	  M *m;
 
 	  d = g->defer;
 	  if (d == NULL || d->__frame != frame || d->__pfn == NULL)
@@ -90,7 +91,9 @@
 
 	  (*pfn) (d->__arg);
 
-	  __go_free (d);
+	  m = runtime_m ();
+	  if (m != NULL && m->mcache != NULL && d->__free)
+	    __go_free (d);
 
 	  if (n->__was_recovered)
 	    {
@@ -119,13 +122,17 @@
 	   && g->defer->__frame == frame)
     {
       struct __go_defer_stack *d;
+      M *m;
 
       /* This is the defer function which called recover.  Simply
 	 return to stop the stack unwind, and let the Go code continue
 	 to execute.  */
       d = g->defer;
       g->defer = d->__next;
-      __go_free (d);
+
+      m = runtime_m ();
+      if (m != NULL && m->mcache != NULL && d->__free)
+	__go_free (d);
 
       /* We are returning from this function.  */
       *frame = 1;
diff -r f3ec8ff457ec -r 9931ebbea550 libgo/runtime/panic.c
--- a/libgo/runtime/panic.c	Thu Dec 12 11:23:56 2013 -0800
+++ b/libgo/runtime/panic.c	Thu Dec 12 12:13:34 2013 -0800
@@ -28,7 +28,8 @@
 		d->__pfn = nil;
 		if (pfn != nil)
 			(*pfn)(d->__arg);
-		runtime_free(d);
+		if (d->__free)
+		  runtime_free(d);
 	}
 }
 
diff -r f3ec8ff457ec -r 9931ebbea550 libgo/runtime/proc.c
--- a/libgo/runtime/proc.c	Thu Dec 12 11:23:56 2013 -0800
+++ b/libgo/runtime/proc.c	Thu Dec 12 12:13:34 2013 -0800
@@ -541,6 +541,7 @@
 	d.__retaddr = nil;
 	d.__makefunc_can_recover = 0;
 	d.__frame = &frame;
+	d.__free = 0;
 	g->defer = &d;
 
 	if(m != &runtime_m0)

Reply via email to