diff options
| author | Ken Thompson <ken@golang.org> | 2009-01-27 12:03:53 -0800 |
|---|---|---|
| committer | Ken Thompson <ken@golang.org> | 2009-01-27 12:03:53 -0800 |
| commit | 1e1cc4eb570aa6fec645ff4faf13431847b99db8 (patch) | |
| tree | bbbf12c48e9ab2d82b89e6a0adf15f15757e57af /src/runtime | |
| parent | 4a903e0b32be5a590880ceb7379e68790602c29d (diff) | |
| download | go-1e1cc4eb570aa6fec645ff4faf13431847b99db8.tar.xz | |
defer
R=r
OCL=23592
CL=23592
Diffstat (limited to 'src/runtime')
| -rw-r--r-- | src/runtime/proc.c | 37 | ||||
| -rw-r--r-- | src/runtime/rt0_amd64.s | 12 | ||||
| -rw-r--r-- | src/runtime/runtime.h | 23 |
3 files changed, 66 insertions, 6 deletions
diff --git a/src/runtime/proc.c b/src/runtime/proc.c index 7435830ff6..3fe08df94d 100644 --- a/src/runtime/proc.c +++ b/src/runtime/proc.c @@ -171,7 +171,7 @@ sys·newproc(int32 siz, byte* fn, byte* arg0) if((newg = gfget()) != nil){ newg->status = Gwaiting; - }else{ + } else { newg = malg(4096); newg->status = Gwaiting; newg->alllink = allg; @@ -205,6 +205,41 @@ sys·newproc(int32 siz, byte* fn, byte* arg0) } void +sys·deferproc(int32 siz, byte* fn, byte* arg0) +{ + Defer *d; + + d = mal(sizeof(*d) + siz - sizeof(d->args)); + d->fn = fn; + d->sp = (byte*)&arg0; + d->siz = siz; + mcpy(d->args, d->sp, d->siz); + + d->link = g->defer; + g->defer = d; +} + +void +sys·deferreturn(int32 arg0) +{ + // warning: jmpdefer knows the frame size + // of this routine. dont change anything + // that might change the frame size + Defer *d; + byte *sp; + + d = g->defer; + if(d == nil) + return; + sp = (byte*)&arg0; + if(d->sp != sp) + return; + mcpy(d->sp, d->args, d->siz); + g->defer = d->link; + jmpdefer(d->fn); +} + +void tracebackothers(G *me) { G *g; diff --git a/src/runtime/rt0_amd64.s b/src/runtime/rt0_amd64.s index 8588d61a4e..f8d4a381b3 100644 --- a/src/runtime/rt0_amd64.s +++ b/src/runtime/rt0_amd64.s @@ -120,7 +120,7 @@ TEXT setspgoto(SB), 7, $0 // if(*val == old){ // *val = new; // return 1; -// }else +// } else // return 0; TEXT cas(SB), 7, $0 MOVQ 8(SP), BX @@ -133,3 +133,13 @@ TEXT cas(SB), 7, $0 RET MOVL $1, AX RET + +// void jmpdefer(byte*); +// 1. pop the caller +// 2. sub 5 bytes from the callers return +// 3. jmp to the argument +TEXT jmpdefer(SB), 7, $0 + MOVQ 8(SP), AX // function + ADDQ $(8+56), SP // pop saved PC and callers frame + SUBQ $5, (SP) // reposition his return address + JMP AX // and goto function diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 5552c9e94d..78e2affc62 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -52,6 +52,7 @@ typedef struct SigTab SigTab; typedef struct MCache MCache; typedef struct Iface Iface; typedef struct Itype Itype; +typedef struct Defer Defer; /* * per cpu declaration @@ -128,6 +129,7 @@ struct G { byte* stackguard; // must not move byte* stackbase; // must not move + Defer* defer; // must not move byte* stack0; // first stack segment Gobuf sched; G* alllink; // on allg @@ -136,8 +138,8 @@ struct G int32 goid; int32 selgen; // valid sudog pointer G* schedlink; - bool readyonstop; - M* m; // for debuggers + bool readyonstop; + M* m; // for debuggers }; struct Mem { @@ -151,8 +153,8 @@ struct M G* g0; // g0 w interrupt stack - must not move uint64 morearg; // arg to morestack - must not move uint64 cret; // return value from C - must not move - uint64 procid; // for debuggers - must not move - G* gsignal; // signal-handling G - must not move + uint64 procid; // for debuggers - must not move + G* gsignal; // signal-handling G - must not move G* curg; // current running goroutine G* lastg; // last running goroutine - to emulate fifo Gobuf sched; @@ -236,6 +238,18 @@ enum }; /* + * defered subroutine calls + */ +struct Defer +{ + int32 siz; + byte* sp; + byte* fn; + Defer* link; + byte args[8]; // padded to actual size +}; + +/* * external data */ extern Alg algarray[Amax]; @@ -286,6 +300,7 @@ int32 write(int32, void*, int32); void close(int32); int32 fstat(int32, void*); bool cas(uint32*, uint32, uint32); +void jmpdefer(byte*); void exit1(int32); void ready(G*); byte* getenv(int8*); |
