1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
|
/* Test harness for stack-copying conext switching.
* Assumes stack grows toward lower addresses.
*/
#include "tra.h"
Label mainlabel;
static void swtch0(Ctxt*, Ctxt*);
static void swtch1(Ctxt*);
static void swtch2(Ctxt*);
/* the abort() calls keep smart compilers from optimizing the tail recursion */
static void
switchctxt(Ctxt *cur, Ctxt *nxt)
{
/*
* save the current stack position and registers
* the first time through. swtch0 won't return.
*/
if(setlabel(&cur->label)==0){
swtch0(cur, nxt);
abort();
}
}
static void
swtch0(Ctxt *cur, Ctxt *nxt)
{
uchar *lo, *hi;
int n;
/* save the stack for the current thread */
lo = (uchar*)cur->label.sp;
hi = (uchar*)mainlabel.sp;
n = hi-lo;
cur->stk = emalloc(n);
memmove(cur->stk, lo, n);
/* switch to the next thread */
swtch1(nxt);
abort();
}
static void
swtch1(Ctxt *nxt)
{
uchar buf[64]; /* take up stack space */
/* recurse until we're out of the area the new stack will occupy. */
if(nxt->label.sp < (ulong)buf)
swtch1(nxt);
/* do the copy */
swtch2(nxt);
abort();
}
static void
swtch2(Ctxt *nxt)
{
uchar *lo, *hi;
int n;
/* put the next stack in place */
lo = (uchar*)nxt->label.sp;
hi = (uchar*)mainlabel.sp;
n = hi-lo;
memmove(lo, nxt->stk, n);
free(nxt->stk);
nxt->stk = nil;
/* hop to it */
gotolabel(&nxt->label);
abort();
}
Ctxt ml, pl;
void
printthread(void *a)
{
printf("printthread runs, arg is %d\n", (int)a);
switchctxt(&pl, &ml);
}
int
main(int argc, char **argv)
{
setlabel(&mainlabel);
initctxt(&pl, printthread, (void*)12345);
printf("main runs\n");
switchctxt(&ml, &pl);
printf("main runs again\n");
return 0;
}
|