From c0c2d8660f22fd5d5d834d7cdb6bb7e58a2af56c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Kijewski?= Date: Thu, 1 Jan 2015 22:52:20 +0100 Subject: [PATCH] core: missing restoreIRQ in mutex_unlock `mutex_unlock()` did not restore IRQsbefore yielding for the woken up thread. --- core/mutex.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/core/mutex.c b/core/mutex.c index 7d8dcb5135..a2ab285a89 100644 --- a/core/mutex.c +++ b/core/mutex.c @@ -84,24 +84,30 @@ static void mutex_wait(struct mutex_t *mutex) void mutex_unlock(struct mutex_t *mutex) { - DEBUG("%s: unlocking mutex. val: %u pid: %" PRIkernel_pid "\n", sched_active_thread->name, ATOMIC_VALUE(mutex->val), sched_active_pid); unsigned irqstate = disableIRQ(); + DEBUG("mutex_unlock(): val: %u pid: %" PRIkernel_pid "\n", mutex->val, sched_active_pid); - if (ATOMIC_VALUE(mutex->val) != 0) { - priority_queue_node_t *next = priority_queue_remove_head(&(mutex->queue)); - if (next) { - tcb_t *process = (tcb_t *) next->data; - DEBUG("%s: waking up waiter.\n", process->name); - sched_set_status(process, STATUS_PENDING); - - sched_switch(process->priority); - } - else { - ATOMIC_VALUE(mutex->val) = 0; /* This is safe, interrupts are disabled */ - } + if (ATOMIC_VALUE(mutex->val) == 0) { + /* the mutex was not locked */ + restoreIRQ(irqstate); + return; } + priority_queue_node_t *next = priority_queue_remove_head(&(mutex->queue)); + if (!next) { + /* the mutex was locked and no thread was waiting for it */ + ATOMIC_VALUE(mutex->val) = 0; + restoreIRQ(irqstate); + return; + } + + tcb_t *process = (tcb_t *) next->data; + DEBUG("mutex_unlock: waking up waiting thread %" PRIkernel_pid "\n", process->pid); + sched_set_status(process, STATUS_PENDING); + + uint16_t process_priority = process->priority; restoreIRQ(irqstate); + sched_switch(process_priority); } void mutex_unlock_and_sleep(struct mutex_t *mutex)