This is an automated email from the ASF dual-hosted git repository. jerpelea pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 0093b3a0fb27a9536e0509e8a78e976907a809d0 Author: Marco Casaroli <[email protected]> AuthorDate: Sun Nov 1 01:28:16 2026 +0100 arch/x86_64: Do not switch context in up_exit() before the last switch. up_exit() runs on the stack of the task that has exited, after nxtask_exit() made the next task the head of the ready-to-run list. addrenv_switch() there can drop the address environment of the task that has exited on the low priority work queue, and work_queue() then switched to the worker if it had a higher priority than the next task (for example the idle task): up_switch_context() saved the context of up_exit() as the one of the next task, and that task later continued in up_exit() on a freed stack. Raise the lock count of the next task around addrenv_switch(), as nxtask_exit() does, then publish the worker, and give the new head of the list its address environment. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <[email protected]> --- arch/x86_64/src/common/x86_64_exit.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/x86_64/src/common/x86_64_exit.c b/arch/x86_64/src/common/x86_64_exit.c index 6070cc82a60..2e8b0b3d03e 100644 --- a/arch/x86_64/src/common/x86_64_exit.c +++ b/arch/x86_64/src/common/x86_64_exit.c @@ -71,10 +71,25 @@ void up_exit(int status) * task is closed down gracefully (data caches dump, MMU flushed) and * set up the address environment for the new thread at the head of * the ready-to-run list. + * + * No context switch here: this runs on the stack of the task that has + * exited. Publish the worker that addrenv_switch() can wake as + * nxtask_exit() does, then switch to the new head of the list. */ - addrenv_switch(tcb); - tcb = this_task(); + do + { + tcb = this_task(); + tcb->lockcount++; + addrenv_switch(tcb); + tcb->lockcount--; +# ifdef CONFIG_SMP + nxsched_deliver_task(this_cpu(), tcb->cpu, SWITCH_HIGHER); +# else + nxsched_merge_pending(); +# endif + } + while (tcb != this_task()); #endif /* Adjusts time slice for SCHED_RR & SCHED_SPORADIC cases
