From 78f7ab4189614860e9802a1ce964c718c6d2cb9c Mon Sep 17 00:00:00 2001 From: root Date: Wed, 2 May 2007 05:53:26 +0000 Subject: *** empty log message *** --- coro.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++---- coro.h | 43 ++++++++++++++++++++++++++++++------------- 2 files changed, 81 insertions(+), 17 deletions(-) diff --git a/coro.c b/coro.c index c95de5e..ebc9654 100644 --- a/coro.c +++ b/coro.c @@ -53,7 +53,7 @@ # include #endif -#if CORO_SJLJ || CORO_LOSER || CORO_LINUX || CORO_IRIX +#if CORO_SJLJ || CORO_LOSER || CORO_LINUX || CORO_IRIX || CORO_ASM #include @@ -113,6 +113,46 @@ trampoline (int sig) #endif +#if CORO_ASM +void __attribute__((__noinline__, __fastcall__)) +coro_transfer (struct coro_context *prev, struct coro_context *next) +{ + asm volatile ( +#if __amd64 +# define NUM_CLOBBERED 5 + "push %%rbx\n\t" + "push %%r12\n\t" + "push %%r13\n\t" + "push %%r14\n\t" + "push %%r15\n\t" + "mov %%rsp, %0\n\t" + "mov %1, %%rsp\n\t" + "pop %%r15\n\t" + "pop %%r14\n\t" + "pop %%r13\n\t" + "pop %%r12\n\t" + "pop %%rbx\n\t" +#elif __i386 +# define NUM_CLOBBERED 4 + "push %%ebx\n\t" + "push %%esi\n\t" + "push %%edi\n\t" + "push %%ebp\n\t" + "mov %%esp, %0\n\t" + "mov %1, %%esp\n\t" + "pop %%ebp\n\t" + "pop %%edi\n\t" + "pop %%esi\n\t" + "pop %%ebx\n\t" +#else +# error unsupported architecture +#endif + : "=m" (prev->sp) + : "m" (next->sp) + ); +} +#endif + /* initialize a machine state */ void coro_create (coro_context *ctx, coro_func coro, void *arg, @@ -129,7 +169,7 @@ void coro_create (coro_context *ctx, makecontext (&(ctx->uc), (void (*)()) coro, 1, arg); -#elif CORO_SJLJ || CORO_LOSER || CORO_LINUX || CORO_IRIX +#elif CORO_SJLJ || CORO_LOSER || CORO_LINUX || CORO_IRIX || CORO_ASM # if CORO_SJLJ stack_t ostk, nstk; @@ -230,7 +270,7 @@ void coro_create (coro_context *ctx, ctx->env[0].__jmpbuf[JB_PC] = (long)coro_init; ctx->env[0].__jmpbuf[JB_RSP] = (long)STACK_ADJUST_PTR (sptr, ssize); #else -#error "linux libc or architecture not supported" +# error "linux libc or architecture not supported" #endif # elif CORO_IRIX @@ -239,12 +279,19 @@ void coro_create (coro_context *ctx, ctx->env[JB_PC] = (__uint64_t)coro_init; ctx->env[JB_SP] = (__uint64_t)STACK_ADJUST_PTR (sptr, ssize); +# elif CORO_ASM + + ctx->sp = (volatile void **)(ssize + (char *)sptr); + *--ctx->sp = (void *)coro_init; + *--ctx->sp = (void *)coro_init; // this is needed when the prologue saves ebp + ctx->sp -= NUM_CLOBBERED; + # endif coro_transfer ((coro_context *)create_coro, (coro_context *)new_coro); #else -error unsupported architecture +# error unsupported architecture #endif } diff --git a/coro.h b/coro.h index 993dab6..00ed664 100644 --- a/coro.h +++ b/coro.h @@ -41,6 +41,8 @@ * 2006-11-26 Use _setjmp instead of setjmp on GNU/Linux. * 2007-04-27 Set unwind frame info if gcc 3+ and ELF is detected. * Use _setjmp instead of setjmp on _XOPEN_SOURCE >= 600. + * 2007-05-02 Add assembly versions for x86 and amd64 (to avoid reliance + * on SIGUSR2 and sigaltstack in Crossfire). */ #ifndef CORO_H @@ -91,6 +93,11 @@ * * SGI's version of Microsoft's NT ;) * + * -DCORO_ASM + * + * Handcoded assembly, known to work only on a few architectures/ABI: + * ELF Linux x86 && amd64 when gcc is used and optimisation is turned on. + * * If you define neither of these symbols, coro.h will try to autodetect * the model. This currently works for CORO_LOSER only. For the other * alternatives you should check (e.g. using autoconf) and define the @@ -138,10 +145,11 @@ void coro_transfer(coro_context *prev, coro_context *next); #if !defined(CORO_LOSER) && !defined(CORO_UCONTEXT) \ && !defined(CORO_SJLJ) && !defined(CORO_LINUX) \ - && !defined(CORO_IRIX) + && !defined(CORO_IRIX) && !defined(CORO_ASM) # if defined(WINDOWS) # define CORO_LOSER 1 /* you don't win with windoze */ -# elif defined(__linux) && defined(__x86) +# elif defined(__linux) && (defined(__x86) || defined (__amd64)) +# define CORO_ASM 1 # elif defined(HAVE_UCONTEXT_H) # define CORO_UCONTEXT 1 # elif defined(HAVE_SETJMP_H) && defined(HAVE_SIGALTSTACK) @@ -155,31 +163,40 @@ error unknown or unsupported architecture #if CORO_UCONTEXT -#include +# include struct coro_context { ucontext_t uc; }; -#define coro_transfer(p,n) swapcontext (&((p)->uc), &((n)->uc)) +# define coro_transfer(p,n) swapcontext (&((p)->uc), &((n)->uc)) #elif CORO_SJLJ || CORO_LOSER || CORO_LINUX || CORO_IRIX -#if defined(CORO_LINUX) && !defined(_GNU_SOURCE) -# define _GNU_SOURCE /* for linux libc */ -#endif +# if defined(CORO_LINUX) && !defined(_GNU_SOURCE) +# define _GNU_SOURCE /* for linux libc */ +# endif -#include +# include struct coro_context { jmp_buf env; }; -#if CORO_LINUX || (_XOPEN_SOURCE >= 600) -# define coro_transfer(p,n) do { if (!_setjmp ((p)->env)) _longjmp ((n)->env, 1); } while (0) -#else -# define coro_transfer(p,n) do { if (!setjmp ((p)->env)) longjmp ((n)->env, 1); } while (0) -#endif +# if CORO_LINUX || (_XOPEN_SOURCE >= 600) +# define coro_transfer(p,n) do { if (!_setjmp ((p)->env)) _longjmp ((n)->env, 1); } while (0) +# else +# define coro_transfer(p,n) do { if (!setjmp ((p)->env)) longjmp ((n)->env, 1); } while (0) +# endif + +#elif CORO_ASM + +struct coro_context { + volatile void **sp; +}; + +void __attribute__ ((__noinline__, __fastcall__)) + coro_transfer(coro_context *prev, coro_context *next); #endif -- cgit v1.2.3