Skip to content

Commit e92dda4

Browse files
committed
Refine mutex timed lock wakeup condition
Once a task wakes up from a timed mutex lock, its state is already in TASK_RUNNING instead of TASK_BLOCKED. To determine whether the wakeup was triggered by the mutex or by a timeout, check whether the woken task is still present in the mutex waiter list. This change removes the incorrect TASK_BLOCKED-based condition check and replaces it with a waiter list check for timed mutex lock.
1 parent 9942fb4 commit e92dda4

File tree

1 file changed

+9
-16
lines changed

1 file changed

+9
-16
lines changed

kernel/mutex.c

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -237,20 +237,14 @@ int32_t mo_mutex_timedlock(mutex_t *m, uint32_t ticks)
237237
/* Yield and let the scheduler handle timeout via delay mechanism */
238238
mo_task_yield();
239239

240-
/* Check result after waking up */
240+
/* Check result after waking up; the task is in TASK_RUNNING and in the
241+
* ready queue */
241242
int32_t result;
242243

243244
NOSCHED_ENTER();
244-
if (self->state == TASK_BLOCKED) {
245-
/* We woke up due to timeout, not mutex unlock */
246-
if (remove_self_from_waiters(m->waiters)) {
247-
self->state = TASK_READY;
248-
result = ERR_TIMEOUT;
249-
} else {
250-
/* Race condition: we were both timed out and unlocked */
251-
/* Check if we now own the mutex */
252-
result = (m->owner_tid == self_tid) ? ERR_OK : ERR_TIMEOUT;
253-
}
245+
/* If task still in the waiter list, it is woken up due to time out. */
246+
if (remove_self_from_waiters(m->waiters)) {
247+
result = ERR_TIMEOUT;
254248
} else {
255249
/* We were woken by mutex unlock - check ownership */
256250
result = (m->owner_tid == self_tid) ? ERR_OK : ERR_FAIL;
@@ -453,14 +447,13 @@ int32_t mo_cond_timedwait(cond_t *c, mutex_t *m, uint32_t ticks)
453447
/* Yield and wait for signal or timeout */
454448
mo_task_yield();
455449

456-
/* Determine why we woke up */
450+
/* Determine why we woke up; the task is in the TASK_RUNNING state and in
451+
* the ready queue. */
457452
int32_t wait_status;
458453
NOSCHED_ENTER();
459454

460-
if (self->state == TASK_BLOCKED) {
461-
/* Timeout occurred - remove from wait list */
462-
remove_self_from_waiters(c->waiters);
463-
self->state = TASK_READY;
455+
/* Timeout occurred - remove from wait list */
456+
if (remove_self_from_waiters(c->waiters)) {
464457
self->delay = 0;
465458
wait_status = ERR_TIMEOUT;
466459
} else {

0 commit comments

Comments
 (0)