kernel: fix race conditions with z_ready_thread

Several internal APIs wrote thread attributes (return value, mainly)
_after_ calling `z_ready_thread`. This is unsafe, at least in SMP,
because another core could have already picked up and run the thread.

Fixes #32800.

Signed-off-by: James Harris <james.harris@intel.com>
This commit is contained in:
James Harris
2021-03-02 13:22:52 -08:00
committed by Anas Nashif
parent bb014514e0
commit c7bb423f3e
5 changed files with 8 additions and 8 deletions

View File

@@ -64,9 +64,9 @@ int z_impl_k_condvar_broadcast(struct k_condvar *condvar)
/* wake up any threads that are waiting to write */
while ((pending_thread = z_unpend_first_thread(&condvar->wait_q)) !=
NULL) {
woken++;
arch_thread_return_value_set(pending_thread, 0);
z_ready_thread(pending_thread);
woken++;
}
z_reschedule(&lock, key);

View File

@@ -41,9 +41,9 @@ int z_impl_k_futex_wake(struct k_futex *futex, bool wake_all)
do {
thread = z_unpend_first_thread(&futex_data->wait_q);
if (thread) {
z_ready_thread(thread);
arch_thread_return_value_set(thread, 0);
woken++;
arch_thread_return_value_set(thread, 0);
z_ready_thread(thread);
}
} while (thread && wake_all);

View File

@@ -108,10 +108,10 @@ int z_impl_k_stack_push(struct k_stack *stack, stack_data_t data)
first_pending_thread = z_unpend_first_thread(&stack->wait_q);
if (first_pending_thread != NULL) {
z_ready_thread(first_pending_thread);
z_thread_return_value_set_with_data(first_pending_thread,
0, (void *)data);
z_ready_thread(first_pending_thread);
z_reschedule(&stack->lock, key);
goto end;
} else {

View File

@@ -82,9 +82,9 @@ void z_timer_expiration_handler(struct _timeout *t)
*/
z_unpend_thread_no_timeout(thread);
z_ready_thread(thread);
arch_thread_return_value_set(thread, 0);
z_ready_thread(thread);
}

View File

@@ -142,8 +142,8 @@ int pthread_mutex_unlock(pthread_mutex_t *m)
if (thread) {
m->owner = (pthread_t)thread;
m->lock_count++;
z_ready_thread(thread);
arch_thread_return_value_set(thread, 0);
z_ready_thread(thread);
z_reschedule_irqlock(key);
return 0;
}