#include <u.h>
#include <libc.h>
#include "linux.h"
typedef struct Jmparg Jmparg;
struct Jmparg
{
int (*fn)(void *);
void *arg;
int ret;
jmp_buf jmp;
};
static jmp_buf stkjmp;
void
set9stack(void *stack)
{
Jmparg *x;
if(!(x = (Jmparg*)setjmp(stkjmp))){
if(stack)
stkjmp[JMPBUFSP] = (ulong)stack - 16;
return;
}
DPRINT("now in 9stack from x=0x%p pc=0x%lux sp=0x%lux...\n",
x, x->jmp[JMPBUFPC], x->jmp[JMPBUFSP]);
x->ret = x->fn(x->arg);
DPRINT("jumping back from 9stack to x=0x%p pc=0x%lux sp=0x%lux...\n",
x, x->jmp[JMPBUFPC], x->jmp[JMPBUFSP]);
longjmp(x->jmp, (int)x);
abort();
}
int
do9stack(int (*fn)(void *), void *arg)
{
Jmparg a;
a.fn = fn;
a.arg = arg;
if(!setjmp(a.jmp)){
longjmp(stkjmp, (int)&a);
abort();
}
return a.ret;
}
typedef struct Args Args;
struct Args
{
int flags;
int stacksize;
void (*fn)(void *);
void *arg;
};
static int
_freeandexitxproc(void *aux)
{
free(aux);
exits(0);
return 0;
}
static void
_exitxproc(void)
{
ulong *p;
ulong *top, *bot;
p = (ulong*)&p;
p += 2;
if(memcmp(p, "STACKBOT", 8) != 0)
abort();
p += 2;
bot = p;
top = (ulong*)*bot;
if(memcmp(&top[1], "STACKTOP", 8) != 0)
abort();
if(*bot != (ulong)top)
abort();
if(*top != (ulong)bot)
abort();
do9stack(_freeandexitxproc, top);
}
static int
_createxproc(void *aux)
{
int pid;
Args a, *x;
x = aux;
/*
* need to have a deep copy on stack because x will
* go away if parent returns after rfork.
*/
memcpy(&a, x, sizeof(a));
pid = rfork(a.flags);
if(pid < 0)
return pid;
if(pid == 0){
jmp_buf jmp;
int n;
ulong *top, *bot, *p;
n = a.stacksize + (4 + 8) * 2;
top = malloc(n);
bot = (ulong*)((uchar*)top + n - 4);
*top = (ulong)bot;
*bot = (ulong)top;
memcpy(&top[1], "STACKTOP", 8);
p = bot;
p -= 2;
memcpy(p, "STACKBOT", 8);
*--p = (ulong)a.arg;
*--p = (ulong)_exitxproc;
*--p = 0;
jmp[JMPBUFSP] = (ulong)p;
jmp[JMPBUFPC] = (ulong)a.fn;
longjmp(jmp, 1);
abort();
}
return pid;
}
int
createxproc(void (*fn)(void *), void *arg, int flags, int stacksize)
{
Args a;
a.fn = fn;
a.arg = arg;
a.flags = flags;
a.stacksize = stacksize;
return do9stack(_createxproc, &a);
}
|