/* * svr4.c -- context switch code for Unix System V, release 4. * * Some Makefile changes are needed to use this code. * * This code has been successfully tested under Solaris 2.1 and 2.2; * it is known not to work with MPD_PARALLEL > 1 but this has not been * investigated. */ #include #include #include typedef struct { /* layout of beginning of MPD context area */ ucontext_t ucontext; /* SVR4 context structure */ int arg1, arg2, arg3, arg4; /* initial arguments to pass */ } stk_hdr; static void startup(); void mpd_stk_underflow(); /* * mpd_build_context (func, buf, bufsize, arg1, arg2, arg3, arg4) * * Build a context that will call func(arg1,arg2,arg3,arg4) when activated * and will catch an underflow error if func returns. We use an intermediary * in order to catch that return. */ void mpd_build_context (func, buf, bufsize, arg1, arg2, arg3, arg4) void (*func)(); char *buf; int bufsize, arg1, arg2, arg3, arg4; { stk_hdr *stk = (stk_hdr *) buf; /* put header at front of buf */ bufsize -= sizeof (stk_hdr); /* adjust size accordingly */ getcontext (&stk->ucontext); /* initialize context */ #ifdef sparc /* Solaris 2.1 makecontext() neglects to adjust for down-growing stack */ /* but also seems to need a little room above the top */ stk->ucontext.uc_stack.ss_sp = buf + bufsize - 128; stk->ucontext.uc_stack.ss_size = bufsize - sizeof (ucontext_t) - 128; #else stk->ucontext.uc_stack.ss_sp = buf + sizeof (ucontext_t); stk->ucontext.uc_stack.ss_size = bufsize - sizeof (ucontext_t); #endif /* * This would be simpler if makecontext() could pass five args to the * called function. Under Solaris 2.1 there's a bug and only four work, * so we have to store the args in the buffer area. */ stk->arg1 = arg1; stk->arg2 = arg2; stk->arg3 = arg3; stk->arg4 = arg4; makecontext (&stk->ucontext, startup, 2, (int) func, (int) stk); } /* * startup (func, stk) -- intermediary for startup and underflow detection. */ static void startup (func, stk) void (*func)(); stk_hdr *stk; { (*func) (stk->arg1, stk->arg2, stk->arg3, stk->arg4); mpd_stk_underflow(); } /* * mpd_chg_context (newctx, oldctx) -- change contexts. */ void mpd_chg_context (new, old) char *new, *old; { if (old) swapcontext (&((stk_hdr*) old)->ucontext, &((stk_hdr*) new)->ucontext); else setcontext (&((stk_hdr*) new)->ucontext); } /* * mpd_check_stk (stk) -- check for stack overflow. * * We have no idea of how to do that, so we do nothing. */ void mpd_check_stk(stk) char *stk; { /* nothing */ }