Skip to content

Commit cba5ce6

Browse files
committed
OS/ThreadX: fix multi-core deadlock in Nuclei RISC-V SMP port
Fix a real multi-core deadlock in the ThreadX SMP port for Nuclei RISC-V CPU (OS/ThreadX/ports_smp/nuclei). The issue was reported by a customer, who also provided the initial patch. Bug scenario: When a thread on a secondary core entered the sleep/suspend flow, the generic ThreadX SMP layer released the interrupt posture (TX_RESTORE) before calling _tx_thread_system_return, keeping the SMP protection held with interrupts enabled. The port then cleared _tx_thread_preempt_disable before releasing _tx_thread_smp_protection. An IRQ landing in this narrow window could trigger scheduling from the IRQ exit path (_tx_thread_irq_exit_schedule_check) while the core still held the SMP protection: the core found no ready thread and spun forever in the scheduler waiting for a ready thread, while other cores spun forever waiting for the SMP protection, hanging the whole system. Fix: Move the _tx_thread_preempt_disable = 0 clearing out of _tx_thread_system_return into _tx_thread_smp_force_unprotect, right after interrupts are disabled (MSTATUS.MIE cleared). This guarantees preempt_disable is only cleared once the local core can no longer be interrupted, so an IRQ can never trigger scheduling while the core is still in the middle of releasing the SMP protection. This matches the ARM SMP port behavior. Verification: - Reproduced the deadlock and verified the patch on N900FD and NX900FD with SMPx4 - Full ThreadX regression suite still passes with the patch applied Signed-off-by: Huaqi Fang <578567190@qq.com>
1 parent 0b21ce8 commit cba5ce6

2 files changed

Lines changed: 22 additions & 2 deletions

File tree

OS/ThreadX/ports_smp/nuclei/port.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,12 @@ void _tx_thread_smp_force_unprotect(UINT new_interrupt_posture)
240240
UINT core_id;
241241

242242
__RV_CSR_READ_CLEAR(CSR_MSTATUS, MSTATUS_MIE);
243+
/* Clear preempt_disable only after interrupts are disabled: the generic SMP layer
244+
can call this with interrupts re-enabled while the SMP protection is still held,
245+
so clearing it earlier would let an IRQ exit trigger scheduling on a core that
246+
still owns the protection and deadlock against other cores waiting for it. */
247+
_tx_thread_preempt_disable = 0;
248+
__RWMB();
243249
core_id = _tx_thread_smp_core_get();
244250
if (_tx_thread_smp_protection.tx_thread_smp_protect_core == core_id) {
245251
_tx_thread_smp_protection.tx_thread_smp_protect_count = 0;
@@ -260,8 +266,6 @@ extern volatile UINT _tx_thread_preempt_disable;
260266
#ifndef TXM_MODULE
261267
void _tx_thread_system_return(void)
262268
{
263-
_tx_thread_preempt_disable = 0;
264-
__RWMB();
265269
_tx_thread_smp_force_unprotect(MSTATUS_MIE);
266270

267271
/* Set a software interrupt(SWI) request to request a context switch. */

doc/source/changelog.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,22 @@ This is release version of ``1.0.0`` of Nuclei SDK, which is still under develop
3232
- Enhance ``Components/profiling/README.md`` to add a FAQ entry explaining how to interpret common gprof/gcov error messages, covering the two main categories: heap memory (HEAP) insufficient leading to ``malloc`` failures, and file/IO failures due to semihosting or filesystem issues, with remediation steps for each.
3333
- Add error pattern detection to ``Components/profiling/parse.py`` so that it scans the profiling log for common gprof/gcov error keywords and prints corresponding diagnostic hints before parsing, helping users quickly identify heap-insufficient or file-IO problems.
3434

35+
* OS
36+
37+
- Fix a multi-core deadlock in the ThreadX SMP port for Nuclei RISC-V CPU. When a thread on a
38+
secondary core entered the sleep/suspend flow, the generic ThreadX SMP layer released the
39+
interrupt posture (``TX_RESTORE``) before calling ``_tx_thread_system_return``, keeping the
40+
SMP protection held with interrupts enabled. The port then cleared ``_tx_thread_preempt_disable``
41+
before releasing ``_tx_thread_smp_protection``. An IRQ landing in this window could trigger
42+
scheduling from the IRQ exit path (``_tx_thread_irq_exit_schedule_check``) while the core still
43+
held the SMP protection: the core found no ready thread and spun forever in the scheduler, while
44+
other cores spun forever waiting for the SMP protection, hanging the whole system. Now the
45+
``_tx_thread_preempt_disable = 0`` clearing is moved into ``_tx_thread_smp_force_unprotect`` right
46+
after interrupts are disabled (aligned with the ARM SMP port behavior), so no IRQ can trigger
47+
scheduling in that window. This issue was reported by a customer who also provided the patch;
48+
we reproduced the deadlock and verified the patch on N900FD and NX900FD SMPx4, and confirmed
49+
the full ThreadX regression suite still passes.
50+
3551
* Build System
3652

3753
- Add the ``PFL`` variable to configure EvalSoC IREGION data-prefetch levels.

0 commit comments

Comments
 (0)