diff options
author | Russ Cox <rsc@golang.org> | 2009-06-17 15:12:16 -0700 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2009-06-17 15:12:16 -0700 |
commit | 8b35fb2c49156940fa2aa83a17b8985e86dc6948 (patch) | |
tree | 26899cbde2c38fd1275b590dcdd6bf92ab0f80c9 /src/pkg/runtime/proc.c | |
parent | ac89b17a9fdbf67ce3fed035a454a5f9ba64722e (diff) | |
download | golang-8b35fb2c49156940fa2aa83a17b8985e86dc6948.tar.gz |
runtime: stack growth adjustments, cleanup
* keep coherent SP/PC in gobuf
(i.e., SP that would be in use at that PC)
* gogocall replaces setspgoto,
should work better in presence of link registers
* delete unused system calls
only amd64; 386 is now broken
R=r
DELTA=548 (183 added, 183 deleted, 182 changed)
OCL=30381
CL=30442
Diffstat (limited to 'src/pkg/runtime/proc.c')
-rw-r--r-- | src/pkg/runtime/proc.c | 154 |
1 files changed, 50 insertions, 104 deletions
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c index ada3efd4f..87b89f6a1 100644 --- a/src/pkg/runtime/proc.c +++ b/src/pkg/runtime/proc.c @@ -149,7 +149,7 @@ tracebackothers(G *me) if(g == me || g->status == Gdead) continue; printf("\ngoroutine %d:\n", g->goid); - traceback(g->sched.PC, g->sched.SP+sizeof(uintptr), g); // gogo adjusts SP by one word + traceback(g->sched.pc, g->sched.sp, g); } } @@ -387,7 +387,7 @@ matchmg(void) m->id = sched.mcount++; if(debug) { lock(&debuglock); - printf("alloc m%d g%d\n", m->id, g->goid); + printf("alloc m=%p m%d g%d\n", m, m->id, g->goid); unlock(&debuglock); } newosproc(m, m->g0, m->g0->stackbase, mstart); @@ -402,7 +402,7 @@ scheduler(void) G* gp; lock(&sched); - if(gosave(&m->sched)){ + if(gosave(&m->sched) != 0){ // Jumped here via gosave/gogo, so didn't // execute lock(&sched) above. lock(&sched); @@ -446,14 +446,15 @@ scheduler(void) gp->status = Grunning; if(debug > 1) { lock(&debuglock); - printf("m%d run g%d at %p\n", m->id, gp->goid, gp->sched.PC); - traceback(gp->sched.PC, gp->sched.SP+sizeof(uintptr), gp); + printf("m%d run g%d at %p\n", m->id, gp->goid, gp->sched.pc); + traceback(gp->sched.pc, gp->sched.sp, gp); unlock(&debuglock); } m->curg = gp; gp->m = m; - g = gp; - gogo(&gp->sched); + if(gp->sched.pc == (byte*)goexit) // kickoff + gogocall(&gp->sched, (void(*)(void))gp->entry); + gogo(&gp->sched, 1); } // Enter scheduler. If g->status is Grunning, @@ -465,10 +466,8 @@ gosched(void) { if(g == m->g0) throw("gosched of g0"); - if(gosave(&g->sched) == 0){ - g = m->g0; - gogo(&m->sched); - } + if(gosave(&g->sched) == 0) + gogo(&m->sched, 1); } // The goroutine g is about to enter a system call. @@ -606,53 +605,28 @@ enum void oldstack(void) { - Stktop *top; + Stktop *top, old; uint32 args; byte *sp; - uintptr oldsp, oldpc, oldbase, oldguard; - -// printf("oldstack m->cret=%p\n", m->cret); - - top = (Stktop*)m->curg->stackbase; + G *g1; - args = (top->magic>>32) & 0xffffLL; +//printf("oldstack m->cret=%p\n", m->cret); + g1 = m->curg; + top = (Stktop*)g1->stackbase; sp = (byte*)top; + old = *top; + args = old.args; if(args > 0) { - args = (args+7) & ~7; sp -= args; - mcpy(top->oldsp+2*sizeof(uintptr), sp, args); + mcpy(top->gobuf.sp, sp, args); } - oldsp = (uintptr)top->oldsp + sizeof(uintptr); - oldpc = *(uintptr*)oldsp; - oldbase = (uintptr)top->oldbase; - oldguard = (uintptr)top->oldguard; - - stackfree((byte*)m->curg->stackguard - StackGuard); - - m->curg->stackbase = (byte*)oldbase; - m->curg->stackguard = (byte*)oldguard; - m->morestack.SP = (byte*)oldsp; - m->morestack.PC = (byte*)oldpc; - - // These two lines must happen in sequence; - // once g has been changed, must switch to g's stack - // before calling any non-assembly functions. - // TODO(rsc): Perhaps make the new g a parameter - // to gogoret and setspgoto, so that g is never - // explicitly assigned to without also setting - // the stack pointer. - g = m->curg; - gogoret(&m->morestack, m->cret); -} + stackfree((byte*)g1->stackguard - StackGuard); + g1->stackbase = old.stackbase; + g1->stackguard = old.stackguard; -#pragma textflag 7 -void -lessstack(void) -{ - g = m->g0; - setspgoto(m->sched.SP, oldstack, nil); + gogo(&old.gobuf, m->cret); } void @@ -661,75 +635,49 @@ newstack(void) int32 frame, args; Stktop *top; byte *stk, *sp; - void (*fn)(void); - - frame = m->morearg & 0xffffffffLL; - args = (m->morearg>>32) & 0xffffLL; + G *g1; + Gobuf label; -// printf("newstack frame=%d args=%d moresp=%p morepc=%p\n", frame, args, m->moresp, *(uintptr*)m->moresp); + frame = m->moreframe; + args = m->moreargs; + + // Round up to align things nicely. + // This is sufficient for both 32- and 64-bit machines. + args = (args+7) & ~7; if(frame < StackBig) frame = StackBig; frame += 1024; // for more functions, Stktop. stk = stackalloc(frame); - top = (Stktop*)(stk+frame-sizeof(*top)); +//printf("newstack frame=%d args=%d morepc=%p gobuf=%p, %p newstk=%p\n", frame, args, m->morepc, g->sched.pc, g->sched.sp, stk); - top->oldbase = m->curg->stackbase; - top->oldguard = m->curg->stackguard; - top->oldsp = m->moresp; - top->magic = m->morearg; + g1 = m->curg; + top = (Stktop*)(stk+frame-sizeof(*top)); + top->stackbase = g1->stackbase; + top->stackguard = g1->stackguard; + top->gobuf = m->morebuf; + top->args = args; - m->curg->stackbase = (byte*)top; - m->curg->stackguard = stk + StackGuard; + g1->stackbase = (byte*)top; + g1->stackguard = stk + StackGuard; sp = (byte*)top; - if(args > 0) { - // Copy args. There have been two function calls - // since they got pushed, so skip over those return - // addresses. - args = (args+7) & ~7; sp -= args; - mcpy(sp, m->moresp+2*sizeof(uintptr), args); + mcpy(sp, top->gobuf.sp, args); } - g = m->curg; - - // sys.morestack's return address - fn = (void(*)(void))(*(uintptr*)m->moresp); - -// printf("fn=%p\n", fn); - - setspgoto(sp, fn, retfromnewstack); + // Continue as if lessstack had just called m->morepc + // (the PC that decided to grow the stack). + label.sp = sp; + label.pc = (byte*)sys·lessstack; + label.g = m->curg; + gogocall(&label, m->morepc); *(int32*)345 = 123; // never return } -#pragma textflag 7 -void -sys·morestack(uintptr u) -{ - while(g == m->g0) { - // very bad news - *(int32*)0x1001 = 123; - } - - // Morestack's frame is about 0x30 bytes on amd64. - // If that the frame ends below the stack bottom, we've already - // overflowed. Stop right now. - while((byte*)&u - 0x30 < m->curg->stackguard - StackGuard) { - // very bad news - *(int32*)0x1002 = 123; - } - - g = m->g0; - m->moresp = (byte*)(&u-1); - setspgoto(m->sched.SP, newstack, nil); - - *(int32*)0x1003 = 123; // never return -} - G* malg(int32 stacksize) { @@ -786,12 +734,10 @@ sys·newproc(int32 siz, byte* fn, byte* arg0) sp -= siz; mcpy(sp, (byte*)&arg0, siz); - sp -= sizeof(uintptr); - *(byte**)sp = (byte*)goexit; - - sp -= sizeof(uintptr); // retpc used by gogo - newg->sched.SP = sp; - newg->sched.PC = fn; + newg->sched.sp = sp; + newg->sched.pc = (byte*)goexit; + newg->sched.g = newg; + newg->entry = fn; sched.gcount++; goidgen++; |