From f3b13cf90cb085e272abacf88d0f669e2d2d1af6 Mon Sep 17 00:00:00 2001 From: Pieter Willemsen Date: Fri, 25 Jan 2019 18:53:54 +0100 Subject: [PATCH 1/2] 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 */ /* DEBUG: simulate callback call between lock and remove */ xtimer_spin(xtimer_ticks_from_usec(timeout*2)); xtimer_remove(&t); ... } --- sys/xtimer/xtimer.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/sys/xtimer/xtimer.c b/sys/xtimer/xtimer.c index e238707aa6..68ba2d0eeb 100644 --- a/sys/xtimer/xtimer.c +++ b/sys/xtimer/xtimer.c @@ -250,20 +250,23 @@ 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 (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 thread was removed from the list */ - if (node != NULL) { - if (mt->mutex->queue.next == NULL) { - mt->mutex->queue.next = MUTEX_LOCKED; + /* if thread was removed from the list */ + if (node != NULL) { + if (mt->mutex->queue.next == NULL) { + mt->mutex->queue.next = MUTEX_LOCKED; + } + sched_set_status(mt->thread, STATUS_PENDING); + irq_restore(irqstate); + sched_switch(mt->thread->priority); + return; } - sched_set_status(mt->thread, STATUS_PENDING); - irq_restore(irqstate); - sched_switch(mt->thread->priority); - return; } + irq_restore(irqstate); } From 7cd3e8b73e39dbd89a92293330c1cbbccfaa4aad Mon Sep 17 00:00:00 2001 From: JulianHolzwarth Date: Fri, 31 May 2019 17:43:18 +0200 Subject: [PATCH 2/2] xtimer/xtimer.c:_mutex_timeout() improved no longer into the "if" when the mutex is free --- sys/xtimer/xtimer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/xtimer/xtimer.c b/sys/xtimer/xtimer.c index 68ba2d0eeb..8f1e441bf8 100644 --- a/sys/xtimer/xtimer.c +++ b/sys/xtimer/xtimer.c @@ -250,7 +250,8 @@ static void _mutex_timeout(void *arg) mutex_thread_t *mt = (mutex_thread_t *)arg; - if (mt->mutex->queue.next != MUTEX_LOCKED) { + if (mt->mutex->queue.next != MUTEX_LOCKED && + mt->mutex->queue.next != NULL) { mt->timeout = 1; list_node_t *node = list_remove(&mt->mutex->queue, (list_node_t *)&mt->thread->rq_entry); @@ -266,7 +267,6 @@ static void _mutex_timeout(void *arg) return; } } - irq_restore(irqstate); }