futex: Make futexes independent of pthreads
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 7 Apr 2017 17:59:51 +0000 (13:59 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 3 May 2017 16:13:02 +0000 (12:13 -0400)
Unlike POSIX semaphores, the futex code can't be implemented 1:1 with
semaphores or CVs.  It manages its own wakeup conditions and whatnot.  We
probably could reimplement the whole thing with other uthread primitives.
For now, we just want to make it not depend on pthread code.

Similar to POSIX semaphores, futex.h is a common header for the Linux/POSIX
world, and is an API people will want to use regardless of their 2LS.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
user/pthread/futex.c

index b2436e9..916e6fe 100644 (file)
@@ -1,7 +1,7 @@
 #include <parlib/common.h>
 #include <futex.h>
 #include <sys/queue.h>
-#include <pthread.h>
+#include <parlib/uthread.h>
 #include <parlib/parlib.h>
 #include <parlib/assert.h>
 #include <stdio.h>
@@ -16,7 +16,7 @@ static void *timer_thread(void *arg);
 
 struct futex_element {
   TAILQ_ENTRY(futex_element) link;
-  pthread_t pthread;
+  struct uthread *uthread;
   int *uaddr;
   uint64_t us_timeout;
   struct alarm_waiter awaiter;
@@ -54,7 +54,7 @@ static void __futex_timeout(struct alarm_waiter *awaiter) {
   if (__e != NULL) {
     e->timedout = true;
     //printf("timeout: %p\n", e->uaddr);
-    uthread_runnable((struct uthread*)e->pthread);
+    uthread_runnable(e->uthread);
   }
   // Set this as the very last thing we do whether we successfully woke the
   // thread blocked on the futex or not.  Either we set this or wake() sets
@@ -65,11 +65,10 @@ static void __futex_timeout(struct alarm_waiter *awaiter) {
 }
 
 static void __futex_block(struct uthread *uthread, void *arg) {
-  pthread_t pthread = (pthread_t)uthread;
   struct futex_element *e = (struct futex_element*)arg;
 
   // Set the remaining properties of the futex element
-  e->pthread = pthread;
+  e->uthread = uthread;
   e->timedout = false;
 
   // Insert the futex element into the queue
@@ -85,8 +84,7 @@ static void __futex_block(struct uthread *uthread, void *arg) {
   }
 
   // Notify the scheduler of the type of yield we did
-  __pthread_generic_yield(pthread);
-  pthread->state = PTH_BLK_MUTEX;
+  uthread_has_blocked(uthread, NULL, UTH_EXT_BLK_MUTEX);
 
   // Unlock the pdr_lock 
   mcs_pdr_unlock(&__futex.lock);
@@ -178,7 +176,7 @@ static inline int futex_wake(int *uaddr, int count)
       }
     }
     //printf("wake: %p\n", uaddr);
-    uthread_runnable((struct uthread*)e->pthread);
+    uthread_runnable(e->uthread);
     e = n;
   }
   return max-count;