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
This commit is contained in:
Ian Lance Taylor 2013-12-12 20:13:58 +00:00
parent 96d91784e5
commit 1635eab367
6 changed files with 19 additions and 5 deletions

View File

@ -28,6 +28,7 @@ __go_defer (_Bool *frame, void (*pfn) (void *), void *arg)
n->__arg = arg; n->__arg = arg;
n->__retaddr = NULL; n->__retaddr = NULL;
n->__makefunc_can_recover = 0; n->__makefunc_can_recover = 0;
n->__free = 1;
g->defer = n; g->defer = n;
} }
@ -59,7 +60,7 @@ __go_undefer (_Bool *frame)
have a memory context. Don't try to free anything in that have a memory context. Don't try to free anything in that
case--the GC will release it later. */ case--the GC will release it later. */
m = runtime_m (); m = runtime_m ();
if (m != NULL && m->mcache != NULL) if (m != NULL && m->mcache != NULL && d->__free)
__go_free (d); __go_free (d);
/* Since we are executing a defer function here, we know we are /* Since we are executing a defer function here, we know we are

View File

@ -40,4 +40,8 @@ struct __go_defer_stack
function will be somewhere in libffi, so __retaddr is not function will be somewhere in libffi, so __retaddr is not
useful. */ useful. */
_Bool __makefunc_can_recover; _Bool __makefunc_can_recover;
/* Set to true if this defer stack entry should be freed when
done. */
_Bool __free;
}; };

View File

@ -102,7 +102,7 @@ __go_panic (struct __go_empty_interface arg)
have a memory context. Don't try to free anything in that have a memory context. Don't try to free anything in that
case--the GC will release it later. */ case--the GC will release it later. */
m = runtime_m (); m = runtime_m ();
if (m != NULL && m->mcache != NULL) if (m != NULL && m->mcache != NULL && d->__free)
__go_free (d); __go_free (d);
} }

View File

@ -80,6 +80,7 @@ __go_check_defer (_Bool *frame)
{ {
struct __go_defer_stack *d; struct __go_defer_stack *d;
void (*pfn) (void *); void (*pfn) (void *);
M *m;
d = g->defer; d = g->defer;
if (d == NULL || d->__frame != frame || d->__pfn == NULL) if (d == NULL || d->__frame != frame || d->__pfn == NULL)
@ -90,7 +91,9 @@ __go_check_defer (_Bool *frame)
(*pfn) (d->__arg); (*pfn) (d->__arg);
__go_free (d); m = runtime_m ();
if (m != NULL && m->mcache != NULL && d->__free)
__go_free (d);
if (n->__was_recovered) if (n->__was_recovered)
{ {
@ -119,13 +122,17 @@ __go_check_defer (_Bool *frame)
&& g->defer->__frame == frame) && g->defer->__frame == frame)
{ {
struct __go_defer_stack *d; struct __go_defer_stack *d;
M *m;
/* This is the defer function which called recover. Simply /* This is the defer function which called recover. Simply
return to stop the stack unwind, and let the Go code continue return to stop the stack unwind, and let the Go code continue
to execute. */ to execute. */
d = g->defer; d = g->defer;
g->defer = d->__next; 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. */ /* We are returning from this function. */
*frame = 1; *frame = 1;

View File

@ -28,7 +28,8 @@ rundefer(void)
d->__pfn = nil; d->__pfn = nil;
if (pfn != nil) if (pfn != nil)
(*pfn)(d->__arg); (*pfn)(d->__arg);
runtime_free(d); if (d->__free)
runtime_free(d);
} }
} }

View File

@ -541,6 +541,7 @@ runtime_main(void* dummy __attribute__((unused)))
d.__retaddr = nil; d.__retaddr = nil;
d.__makefunc_can_recover = 0; d.__makefunc_can_recover = 0;
d.__frame = &frame; d.__frame = &frame;
d.__free = 0;
g->defer = &d; g->defer = &d;
if(m != &runtime_m0) if(m != &runtime_m0)