From 89c4a074dc6257a4f2f186dbb30368937259d618 Mon Sep 17 00:00:00 2001 From: Qi Yang Date: Fri, 12 Aug 2022 10:44:38 +0800 Subject: [PATCH] kernel: mutex: fix races when lock timeout Say threadA holds a mutex and threadB tries to lock it with a timeout, a race would occur if threadA unlock that mutex after threadB got unpended by sys_clock and before it gets scheduled and calls k_spin_lock. This patch fixes this issue by checking the mutex's status again after k_spin_lock calls. Fixes #48056 Signed-off-by: Qi Yang --- kernel/mutex.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/kernel/mutex.c b/kernel/mutex.c index 24d4e378311..32c889bb237 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c @@ -161,15 +161,21 @@ int z_impl_k_mutex_lock(struct k_mutex *mutex, k_timeout_t timeout) key = k_spin_lock(&lock); - struct k_thread *waiter = z_waitq_head(&mutex->wait_q); + /* + * Check if mutex was unlocked after this thread was unpended. + * If so, skip adjusting owner's priority down. + */ + if (likely(mutex->owner != NULL)) { + struct k_thread *waiter = z_waitq_head(&mutex->wait_q); - new_prio = (waiter != NULL) ? - new_prio_for_inheritance(waiter->base.prio, mutex->owner_orig_prio) : - mutex->owner_orig_prio; + new_prio = (waiter != NULL) ? + new_prio_for_inheritance(waiter->base.prio, mutex->owner_orig_prio) : + mutex->owner_orig_prio; - LOG_DBG("adjusting prio down on mutex %p", mutex); + LOG_DBG("adjusting prio down on mutex %p", mutex); - resched = adjust_owner_prio(mutex, new_prio) || resched; + resched = adjust_owner_prio(mutex, new_prio) || resched; + } if (resched) { z_reschedule(&lock, key);