Browse Source

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>
pull/32805/head
James Harris 4 years ago committed by Anas Nashif
parent
commit
c7bb423f3e
  1. 2
      kernel/condvar.c
  2. 4
      kernel/futex.c
  3. 4
      kernel/stack.c
  4. 4
      kernel/timer.c
  5. 2
      lib/posix/pthread_mutex.c

2
kernel/condvar.c

@ -64,9 +64,9 @@ int z_impl_k_condvar_broadcast(struct k_condvar *condvar) @@ -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);

4
kernel/futex.c

@ -41,9 +41,9 @@ int z_impl_k_futex_wake(struct k_futex *futex, bool wake_all) @@ -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);

4
kernel/stack.c

@ -108,10 +108,10 @@ int z_impl_k_stack_push(struct k_stack *stack, stack_data_t data) @@ -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 {

4
kernel/timer.c

@ -82,9 +82,9 @@ void z_timer_expiration_handler(struct _timeout *t) @@ -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);
}

2
lib/posix/pthread_mutex.c

@ -142,8 +142,8 @@ int pthread_mutex_unlock(pthread_mutex_t *m) @@ -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;
}

Loading…
Cancel
Save