summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/proc.c
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-06-17 15:12:16 -0700
committerRuss Cox <rsc@golang.org>2009-06-17 15:12:16 -0700
commit8b35fb2c49156940fa2aa83a17b8985e86dc6948 (patch)
tree26899cbde2c38fd1275b590dcdd6bf92ab0f80c9 /src/pkg/runtime/proc.c
parentac89b17a9fdbf67ce3fed035a454a5f9ba64722e (diff)
downloadgolang-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.c154
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++;