MCS-PDR locks take a *qnode
[akaros.git] / user / pthread / futex.c
index 381a9ef..d8319d4 100644 (file)
@@ -1,5 +1,5 @@
 #include <ros/common.h>
-#include <ros/futex.h>
+#include <futex.h>
 #include <sys/queue.h>
 #include <pthread.h>
 #include <assert.h>
@@ -12,6 +12,7 @@ struct futex_element {
   TAILQ_ENTRY(futex_element) link;
   pthread_t pthread;
   int *uaddr;
+  struct mcs_pdr_qnode *mcs_qnode;
 };
 TAILQ_HEAD(futex_queue, futex_element);
 
@@ -34,22 +35,25 @@ static inline void futex_init()
 static void __futex_block(struct uthread *uthread, void *arg) {
   struct futex_element *e = (struct futex_element*)arg;
   e->pthread = (pthread_t)uthread;
+       __pthread_generic_yield(e->pthread);
   e->pthread->state = PTH_BLK_MUTEX;
   TAILQ_INSERT_TAIL(&__futex.queue, e, link);
-  mcs_pdr_unlock(&__futex.lock);
+  mcs_pdr_unlock(&__futex.lock, e->mcs_qnode);
 }
 
 static inline int futex_wait(int *uaddr, int val)
 {
-  mcs_pdr_lock(&__futex.lock);
+  struct mcs_pdr_qnode qnode;
+  mcs_pdr_lock(&__futex.lock, &qnode);
   if(*uaddr == val) {
     // We unlock in the body of __futex_block
     struct futex_element *e = kmem_cache_alloc(__futex.element_cache, 0); 
     e->uaddr = uaddr;
+    e->mcs_qnode = &qnode;
     uthread_yield(TRUE, __futex_block, e);
   }
   else {
-    mcs_pdr_unlock(&__futex.lock);
+    mcs_pdr_unlock(&__futex.lock, &qnode);
   }
   return 0;
 }
@@ -57,7 +61,8 @@ static inline int futex_wait(int *uaddr, int val)
 static inline int futex_wake(int *uaddr, int count)
 {
   struct futex_element *e,*n = NULL;
-  mcs_pdr_lock(&__futex.lock);
+  struct mcs_pdr_qnode qnode;
+  mcs_pdr_lock(&__futex.lock, &qnode);
   e = TAILQ_FIRST(&__futex.queue);
   while(e != NULL) {
     if(count > 0) {
@@ -72,7 +77,7 @@ static inline int futex_wake(int *uaddr, int count)
     }
     else break;
   }
-  mcs_pdr_unlock(&__futex.lock);
+  mcs_pdr_unlock(&__futex.lock, &qnode);
   return 0;
 }
 
@@ -83,7 +88,7 @@ int futex(int *uaddr, int op, int val, const struct timespec *timeout,
   assert(uaddr2 == NULL);
   assert(val3 == 0);
 
-  run_once_safe(futex_init());
+  run_once(futex_init());
   switch(op) {
     case FUTEX_WAIT:
       return futex_wait(uaddr, val);