117 lines
2.5 KiB
C
117 lines
2.5 KiB
C
/* Copyright (c) 2005-2006 Russ Cox, MIT; see COPYRIGHT */
|
|
|
|
#include "taskimpl.h"
|
|
|
|
#if defined(__APPLE__)
|
|
#if defined(__i386__)
|
|
#define NEEDX86MAKECONTEXT
|
|
#define NEEDSWAPCONTEXT
|
|
#elif defined(__x86_64__)
|
|
#define NEEDAMD64MAKECONTEXT
|
|
#define NEEDSWAPCONTEXT
|
|
#else
|
|
#define NEEDPOWERMAKECONTEXT
|
|
#define NEEDSWAPCONTEXT
|
|
#endif
|
|
#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 NEEDAMD64MAKECONTEXT
|
|
void
|
|
makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
|
|
{
|
|
long *sp;
|
|
va_list va;
|
|
|
|
memset(&ucp->uc_mcontext, 0, sizeof ucp->uc_mcontext);
|
|
if(argc != 2)
|
|
__builtin_trap();
|
|
va_start(va, argc);
|
|
ucp->uc_mcontext.mc_rdi = va_arg(va, int);
|
|
ucp->uc_mcontext.mc_rsi = va_arg(va, int);
|
|
va_end(va);
|
|
sp = (long*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/sizeof(long);
|
|
sp -= argc;
|
|
sp = (void*)((uintptr_t)sp - (uintptr_t)sp%16); /* 16-align for OS X */
|
|
*--sp = 0; /* return address */
|
|
ucp->uc_mcontext.mc_rip = (long)func;
|
|
ucp->uc_mcontext.mc_rsp = (long)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
|
|
|