futex: Fix buggy timeout
[akaros.git] / user / pthread / futex.c
index 12d4355..300b310 100644 (file)
@@ -96,6 +96,10 @@ static inline int futex_wake(int *uaddr, int count)
        struct futex_element *e, *temp;
        struct futex_queue q = TAILQ_HEAD_INITIALIZER(q);
 
+       /* The waiter spins on us with cpu_relax_any().  That code assumes the
+        * target of the wait/spin is in vcore context, or at least has notifs
+        * disabled. */
+       uth_disable_notifs();
        mcs_pdr_lock(&__futex.lock);
        TAILQ_FOREACH_SAFE(e, &__futex.queue, link, temp) {
                if (count <= 0)
@@ -111,13 +115,13 @@ static inline int futex_wake(int *uaddr, int count)
                }
        }
        mcs_pdr_unlock(&__futex.lock);
-
        TAILQ_FOREACH_SAFE(e, &q, link, temp) {
                TAILQ_REMOVE(&q, e, link);
                uth_cond_var_signal(&e->cv);
                /* Do not touch e after marking it. */
                e->waker_using = false;
        }
+       uth_enable_notifs();
 
        return max - count;
 }
@@ -146,7 +150,7 @@ int futex(int *uaddr, int op, int val, const struct timespec *timeout,
 
        switch (op) {
        case FUTEX_WAIT:
-               return futex_wait(uaddr, val, abs_timeout);
+               return futex_wait(uaddr, val, timeout ? abs_timeout : NULL);
        case FUTEX_WAKE:
                return futex_wake(uaddr, val);
        default: