preserve AX across stack jump so C routines return correct value when triggering morestack.

SVN=126935
This commit is contained in:
Rob Pike 2008-07-12 11:30:53 -07:00
parent 5a81d1f29f
commit 2da9783e2b
4 changed files with 34 additions and 14 deletions

View File

@ -72,6 +72,25 @@ TEXT gosave(SB), 7, $0
MOVL $0, AX // return 0 MOVL $0, AX // return 0
RET RET
/*
* support for morestack
*/
// return point when leaving new stack. save AX, jmp to oldstack to switch back
TEXT retfromnewstack(SB), 7, $0
MOVQ AX, 16(R14) // save AX in m->cret
MOVQ $oldstack(SB), AX
JMP AX
// gogo, returning 2nd arg instead of 1
TEXT gogoret(SB), 7, $0
MOVQ 16(SP), AX // return 2nd arg
MOVQ 8(SP), BX // gobuf
MOVQ 0(BX), SP // restore SP
MOVQ 8(BX), BX
MOVQ BX, 0(SP) // put PC on the stack
RET
TEXT setspgoto(SB), 7, $0 TEXT setspgoto(SB), 7, $0
MOVQ 8(SP), AX // SP MOVQ 8(SP), AX // SP
MOVQ 16(SP), BX // fn to call MOVQ 16(SP), BX // fn to call

View File

@ -8,8 +8,6 @@ extern int32 debug;
static int8 spmark[] = "\xa7\xf1\xd9\x2a\x82\xc8\xd8\xfe"; static int8 spmark[] = "\xa7\xf1\xd9\x2a\x82\xc8\xd8\xfe";
extern void morestack2();
void void
traceback(uint8 *pc, uint8 *sp, void* r15) traceback(uint8 *pc, uint8 *sp, void* r15)
{ {
@ -29,8 +27,8 @@ traceback(uint8 *pc, uint8 *sp, void* r15)
name = "panic"; name = "panic";
for(;;){ for(;;){
callpc = pc; callpc = pc;
if((uint8*)morestack2 == pc) { if((uint8*)retfromnewstack == pc) {
// call site is morestack2(); pop to earlier stack block to get true caller // call site is retfromnewstack(); pop to earlier stack block to get true caller
stktop = (Stktop*)g.stackbase; stktop = (Stktop*)g.stackbase;
g.stackbase = stktop->oldbase; g.stackbase = stktop->oldbase;
g.stackguard = stktop->oldguard; g.stackguard = stktop->oldguard;

View File

@ -698,15 +698,15 @@ sys·gosched(void)
// CALL sys·morestack(SB) // CALL sys·morestack(SB)
// //
int32 debug = 0;
void void
morestack2(void) oldstack(void)
{ {
Stktop *top; Stktop *top;
uint32 siz2; uint32 siz2;
byte *sp; byte *sp;
if(debug) prints("morestack2\n"); if(debug) prints("oldstack m->cret = ");
if(debug) sys·printpointer((void*)m->cret);
if(debug) prints("\n");
top = (Stktop*)m->curg->stackbase; top = (Stktop*)m->curg->stackbase;
@ -723,16 +723,16 @@ if(debug) prints("morestack2\n");
m->morestack.SP = top->oldsp+8; m->morestack.SP = top->oldsp+8;
m->morestack.PC = (byte*)(*(uint64*)(top->oldsp+8)); m->morestack.PC = (byte*)(*(uint64*)(top->oldsp+8));
if(debug) prints("morestack2 sp="); if(debug) prints("oldstack sp=");
if(debug) sys·printpointer(m->morestack.SP); if(debug) sys·printpointer(m->morestack.SP);
if(debug) prints(" pc="); if(debug) prints(" pc=");
if(debug) sys·printpointer(m->morestack.PC); if(debug) sys·printpointer(m->morestack.PC);
if(debug) prints("\n"); if(debug) prints("\n");
gogo(&m->morestack); gogoret(&m->morestack, m->cret);
} }
void void
morestack1(void) newstack(void)
{ {
int32 siz1, siz2; int32 siz1, siz2;
Stktop *top; Stktop *top;
@ -742,7 +742,7 @@ morestack1(void)
siz1 = m->morearg & 0xffffffffLL; siz1 = m->morearg & 0xffffffffLL;
siz2 = (m->morearg>>32) & 0xffffLL; siz2 = (m->morearg>>32) & 0xffffLL;
if(debug) prints("morestack1 siz1="); if(debug) prints("newstack siz1=");
if(debug) sys·printint(siz1); if(debug) sys·printint(siz1);
if(debug) prints(" siz2="); if(debug) prints(" siz2=");
if(debug) sys·printint(siz2); if(debug) sys·printint(siz2);
@ -778,7 +778,7 @@ if(debug) prints("\n");
if(debug) prints("fn="); if(debug) prints("fn=");
if(debug) sys·printpointer(fn); if(debug) sys·printpointer(fn);
if(debug) prints("\n"); if(debug) prints("\n");
setspgoto(sp, fn, morestack2); setspgoto(sp, fn, retfromnewstack);
*(int32*)345 = 123; *(int32*)345 = 123;
} }
@ -793,7 +793,7 @@ sys·morestack(uint64 u)
g = m->g0; g = m->g0;
m->moresp = (byte*)(&u-1); m->moresp = (byte*)(&u-1);
setspgoto(m->sched.SP, morestack1, nil); setspgoto(m->sched.SP, newstack, nil);
*(int32*)234 = 123; *(int32*)234 = 123;
} }

View File

@ -82,6 +82,7 @@ struct M
{ {
G* g0; // g0 w interrupt stack - must not move G* g0; // g0 w interrupt stack - must not move
uint64 morearg; // arg to morestack - must not move uint64 morearg; // arg to morestack - must not move
uint64 cret; // return value from C - must not move
G* curg; // current running goroutine G* curg; // current running goroutine
Gobuf sched; Gobuf sched;
Gobuf morestack; Gobuf morestack;
@ -148,6 +149,8 @@ extern int32 debug;
*/ */
int32 gogo(Gobuf*); int32 gogo(Gobuf*);
int32 gosave(Gobuf*); int32 gosave(Gobuf*);
int32 gogoret(Gobuf*, uint64);
void retfromnewstack(void);
void setspgoto(byte*, void(*)(void), void(*)(void)); void setspgoto(byte*, void(*)(void), void(*)(void));
void FLUSH(void*); void FLUSH(void*);
void* getu(void); void* getu(void);