--- libcoro/coro.h 2006/11/25 00:27:00 1.16 +++ libcoro/coro.h 2007/05/02 05:53:26 1.22 @@ -38,7 +38,11 @@ /* * 2006-10-26 Include stddef.h on OS X to work around one of its bugs. * Reported by Michael_G_Schwern. - * 2006-11-25 Use _setjmp instead of setjmp on GNU/Linux. + * 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 @@ -89,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 @@ -101,9 +110,9 @@ typedef void (*coro_func)(void *); /* - * A coroutine state is saved in the following structure. Treat it as a + * A coroutine state is saved in the following structure. Treat it as an * opaque type. errno and sigmask might be saved, but don't rely on it, - * implement your own switching primitive if you need it. + * implement your own switching primitive if you need that. */ typedef struct coro_context coro_context; @@ -115,9 +124,11 @@ * Allocating/deallocating the stack is your own responsibility, so there is * no coro_destroy function. */ -void coro_create (coro_context *ctx, - coro_func coro, void *arg, - void *sptr, long ssize); +void coro_create (coro_context *ctx, /* an uninitialised coro_context */ + coro_func coro, /* the coroutine code to be executed */ + void *arg, /* a single pointer passed to the coro */ + void *sptr, /* start of stack area */ + long ssize); /* size of stack area */ /* * The following prototype defines the coroutine switching function. It is @@ -134,10 +145,11 @@ #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) @@ -151,27 +163,40 @@ #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; }; -#define coro_transfer(p,n) do { if (!setjmp ((p)->env)) longjmp ((n)->env, 1); } while(0) +# 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