Support for context switching using pthreads
authorPhilipp Stephani <phst@google.com>
Thu, 27 Oct 2016 21:14:19 +0000 (23:14 +0200)
committerPhilipp Stephani <phst@google.com>
Thu, 27 Oct 2016 21:14:19 +0000 (23:14 +0200)
Experimental, doesn’t work yet

lib/libtask/context.c
lib/libtask/task.c
lib/libtask/taskimpl.h

index db7d25cdfee31beb98b8941c7fe7fd639e78946e..95c140cc0f63ff4ef820c4af3ed37ff3f49124b9 100644 (file)
@@ -9,7 +9,7 @@
 #define UNICODE
 #include <windows.h>
 
-#else
+#elseif ! defined LIBTASK_USE_PTHREAD
 
 #if defined(__APPLE__)
 #if defined(__i386__)
@@ -159,3 +159,29 @@ swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
   return 0;
 }
 #endif
+
+#ifdef LIBTASK_USE_PTHREAD
+#include <pthread.h>
+static bool oucp_is_valid = false;
+
+int
+swapcontext (ucontext_t *oucp, /* const */ ucontext_t *ucp)
+{
+  oucp->running = false;
+  ucp->running = true;
+  pthread_mutex_lock (&ucp->mutex);
+  pthread_cond_signal (&ucp->cond);
+  pthread_mutex_unlock (&ucp->mutex);
+  if (! oucp_is_valid)
+  {
+    pthread_mutex_init (&oucp->mutex, NULL);
+    pthread_cond_init (&oucp->cond, NULL);
+    oucp->thread = pthread_self ();
+    oucp_is_valid = true;
+  }
+  pthread_mutex_lock (&oucp->mutex);
+  while (! oucp->running)
+    pthread_cond_wait (&oucp->cond, &oucp->mutex);
+  pthread_mutex_unlock (&oucp->mutex);
+}
+#endif
index 4e271f3507127b706730a1dd5b38da4fd0975795..4d68e7ee27209bdb8e8aecc0a29d035eef294450 100644 (file)
 #include <windows.h>
 #endif
 
+#ifdef LIBTASK_USE_PTHREAD
+#include <pthread.h>
+#endif
+
 int    taskdebuglevel;
 int    taskcount;
 int    tasknswitch;
@@ -62,7 +66,7 @@ return;
                fprint(fd, "%d._: %s\n", getpid(), buf);
 }
 
-#ifndef LIBTASK_USE_FIBER
+#if ! defined LIBTASK_USE_FIBER && ! defined LIBTASK_USE_PTHREAD
 static void
 taskstart(uint y, uint x)
 {
@@ -82,6 +86,21 @@ taskstart(uint y, uint x)
 }
 #endif
 
+#ifdef LIBTASK_USE_PTHREAD
+static void *
+thread_func (void *arg)
+{
+  Task *t = arg;
+  ucontext_t *uc = &t->context.uc;
+  pthread_mutex_lock (&uc->mutex);
+  while (! uc->running)
+    pthread_cond_wait (&uc->cond, &uc->mutex);
+  pthread_mutex_unlock (&uc->mutex);
+  t->startfn (t->startarg);
+  return NULL;
+}
+#endif
+
 static int taskidgen;
 
 static Task*
@@ -107,9 +126,18 @@ taskalloc(void (*fn)(void*), void *arg, uint stack)
         t->context.uc.fiber = CreateFiber (stack, fn, arg);
         if (t->context.uc.fiber == NULL)
           abort ();
+#else
+#ifdef LIBTASK_USE_PTHREAD
+        if (pthread_mutex_init (&t->context.uc.mutex, NULL) != 0)
+          abort ();
+        if (pthread_cond_init (&t->context.uc.cond, NULL) != 0)
+          abort ();
+        if (pthread_create (&t->context.uc.thread, NULL, thread_func, t) != 0)
+          abort ();
 #else
        t->stk = (uchar*)(t+1);
        t->stksize = stack;
+#endif
 #endif
        t->id = ++taskidgen;
 #ifndef LIBTASK_USE_FIBER
@@ -121,7 +149,7 @@ taskalloc(void (*fn)(void*), void *arg, uint stack)
         init_emacs_lisp_context (t->id == 1, &t->context.ec);
 #endif
 
-#ifndef LIBTASK_USE_FIBER
+#if ! defined LIBTASK_USE_FIBER && ! defined LIBTASK_USE_PTHREAD
        /* do a reasonable initialization */
        memset(&t->context.uc, 0, sizeof t->context.uc);
        sigemptyset(&zero);
index 2b1e31cfc7b15713d422c467f33818b1a3232ea6..0d23373e3a5d68ac0ba68be466fd9c92650e7ce8 100644 (file)
 #include <config.h>
 #include "lisp.h"
 #ifdef WINDOWSNT
-#undef USE_UCONTEXT
-#define USE_UCONTEXT 0
 #define LIBTASK_USE_FIBER
+#else
+//#define LIBTASK_USE_PTHREAD
 #endif
 #endif
 
+#if defined LIBTASK_USE_FIBER || defined LIBTASK_USE_PTHREAD
+#undef USE_UCONTEXT
+#define USE_UCONTEXT 0
+#endif
+
 #include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -89,7 +94,7 @@ char *vsnprint(char*, uint, char*, va_list);
 char *vseprint(char*, char*, char*, va_list);
 char *strecpy(char*, char*, char*);
 
-#ifdef LIBTASK_USE_FIBER
+#if defined LIBTASK_USE_FIBER
 
 #undef ucontext
 #undef ucontext_t
@@ -100,6 +105,21 @@ typedef struct libtask_fiber_ucontext {
 } libtask_fiber_ucontext_t;
 extern int swapcontext(ucontext_t *, const ucontext_t *);
 
+#elif defined LIBTASK_USE_PTHREAD
+
+#include <pthread.h>
+#undef ucontext
+#undef ucontext_t
+#define ucontext libtask_pthread_ucontext
+#define ucontext_t libtask_pthread_ucontext_t
+typedef struct libtask_pthread_ucontext {
+  pthread_t thread;
+  pthread_mutex_t mutex;
+  pthread_cond_t cond;
+  bool running;
+} libtask_pthread_ucontext_t;
+extern int swapcontext(ucontext_t *, /* const */ ucontext_t *);
+
 #else
 
 #if defined(__FreeBSD__) && __FreeBSD__ < 5