This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 7e5bf155b53d6e9598e8c7f16747a9ee0a65afbd Author: raiden00pl <[email protected]> AuthorDate: Tue Sep 8 10:23:27 2026 +0200 arch/intel64: don't clear the oneshot handler from the HPET ISR intel64_oneshot_handler() cleared oneshot->handler and oneshot->arg after picking them up, without holding g_oneshot_spin, while intel64_oneshot_start() re-arms the timer under that lock from another CPU. Now that the HPET ISR stays attached across a re-arm, a stale interrupt can interleave with start(): it reads the freshly installed handler, clears it, and start() then sets running = true again, so the genuine expiry that follows finds running == true with a NULL handler and jumps to address zero from interrupt context (page fault at RIP 0 in the CPU0 IDLE task while the LTP lio_listio tests were running), or the alarm is simply lost and the tickless system stops. The handler and its argument are owned by start() and cancel(); the ISR only needs to read them. Leave them alone in the ISR and skip the call if none is installed. The remaining effect of a stale interrupt is an early invocation of the alarm callback, which is harmless: the tickless scheduler re-evaluates its expirations and re-arms the timer. Assisted-by: Claude Code Signed-off-by: raiden00pl <[email protected]> --- arch/x86_64/src/intel64/intel64_oneshot.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/arch/x86_64/src/intel64/intel64_oneshot.c b/arch/x86_64/src/intel64/intel64_oneshot.c index eb907eaed17..27168a329f8 100644 --- a/arch/x86_64/src/intel64/intel64_oneshot.c +++ b/arch/x86_64/src/intel64/intel64_oneshot.c @@ -100,18 +100,21 @@ static int intel64_oneshot_handler(int irg_num, void * context, void *arg) INTEL64_TIM_ACKINT(oneshot->tch, oneshot->chan); #endif - /* The timer is no longer running */ + /* The timer is no longer running. Only pick up the handler here; + * it is owned by intel64_oneshot_start()/cancel(), which may be + * re-arming the timer on another CPU right now. Clearing it from + * the ISR could leave a re-armed timer without a handler, and the + * next expiry would then jump through a NULL pointer. + */ oneshot->running = false; - - /* Forward the event, clearing out any vestiges */ - oneshot_handler = (oneshot_handler_t)oneshot->handler; - oneshot->handler = NULL; oneshot_arg = (void *)oneshot->arg; - oneshot->arg = NULL; - oneshot_handler(oneshot_arg); + if (oneshot_handler != NULL) + { + oneshot_handler(oneshot_arg); + } } else {
