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)