From d5c98d19e5636df98de627120f819d563248dbca Mon Sep 17 00:00:00 2001 From: Pieter Willemsen Date: Fri, 25 Jan 2019 18:53:54 +0100 Subject: [PATCH] xtimer: check in timeout callback if thread blocked on mutex Prevent a possible race condition when _mutex_timeout fires just after the mutex was locked but before the xtimer was removed The flow int xtimer_mutex_lock_timeout(mutex_t *mutex, uint64_t timeout) { ... mutex_lock(mutex); <- mutex locked -> <- _mutex_timeout fires and tries to remove thread from mutex queue -> xtimer_remove(&t); ... } --- sys/xtimer/xtimer.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/sys/xtimer/xtimer.c b/sys/xtimer/xtimer.c index ff6dccf0f492..17cb8dd30c09 100644 --- a/sys/xtimer/xtimer.c +++ b/sys/xtimer/xtimer.c @@ -237,14 +237,16 @@ static void _mutex_timeout(void *arg) { mutex_thread_t *mt = (mutex_thread_t *)arg; - mt->timeout = 1; - list_node_t *node = list_remove(&mt->mutex->queue, - (list_node_t *)&mt->thread->rq_entry); - if ((node != NULL) && (mt->mutex->queue.next == NULL)) { - mt->mutex->queue.next = MUTEX_LOCKED; + if (mt->mutex->queue.next != MUTEX_LOCKED) { + mt->timeout = 1; + list_node_t *node = list_remove(&mt->mutex->queue, + (list_node_t *)&mt->thread->rq_entry); + if ((node != NULL) && (mt->mutex->queue.next == NULL)) { + mt->mutex->queue.next = MUTEX_LOCKED; + } + sched_set_status(mt->thread, STATUS_PENDING); + thread_yield_higher(); } - sched_set_status(mt->thread, STATUS_PENDING); - thread_yield_higher(); } int xtimer_mutex_lock_timeout(mutex_t *mutex, uint64_t timeout)