Skip to content

Commit 7022000

Browse files
Andy Rossdleach02
authored andcommitted
kernel/mutex: Fix races, make unlock rescheduling
The k_mutex is a priority-inheriting mutex, so on unlock it's possible that a thread's priority will be lowered. Make this a reschedule point so that reasoning about thread priorities is easier (possibly at the cost of performance): most users are going to expect that the priority elevation stops at exactly the moment of unlock. Note that this also reorders the code to fix what appear to be obvious race conditions. After the call to z_ready_thread(), that thread may be run (e.g. by an interrupt preemption or on another SMP core), yet the return value and mutex weren't correctly set yet. The spinlock was also prematurely released. Fixes #20802 Signed-off-by: Andy Ross <[email protected]>
1 parent 84f8235 commit 7022000

File tree

1 file changed

+3
-6
lines changed

1 file changed

+3
-6
lines changed

kernel/mutex.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -233,18 +233,15 @@ void z_impl_k_mutex_unlock(struct k_mutex *mutex)
233233
mutex, new_owner, new_owner ? new_owner->base.prio : -1000);
234234

235235
if (new_owner != NULL) {
236-
z_ready_thread(new_owner);
237-
238-
k_spin_unlock(&lock, key);
239-
240-
arch_thread_return_value_set(new_owner, 0);
241-
242236
/*
243237
* new owner is already of higher or equal prio than first
244238
* waiter since the wait queue is priority-based: no need to
245239
* ajust its priority
246240
*/
247241
mutex->owner_orig_prio = new_owner->base.prio;
242+
arch_thread_return_value_set(new_owner, 0);
243+
z_ready_thread(new_owner);
244+
z_reschedule(&lock, key);
248245
} else {
249246
mutex->lock_count = 0U;
250247
k_spin_unlock(&lock, key);

0 commit comments

Comments
 (0)