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

Reply via email to