Skip to content

Commit a08e23f

Browse files
andyrossjgl-meta
authored andcommitted
kernel/sched: Fix SMP must-wait-for-switch conditions in abort/join
As discovered by Carlo Caione, the k_thread_join code had a case where it detected it had been called on a thread already marked _THREAD_DEAD and exited early. That's not sufficient. The thread state is mutated from the thread itself on its exit path. It may still be running! Just like the code in z_swap(), we need to spin waiting on the other CPU to write the switch handle before knowing it's safe to return, otherwise the calling context might (and did) do something like immediately k_thread_create() a new thread in the "dead" thread's struct while it was still running on the other core. There was also a similar case in k_thread_abort() which had the same issue: it needs to spin waiting on the other CPU to kill the thread via the same mechanism. Fixes #58116 Originally-by: Carlo Caione <[email protected]> Signed-off-by: Andy Ross <[email protected]>
1 parent c3046f4 commit a08e23f

File tree

1 file changed

+8
-0
lines changed

1 file changed

+8
-0
lines changed

kernel/sched.c

+8
Original file line numberDiff line numberDiff line change
@@ -1771,6 +1771,13 @@ void z_thread_abort(struct k_thread *thread)
17711771
k_spin_unlock(&sched_spinlock, key);
17721772
while (is_aborting(thread)) {
17731773
}
1774+
1775+
/* Now we know it's dying, but not necessarily
1776+
* dead. Wait for the switch to happen!
1777+
*/
1778+
key = k_spin_lock(&sched_spinlock);
1779+
z_sched_switch_spin(thread);
1780+
k_spin_unlock(&sched_spinlock, key);
17741781
} else if (active) {
17751782
/* Threads can join */
17761783
add_to_waitq_locked(_current, &thread->join_queue);
@@ -1806,6 +1813,7 @@ int z_impl_k_thread_join(struct k_thread *thread, k_timeout_t timeout)
18061813
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_thread, join, thread, timeout);
18071814

18081815
if ((thread->base.thread_state & _THREAD_DEAD) != 0U) {
1816+
z_sched_switch_spin(thread);
18091817
ret = 0;
18101818
} else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
18111819
ret = -EBUSY;

0 commit comments

Comments
 (0)