Fix b51b15e: re-disable dispatcher in thread_mutex_lock* and thread_sem_wait().
[barrelfish] / lib / barrelfish / thread_sync.c
index 3e5e850..2478fad 100644 (file)
@@ -184,15 +184,17 @@ void thread_mutex_lock(struct thread_mutex *mutex)
                 (uintptr_t)mutex);
 
     acquire_spinlock(&mutex->lock);
-    if (mutex->locked > 0) {
+    while (mutex->locked > 0) {
         thread_block_and_release_spinlock_disabled(handle, &mutex->queue,
                                                    &mutex->lock);
-    } else {
-        mutex->locked = 1;
-        mutex->holder = disp_gen->current;
-        release_spinlock(&mutex->lock);
-        disp_enable(handle);
+        handle = disp_disable();
+        disp_gen = get_dispatcher_generic(handle);
+        acquire_spinlock(&mutex->lock);
     }
+    mutex->locked = 1;
+    mutex->holder = disp_gen->current;
+    release_spinlock(&mutex->lock);
+    disp_enable(handle);
 
     trace_event(TRACE_SUBSYS_THREADS, TRACE_EVENT_THREADS_MUTEX_LOCK_LEAVE,
                 (uintptr_t)mutex);
@@ -214,16 +216,18 @@ void thread_mutex_lock_nested(struct thread_mutex *mutex)
                 (uintptr_t)mutex);
 
     acquire_spinlock(&mutex->lock);
-    if (mutex->locked > 0
+    while (mutex->locked > 0
         && mutex->holder != disp_gen->current) {
         thread_block_and_release_spinlock_disabled(handle, &mutex->queue,
                                                    &mutex->lock);
-    } else {
-        mutex->locked++;
-        mutex->holder = disp_gen->current;
-        release_spinlock(&mutex->lock);
-        disp_enable(handle);
+        handle = disp_disable();
+        disp_gen = get_dispatcher_generic(handle);
+        acquire_spinlock(&mutex->lock);
     }
+    mutex->locked++;
+    mutex->holder = disp_gen->current;
+    release_spinlock(&mutex->lock);
+    disp_enable(handle);
 
     trace_event(TRACE_SUBSYS_THREADS, TRACE_EVENT_THREADS_MUTEX_LOCK_NESTED_LEAVE,
                 (uintptr_t)mutex);
@@ -353,16 +357,18 @@ void thread_sem_wait(struct thread_sem *sem)
     dispatcher_handle_t disp = disp_disable();
     acquire_spinlock(&sem->lock);
 
-    if(sem->value < 1) {
+    while (sem->value < 1) {
         // Not possible to decrement -- wait!
         thread_block_and_release_spinlock_disabled(disp, &sem->queue, &sem->lock);
-    } else {
-        // Decrement possible
-        sem->value--;
-        release_spinlock(&sem->lock);
-        disp_enable(disp);
+        disp = disp_disable();
+        acquire_spinlock(&sem->lock);
     }
 
+    // Decrement possible
+    sem->value--;
+    release_spinlock(&sem->lock);
+    disp_enable(disp);
+
     trace_event(TRACE_SUBSYS_THREADS, TRACE_EVENT_THREADS_SEM_WAIT_LEAVE,
                 (uintptr_t)sem);
 }