libtask/context.c

91 lines
1.9 KiB
C

/* Copyright (c) 2005-2006 Russ Cox, MIT; see COPYRIGHT */
#include "taskimpl.h"
#if defined(__APPLE__) && defined(__i386__)
#define NEEDX86MAKECONTEXT
#define NEEDSWAPCONTEXT
#endif
#if defined(__APPLE__) && !defined(__i386__)
#define NEEDPOWERMAKECONTEXT
#define NEEDSWAPCONTEXT
#endif
#if defined(__FreeBSD__) && defined(__i386__) && __FreeBSD__ < 5
#define NEEDX86MAKECONTEXT
#define NEEDSWAPCONTEXT
#endif
#if defined(__OpenBSD__) && defined(__i386__)
#define NEEDX86MAKECONTEXT
#define NEEDSWAPCONTEXT
#endif
#if defined(__linux__) && defined(__arm__)
#define NEEDSWAPCONTEXT
#define NEEDARMMAKECONTEXT
#endif
#ifdef NEEDPOWERMAKECONTEXT
void
makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
{
ulong *sp, *tos;
va_list arg;
tos = (ulong*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/sizeof(ulong);
sp = tos - 16;
ucp->mc.pc = (long)func;
ucp->mc.sp = (long)sp;
va_start(arg, argc);
ucp->mc.r3 = va_arg(arg, long);
va_end(arg);
}
#endif
#ifdef NEEDX86MAKECONTEXT
void
makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
{
int *sp;
sp = (int*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/4;
sp -= argc;
sp = (void*)((uintptr_t)sp - (uintptr_t)sp%16); /* 16-align for OS X */
memmove(sp, &argc+1, argc*sizeof(int));
*--sp = 0; /* return address */
ucp->uc_mcontext.mc_eip = (long)func;
ucp->uc_mcontext.mc_esp = (int)sp;
}
#endif
#ifdef NEEDARMMAKECONTEXT
void
makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...)
{
int i, *sp;
va_list arg;
sp = (int*)uc->uc_stack.ss_sp+uc->uc_stack.ss_size/4;
va_start(arg, argc);
for(i=0; i<4 && i<argc; i++)
uc->uc_mcontext.gregs[i] = va_arg(arg, uint);
va_end(arg);
uc->uc_mcontext.gregs[13] = (uint)sp;
uc->uc_mcontext.gregs[14] = (uint)fn;
}
#endif
#ifdef NEEDSWAPCONTEXT
int
swapcontext(ucontext_t *oucp, const ucontext_t *ucp)
{
if(getcontext(oucp) == 0)
setcontext(ucp);
return 0;
}
#endif