From 150bbf2e0ed5fff8aff5e073aff21db851e3d6a9 Mon Sep 17 00:00:00 2001 From: Philipp Stephani Date: Tue, 25 Oct 2016 23:40:09 +0200 Subject: [PATCH] Support for Windows fibers --- lib/libtask/context.c | 20 ++++++++++++++++++++ lib/libtask/task.c | 30 ++++++++++++++++++++++++++++++ lib/libtask/taskimpl.h | 24 ++++++++++++++++++++++++ 3 files changed, 74 insertions(+) diff --git a/lib/libtask/context.c b/lib/libtask/context.c index 9571996fd3a..db7d25cdfee 100644 --- a/lib/libtask/context.c +++ b/lib/libtask/context.c @@ -2,6 +2,15 @@ #include "taskimpl.h" +#ifdef LIBTASK_USE_FIBER + +#define STRICT +#define NOMINMAX +#define UNICODE +#include + +#else + #if defined(__APPLE__) #if defined(__i386__) #define NEEDX86MAKECONTEXT @@ -35,6 +44,8 @@ #define NEEDMIPSMAKECONTEXT #endif +#endif + #ifdef NEEDPOWERMAKECONTEXT void makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) @@ -139,3 +150,12 @@ swapcontext(ucontext_t *oucp, const ucontext_t *ucp) return 0; } #endif + +#ifdef LIBTASK_USE_FIBER +int +swapcontext (ucontext_t *oucp, const ucontext_t *ucp) +{ + SwitchToFiber (ucp->fiber); + return 0; +} +#endif diff --git a/lib/libtask/task.c b/lib/libtask/task.c index ebb868183b3..4e271f35071 100644 --- a/lib/libtask/task.c +++ b/lib/libtask/task.c @@ -4,6 +4,13 @@ #include #include +#ifdef LIBTASK_USE_FIBER +#define STRICT +#define NOMINMAX +#define UNICODE +#include +#endif + int taskdebuglevel; int taskcount; int tasknswitch; @@ -55,6 +62,7 @@ return; fprint(fd, "%d._: %s\n", getpid(), buf); } +#ifndef LIBTASK_USE_FIBER static void taskstart(uint y, uint x) { @@ -72,6 +80,7 @@ taskstart(uint y, uint x) taskexit(0); //print("not reacehd\n"); } +#endif static int taskidgen; @@ -83,23 +92,36 @@ taskalloc(void (*fn)(void*), void *arg, uint stack) uint x, y; ulong z; +#ifdef LIBTASK_USE_FIBER + t = malloc (sizeof *t); +#else /* allocate the task and stack together */ t = malloc(sizeof *t+stack); +#endif if(t == nil){ fprint(2, "taskalloc malloc: %r\n"); abort(); } memset(t, 0, sizeof *t); +#ifdef LIBTASK_USE_FIBER + t->context.uc.fiber = CreateFiber (stack, fn, arg); + if (t->context.uc.fiber == NULL) + abort (); +#else t->stk = (uchar*)(t+1); t->stksize = stack; +#endif t->id = ++taskidgen; +#ifndef LIBTASK_USE_FIBER t->startfn = fn; t->startarg = arg; +#endif #ifdef EMACS init_emacs_lisp_context (t->id == 1, &t->context.ec); #endif +#ifndef LIBTASK_USE_FIBER /* do a reasonable initialization */ memset(&t->context.uc, 0, sizeof t->context.uc); sigemptyset(&zero); @@ -133,6 +155,7 @@ taskalloc(void (*fn)(void*), void *arg, uint stack) z >>= 16; /* hide undefined 32-bit shift from 32-bit compilers */ x = z>>16; makecontext(&t->context.uc, (void(*)())taskstart, 2, y, x); +#endif return t; } @@ -308,6 +331,7 @@ taskgetstate(void) void needstack(int n) { +#ifndef LIBTASK_USE_FIBER Task *t; t = taskrunning; @@ -317,6 +341,7 @@ needstack(int n) fprint(2, "task stack overflow: &t=%p tstk=%p n=%d\n", &t, t->stk, 256+n); abort(); } +#endif } static void @@ -374,6 +399,11 @@ main(int argc, char **argv) taskargc = argc; taskargv = argv; +#ifdef LIBTASK_USE_FIBER + if (ConvertThreadToFiber (NULL) == NULL) + return 2; +#endif + if(mainstacksize == 0) mainstacksize = 256*1024; #ifdef EMACS diff --git a/lib/libtask/taskimpl.h b/lib/libtask/taskimpl.h index 03a26c29fb0..2b1dd8f9f5e 100644 --- a/lib/libtask/taskimpl.h +++ b/lib/libtask/taskimpl.h @@ -27,6 +27,11 @@ #ifdef EMACS #include #include "lisp.h" +#ifdef WINDOWSNT +#undef USE_UCONTEXT +#define USE_UCONTEXT 0 +#define LIBTASK_USE_FIBER +#endif #endif #include @@ -84,6 +89,19 @@ char *vsnprint(char*, uint, char*, va_list); char *vseprint(char*, char*, char*, va_list); char *strecpy(char*, char*, char*); +#ifdef LIBTASK_USE_FIBER + +#undef ucontext +#undef ucontext_t +#define ucontext libtask_fiber_ucontext +#define ucontext_t libtask_fiber_ucontext_t +typedef struct libtask_fiber_ucontext { + void *fiber; +} libtask_fiber_ucontext_t; +extern int swapcontext(ucontext_t *, const ucontext_t *); + +#else + #if defined(__FreeBSD__) && __FreeBSD__ < 5 extern int getmcontext(mcontext_t*); extern void setmcontext(const mcontext_t*); @@ -143,6 +161,8 @@ void setmcontext(const mcontext_t*); #define getcontext(u) getmcontext(&(u)->uc_mcontext) #endif +#endif + typedef struct Context Context; enum @@ -169,14 +189,18 @@ struct Task Context context; uvlong alarmtime; uint id; +#ifndef LIBTASK_USE_FIBER uchar *stk; uint stksize; +#endif int exiting; int alltaskslot; int system; int ready; +#ifndef LIBTASK_USE_FIBER void (*startfn)(void*); void *startarg; +#endif void *udata; }; -- 2.39.5