diff options
| author | root <root> | 2007-05-02 05:53:26 +0000 | 
|---|---|---|
| committer | root <root> | 2007-05-02 05:53:26 +0000 | 
| commit | 78f7ab4189614860e9802a1ce964c718c6d2cb9c (patch) | |
| tree | af22d1ba255e271a585d7ebd6319f224f37c2286 | |
| parent | 0cfd3b56792a5d7145f300ef14574f820fce3f06 (diff) | |
*** empty log message ***rel-4_3
| -rw-r--r-- | coro.c | 55 | ||||
| -rw-r--r-- | coro.h | 43 | 
2 files changed, 81 insertions, 17 deletions
| @@ -53,7 +53,7 @@  # include <stddef.h>  #endif -#if CORO_SJLJ || CORO_LOSER || CORO_LINUX || CORO_IRIX +#if CORO_SJLJ || CORO_LOSER || CORO_LINUX || CORO_IRIX || CORO_ASM  #include <stdlib.h> @@ -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  } @@ -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 <ucontext.h> +# include <ucontext.h>  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 <setjmp.h> +# include <setjmp.h>  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 | 
