Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion sys/xtimer/xtimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,12 @@ 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;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has to be MUTEX_LOCKED because we assume that someone still owns the mutex, right?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly.

When the mutex is unlocked, queue.next is NULL. mutex -> NULL
When the mutex is locked by 1 thread queue.next is MUTEX_LOCKED. mutex -> LOCKED
When the mutex is locked by 2+ threads queue.next is the mt->thread->rq_entry of a thread and the last .next is NULL. mutex -> thread -> (thread -> ...) NULL

If node != NULL we were removed from the list, hence 2+ threads where in the list. At the same time if queue.next is NULL means that we were the last thread in the list and we need to set queue.next to MUTEX_LOCKED as there's now 1 thread still owning the mutex.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, otherwise you could have locked it and then the timeout never fire.

}
sched_set_status(mt->thread, STATUS_PENDING);
list_remove(&mt->mutex->queue, (list_node_t *)&mt->thread->rq_entry);
thread_yield_higher();
}

Expand Down