From f324d1d8dde878ce5ed5ce86e54a8388783bfef4 Mon Sep 17 00:00:00 2001 From: yangguangcai Date: Thu, 23 Mar 2023 23:08:22 +0800 Subject: [PATCH] SMP: fix repeat entry oneshot_tick_start Situation: Assume we have 2 cpus. CPU0 CPU1 1. -> nxsched_alarm_expiration 2. -> nxshced_timer_start 3. -> ONESHOT_TICK_START 4. now timer in IRQ 5. in thread 6. -> wd_start 7. -> nxshced_timer_start 8. -> ONESHOT_TICK_START 9. reentry timer crash Fix: Enter critical section before nxsched_timer_start Signed-off-by: yangguangcai --- sched/sched/sched_timerexpiration.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sched/sched/sched_timerexpiration.c b/sched/sched/sched_timerexpiration.c index 427185ccd9d..96ea6b23ff5 100644 --- a/sched/sched/sched_timerexpiration.c +++ b/sched/sched/sched_timerexpiration.c @@ -533,6 +533,18 @@ void nxsched_alarm_tick_expiration(clock_t ticks) { unsigned int elapsed; unsigned int nexttime; +#ifdef CONFIG_SMP + irqstate_t flags; + + /* If we are running on a single CPU architecture, then we know interrupts + * are disabled and there is no need to explicitly call + * enter_critical_section(). However, in the SMP case, + * enter_critical_section() is required prevent multiple cpu to enter + * oneshot_tick_start. + */ + + flags = enter_critical_section(); +#endif /* Calculate elapsed */ @@ -552,6 +564,9 @@ void nxsched_alarm_tick_expiration(clock_t ticks) nexttime = nxsched_timer_process(elapsed, false); nxsched_timer_start(nexttime); +#ifdef CONFIG_SMP + leave_critical_section(flags); +#endif } void nxsched_alarm_expiration(FAR const struct timespec *ts)