diff options
| author | Russ Cox <rsc@golang.org> | 2014-10-03 12:22:19 -0400 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2014-10-03 12:22:19 -0400 |
| commit | 904ec0098137f742e0dd96da3bc033d6a0b615d1 (patch) | |
| tree | 6a05a91443927524fcb78ac82df0142d8e6ae71f /src/runtime/stack.c | |
| parent | d42328c9f749140adf947833e0381fc639c32737 (diff) | |
| parent | c65a47f890e33eeed6ee9d8b6d965a5534fb6e0e (diff) | |
| download | go-904ec0098137f742e0dd96da3bc033d6a0b615d1.tar.xz | |
[dev.garbage] merge default into dev.garbage
Diffstat (limited to 'src/runtime/stack.c')
| -rw-r--r-- | src/runtime/stack.c | 92 |
1 files changed, 61 insertions, 31 deletions
diff --git a/src/runtime/stack.c b/src/runtime/stack.c index 143b645e42..8562b94076 100644 --- a/src/runtime/stack.c +++ b/src/runtime/stack.c @@ -32,8 +32,8 @@ enum // Stacks are assigned an order according to size. // order = log_2(size/FixedStack) // There is a free list for each order. -static MSpan stackpool[NumStackOrders]; -static Mutex stackpoolmu; +MSpan runtime·stackpool[NumStackOrders]; +Mutex runtime·stackpoolmu; // TODO: one lock per order? void @@ -45,7 +45,7 @@ runtime·stackinit(void) runtime·throw("cache size must be a multiple of page size"); for(i = 0; i < NumStackOrders; i++) - runtime·MSpanList_Init(&stackpool[i]); + runtime·MSpanList_Init(&runtime·stackpool[i]); } // Allocates a stack from the free pool. Must be called with @@ -58,7 +58,7 @@ poolalloc(uint8 order) MLink *x; uintptr i; - list = &stackpool[order]; + list = &runtime·stackpool[order]; s = list->next; if(s == list) { // no free stacks. Allocate another span worth. @@ -99,7 +99,7 @@ poolfree(MLink *x, uint8 order) runtime·throw("freeing stack not in a stack span"); if(s->freelist == nil) { // s will now have a free stack - runtime·MSpanList_Insert(&stackpool[order], s); + runtime·MSpanList_Insert(&runtime·stackpool[order], s); } x->next = s->freelist; s->freelist = x; @@ -127,14 +127,14 @@ stackcacherefill(MCache *c, uint8 order) // Grab half of the allowed capacity (to prevent thrashing). list = nil; size = 0; - runtime·lock(&stackpoolmu); + runtime·lock(&runtime·stackpoolmu); while(size < StackCacheSize/2) { x = poolalloc(order); x->next = list; list = x; size += FixedStack << order; } - runtime·unlock(&stackpoolmu); + runtime·unlock(&runtime·stackpoolmu); c->stackcache[order].list = list; c->stackcache[order].size = size; @@ -150,14 +150,14 @@ stackcacherelease(MCache *c, uint8 order) runtime·printf("stackcacherelease order=%d\n", order); x = c->stackcache[order].list; size = c->stackcache[order].size; - runtime·lock(&stackpoolmu); + runtime·lock(&runtime·stackpoolmu); while(size > StackCacheSize/2) { y = x->next; poolfree(x, order); x = y; size -= FixedStack << order; } - runtime·unlock(&stackpoolmu); + runtime·unlock(&runtime·stackpoolmu); c->stackcache[order].list = x; c->stackcache[order].size = size; } @@ -170,7 +170,7 @@ runtime·stackcache_clear(MCache *c) if(StackDebug >= 1) runtime·printf("stackcache clear\n"); - runtime·lock(&stackpoolmu); + runtime·lock(&runtime·stackpoolmu); for(order = 0; order < NumStackOrders; order++) { x = c->stackcache[order].list; while(x != nil) { @@ -181,7 +181,7 @@ runtime·stackcache_clear(MCache *c) c->stackcache[order].list = nil; c->stackcache[order].size = 0; } - runtime·unlock(&stackpoolmu); + runtime·unlock(&runtime·stackpoolmu); } Stack @@ -227,9 +227,9 @@ runtime·stackalloc(uint32 n) // procresize. Just get a stack from the global pool. // Also don't touch stackcache during gc // as it's flushed concurrently. - runtime·lock(&stackpoolmu); + runtime·lock(&runtime·stackpoolmu); x = poolalloc(order); - runtime·unlock(&stackpoolmu); + runtime·unlock(&runtime·stackpoolmu); } else { x = c->stackcache[order].list; if(x == nil) { @@ -289,9 +289,9 @@ runtime·stackfree(Stack stk) x = (MLink*)v; c = g->m->mcache; if(c == nil || g->m->gcing || g->m->helpgc) { - runtime·lock(&stackpoolmu); + runtime·lock(&runtime·stackpoolmu); poolfree(x, order); - runtime·unlock(&stackpoolmu); + runtime·unlock(&runtime·stackpoolmu); } else { if(c->stackcache[order].size >= StackCacheSize) stackcacherelease(c, order); @@ -463,7 +463,7 @@ adjustframe(Stkframe *frame, void *arg) StackMap *stackmap; int32 pcdata; BitVector bv; - uintptr targetpc; + uintptr targetpc, size, minsize; adjinfo = arg; targetpc = frame->continpc; @@ -486,27 +486,47 @@ adjustframe(Stkframe *frame, void *arg) if(pcdata == -1) pcdata = 0; // in prologue - // adjust local pointers - if((byte*)frame->varp != (byte*)frame->sp) { + // Adjust local variables if stack frame has been allocated. + size = frame->varp - frame->sp; + if(thechar != '6' && thechar != '8') + minsize = sizeof(uintptr); + else + minsize = 0; + if(size > minsize) { stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps); - if(stackmap == nil) - runtime·throw("no locals info"); - if(stackmap->n <= 0) - runtime·throw("locals size info only"); + if(stackmap == nil || stackmap->n <= 0) { + runtime·printf("runtime: frame %s untyped locals %p+%p\n", runtime·funcname(f), (byte*)(frame->varp-size), size); + runtime·throw("missing stackmap"); + } + // Locals bitmap information, scan just the pointers in locals. + if(pcdata < 0 || pcdata >= stackmap->n) { + // don't know where we are + runtime·printf("runtime: pcdata is %d and %d locals stack map entries for %s (targetpc=%p)\n", + pcdata, stackmap->n, runtime·funcname(f), targetpc); + runtime·throw("bad symbol table"); + } bv = runtime·stackmapdata(stackmap, pcdata); + size = (bv.n * PtrSize) / BitsPerPointer; if(StackDebug >= 3) runtime·printf(" locals\n"); - adjustpointers((byte**)frame->varp - bv.n / BitsPerPointer, &bv, adjinfo, f); + adjustpointers((byte**)(frame->varp - size), &bv, adjinfo, f); } - // adjust inargs and outargs - if(frame->arglen != 0) { + + // Adjust arguments. + if(frame->arglen > 0) { if(frame->argmap != nil) { bv = *frame->argmap; } else { stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps); - if(stackmap == nil) { - runtime·printf("size %d\n", (int32)frame->arglen); - runtime·throw("no arg info"); + if(stackmap == nil || stackmap->n <= 0) { + runtime·printf("runtime: frame %s untyped args %p+%p\n", runtime·funcname(f), frame->argp, (uintptr)frame->arglen); + runtime·throw("missing stackmap"); + } + if(pcdata < 0 || pcdata >= stackmap->n) { + // don't know where we are + runtime·printf("runtime: pcdata is %d and %d args stack map entries for %s (targetpc=%p)\n", + pcdata, stackmap->n, runtime·funcname(f), targetpc); + runtime·throw("bad symbol table"); } bv = runtime·stackmapdata(stackmap, pcdata); } @@ -675,7 +695,7 @@ runtime·newstack(void) runtime·traceback(morebuf.pc, morebuf.sp, morebuf.lr, morebuf.g); runtime·throw("runtime: wrong goroutine in newstack"); } - if(g->throwsplit) + if(g->m->curg->throwsplit) runtime·throw("runtime: stack split at bad time"); // The goroutine must be executing in order to call newstack, @@ -786,8 +806,16 @@ runtime·shrinkstack(G *gp) { uintptr used, oldsize, newsize; - if(runtime·readgstatus(gp) == Gdead) + if(runtime·readgstatus(gp) == Gdead) { + if(gp->stack.lo != 0) { + // Free whole stack - it will get reallocated + // if G is used again. + runtime·stackfree(gp->stack); + gp->stack.lo = 0; + gp->stack.hi = 0; + } return; + } if(gp->stack.lo == 0) runtime·throw("missing stack in shrinkstack"); @@ -799,7 +827,9 @@ runtime·shrinkstack(G *gp) if(used >= oldsize / 4) return; // still using at least 1/4 of the segment. - if(gp->syscallsp != 0) // TODO: can we handle this case? + // We can't copy the stack if we're in a syscall. + // The syscall might have pointers into the stack. + if(gp->syscallsp != 0) return; #ifdef GOOS_windows |
