1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

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);
    ...
}
This commit is contained in:
Pieter Willemsen 2019-01-25 18:53:54 +01:00 committed by JulianHolzwarth
parent cce1438e61
commit f3b13cf90c

View File

@ -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);
}