Skip to content

Commit d79c863

Browse files
committed
OS/ThreadX: Fix SMP IRQ system state handling and IRQ-exit reschedule
Update the Nuclei SMP interrupt entry paths to maintain `_tx_thread_system_state` per hart for normal IRQ nesting, while keeping the scheduler SWI path separate. This lets ThreadX caller checks correctly detect IRQ context, so illegal system calls made from timer or interrupt context are rejected instead of running into normal thread-side scheduling paths and faulting later. Also add an non-vector IRQ-exit scheduling check that raises the local scheduler SWI only after IRQ nesting unwinds back to thread context, when the current thread no longer matches the execute slot and preemption is enabled. Apply the same behavior to both GCC and IAR ports. This change only updates the common non-vector IRQ exit path. If a vector interrupt path also needs IRQ-exit reschedule behavior, it should invoke `_tx_thread_irq_exit_schedule_check` before returning to thread context. Signed-off-by: Huaqi Fang <578567190@qq.com>
1 parent 3bea058 commit d79c863

3 files changed

Lines changed: 91 additions & 0 deletions

File tree

OS/ThreadX/ports_smp/nuclei/gcc/interrupt.S

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "riscv_encoding.h"
22
#include "cpufeature.h"
33

4+
.extern _tx_thread_irq_exit_schedule_check
5+
46
.section .text.entry
57
.align 8
68

@@ -15,6 +17,19 @@
1517
csrc CSR_MSTATUS, MSTATUS_MIE
1618
.endm
1719

20+
/* Update ThreadX SMP per-core ISR nesting state.
21+
* This macro must be called after SAVE_CONTEXT because it clobbers t0-t2.
22+
*/
23+
.macro UPDATE_THREADX_SYSTEM_STATE delta
24+
la t0, _tx_thread_system_state
25+
csrr t1, CSR_MHARTID
26+
slli t1, t1, LOG_REGBYTES
27+
add t0, t0, t1
28+
LOAD t2, 0(t0)
29+
addi t2, t2, \delta
30+
STORE t2, 0(t0)
31+
.endm
32+
1833
/**
1934
* \brief Macro for context save
2035
* \details
@@ -202,6 +217,11 @@ irq_entry:
202217
/* Save the necessary CSR registers */
203218
SAVE_CSR_CONTEXT
204219

220+
/* Mark this core as being in a normal IRQ handler.
221+
* eclic_msip_handler is the scheduler SWI path and is handled separately.
222+
*/
223+
UPDATE_THREADX_SYSTEM_STATE 1
224+
205225
/* This special CSR read/write operation, which is actually
206226
* claim the CLIC to find its pending highest ID, if the ID
207227
* is not 0, then automatically enable the mstatus.MIE, and
@@ -212,6 +232,17 @@ irq_entry:
212232
/* Critical section with interrupts disabled */
213233
DISABLE_MIE
214234

235+
/* All nested IRQ work claimed by JALMNXTI is done; leave ThreadX ISR context
236+
* before restoring the interrupted context.
237+
*/
238+
UPDATE_THREADX_SYSTEM_STATE -1
239+
240+
/* If ThreadX is about to return to normal thread context and the
241+
* scheduler already selected a different execute thread for this core,
242+
* request the scheduler SWI now.
243+
*/
244+
call _tx_thread_irq_exit_schedule_check
245+
215246
/* Restore the necessary CSR registers */
216247
RESTORE_CSR_CONTEXT
217248
/* Restore the caller saving registers (context) */

OS/ThreadX/ports_smp/nuclei/iar/interrupt.S

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ DISABLE_MIE MACRO
55
csrci CSR_MSTATUS, MSTATUS_MIE
66
ENDM
77

8+
/* Update ThreadX SMP per-core ISR nesting state.
9+
* This macro must be called after SAVE_CONTEXT because it clobbers t0-t2.
10+
*/
11+
UPDATE_THREADX_SYSTEM_STATE MACRO delta
12+
la t0, _tx_thread_system_state
13+
csrr t1, CSR_MHARTID
14+
slli t1, t1, LOG_REGBYTES
15+
add t0, t0, t1
16+
LOAD t2, 0(t0)
17+
addi t2, t2, delta
18+
STORE t2, 0(t0)
19+
ENDM
20+
821
SAVE_CONTEXT MACRO
922
#if defined(ECLIC_HW_CTX_AUTO) && defined(CFG_HAS_ECLICV2)
1023
#else
@@ -97,6 +110,8 @@ RESTORE_CSR_CONTEXT MACRO
97110
PUBLIC exc_entry, irq_entry, default_intexc_handler
98111
PUBLIC Undef_Handler
99112
EXTERN core_exception_handler
113+
EXTERN _tx_thread_irq_exit_schedule_check
114+
EXTERN _tx_thread_system_state
100115
SECTION `.text`:CODE:NOROOT(2)
101116
CODE
102117

@@ -162,6 +177,11 @@ irq_entry:
162177
/* Save the necessary CSR registers */
163178
SAVE_CSR_CONTEXT
164179

180+
/* Mark this core as being in a normal IRQ handler.
181+
* eclic_msip_handler is the scheduler SWI path and is handled separately.
182+
*/
183+
UPDATE_THREADX_SYSTEM_STATE 1
184+
165185
/* This special CSR read/write operation, which is actually
166186
* claim the CLIC to find its pending highest ID, if the ID
167187
* is not 0, then automatically enable the mstatus.MIE, and
@@ -172,6 +192,17 @@ irq_entry:
172192
/* Critical section with interrupts disabled */
173193
DISABLE_MIE
174194

195+
/* All nested IRQ work claimed by JALMNXTI is done; leave ThreadX ISR context
196+
* before restoring the interrupted context.
197+
*/
198+
UPDATE_THREADX_SYSTEM_STATE -1
199+
200+
/* If ThreadX is about to return to normal thread context and the
201+
* scheduler already selected a different execute thread for this core,
202+
* request the scheduler SWI now.
203+
*/
204+
call _tx_thread_irq_exit_schedule_check
205+
175206
/* Restore the necessary CSR registers */
176207
RESTORE_CSR_CONTEXT
177208
/* Restore the caller saving registers (context) */

OS/ThreadX/ports_smp/nuclei/port.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,35 @@ void _tx_thread_smp_core_preempt(UINT core)
267267
within the specified behaviour for the architecture. */
268268
__RWMB();
269269
}
270+
271+
void _tx_thread_irq_exit_schedule_check(void)
272+
{
273+
UINT coreid;
274+
275+
coreid = _tx_thread_smp_core_get();
276+
277+
/* Only request scheduling when the IRQ nesting for this core has fully
278+
unwound and ThreadX is about to return to normal thread context. */
279+
if (_tx_thread_system_state[coreid] != ((ULONG)0)) {
280+
return;
281+
}
282+
283+
/* No scheduling request is needed if the current thread already matches
284+
the scheduler's execute target for this core. */
285+
if (_tx_thread_current_ptr[coreid] == _tx_thread_execute_ptr[coreid]) {
286+
return;
287+
}
288+
289+
/* Honor ThreadX global preemption disable state. If scheduling is
290+
deferred here, the normal ThreadX resume/preempt paths are expected
291+
to request it later. */
292+
if (_tx_thread_preempt_disable != ((UINT)0)) {
293+
return;
294+
}
295+
296+
SysTimer_SetSWIRQ();
297+
__RWMB();
298+
}
270299
#endif
271300

272301
// _tx_thread_schedule function implemented in context.S

0 commit comments

Comments
 (0)