From 1635eab367caf9615b4156090fbcd4251fd46e32 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 12 Dec 2013 20:13:58 +0000 Subject: [PATCH] runtime: Fix defer of unlock thread at program startup. Don't free stack allocated defer block. Also ensure we have a Go context in a few more places before freeing the block. From-SVN: r205940 --- libgo/runtime/go-defer.c | 3 ++- libgo/runtime/go-defer.h | 4 ++++ libgo/runtime/go-panic.c | 2 +- libgo/runtime/go-unwind.c | 11 +++++++++-- libgo/runtime/panic.c | 3 ++- libgo/runtime/proc.c | 1 + 6 files changed, 19 insertions(+), 5 deletions(-) diff --git a/libgo/runtime/go-defer.c b/libgo/runtime/go-defer.c index fed8db385ae..4c61ae7db2f 100644 --- a/libgo/runtime/go-defer.c +++ b/libgo/runtime/go-defer.c @@ -28,6 +28,7 @@ __go_defer (_Bool *frame, void (*pfn) (void *), void *arg) n->__arg = arg; n->__retaddr = NULL; n->__makefunc_can_recover = 0; + n->__free = 1; g->defer = n; } @@ -59,7 +60,7 @@ __go_undefer (_Bool *frame) 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 --git a/libgo/runtime/go-defer.h b/libgo/runtime/go-defer.h index 3298ce95059..d110a8766e3 100644 --- a/libgo/runtime/go-defer.h +++ b/libgo/runtime/go-defer.h @@ -40,4 +40,8 @@ struct __go_defer_stack 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 --git a/libgo/runtime/go-panic.c b/libgo/runtime/go-panic.c index 7e284eeaa3d..0cacbcd91cb 100644 --- a/libgo/runtime/go-panic.c +++ b/libgo/runtime/go-panic.c @@ -102,7 +102,7 @@ __go_panic (struct __go_empty_interface arg) 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 --git a/libgo/runtime/go-unwind.c b/libgo/runtime/go-unwind.c index c669a3ce889..04b0a28607a 100644 --- a/libgo/runtime/go-unwind.c +++ b/libgo/runtime/go-unwind.c @@ -80,6 +80,7 @@ __go_check_defer (_Bool *frame) { 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 @@ __go_check_defer (_Bool *frame) (*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 @@ __go_check_defer (_Bool *frame) && 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 --git a/libgo/runtime/panic.c b/libgo/runtime/panic.c index 7a8d95b1ade..8fe321f6af2 100644 --- a/libgo/runtime/panic.c +++ b/libgo/runtime/panic.c @@ -28,7 +28,8 @@ rundefer(void) d->__pfn = nil; if (pfn != nil) (*pfn)(d->__arg); - runtime_free(d); + if (d->__free) + runtime_free(d); } } diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c index 0d0127b6c75..8f54e51df35 100644 --- a/libgo/runtime/proc.c +++ b/libgo/runtime/proc.c @@ -541,6 +541,7 @@ runtime_main(void* dummy __attribute__((unused))) d.__retaddr = nil; d.__makefunc_can_recover = 0; d.__frame = &frame; + d.__free = 0; g->defer = &d; if(m != &runtime_m0)