This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 57ad26a7c2247cc5a073fa7b4a32f245275be6f2
Author: Marco Casaroli <[email protected]>
AuthorDate: Mon Nov 2 13:24:41 2026 +0100

    sched/init: Clear a lost task delivery when a CPU starts.
    
    nxsched_deliver_task() sets g_delivertasks[cpu] and sends an
    inter-processor interrupt to that CPU.  The CPU clears the request in
    nxsched_process_delivered().  While the request is set, no other CPU
    sends an interrupt to that CPU again.
    
    The other CPUs boot in parallel with CPU0 (on arm64 since commit
    5e2eadacf77), so CPU0 can deliver a task to a CPU that did not yet
    initialize its interrupt controller.  That CPU loses the interrupt (the
    arm64 GICv3 initialization also clears the pending SGIs of the CPU),
    and the request stays set.  After that, no task delivery reaches this
    CPU, also not the one of sched_unlock() on the CPU itself.  A task that
    can run only on that CPU never runs: the ostest spinlock test hangs in
    its first case on qemu-armv8a:nsh_smp with 4 CPUs under HVF.
    
    Clear the request in nx_idle_trampoline(), where the CPU can take
    interrupts, before sched_unlock() looks at the ready-to-run list.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 sched/init/nx_smpstart.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/sched/init/nx_smpstart.c b/sched/init/nx_smpstart.c
index e8e3d3a2f87..b87008c6e1e 100644
--- a/sched/init/nx_smpstart.c
+++ b/sched/init/nx_smpstart.c
@@ -79,6 +79,13 @@ void nx_idle_trampoline(void)
 
   while (!OSINIT_IDLELOOP());
 
+  /* A task delivered to this CPU before it could take interrupts may have
+   * lost its inter-processor interrupt.  Clear the stale request, which
+   * would block every later delivery here; sched_unlock() runs the task.
+   */
+
+  g_delivertasks[this_cpu()] = SWITCH_NONE;
+
   sched_unlock();
 
   /* Enter the IDLE loop */

Reply via email to