From 0eb66a429fddc63b42fe602d0fc74c16eef23d6e Mon Sep 17 00:00:00 2001 From: Koen Zandberg Date: Tue, 21 Jul 2020 11:23:49 +0200 Subject: [PATCH 1/2] cortexm_common: Clear PendSV request after idle sleep The PendSV interrupt is used to request a scheduling operation. An interrupt during the idle sleep can re-request the PendSV interrupt, while the PendSV is still busy scheduling the next thread. This clears the request after sleep to prevent triggering an extra PendSV interrupt after the current PendSV handler finished. --- cpu/cortexm_common/thread_arch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/cpu/cortexm_common/thread_arch.c b/cpu/cortexm_common/thread_arch.c index ebc13ac609..0b4352b658 100644 --- a/cpu/cortexm_common/thread_arch.c +++ b/cpu/cortexm_common/thread_arch.c @@ -474,4 +474,5 @@ void sched_arch_idle(void) #endif irq_restore(state); NVIC_SetPriority(PendSV_IRQn, CPU_CORTEXM_PENDSV_IRQ_PRIO); + SCB->ICSR = SCB_ICSR_PENDSVCLR_Msk; } From 2d746512376fa94e8a0de47c5fb8b40bbef0f7be Mon Sep 17 00:00:00 2001 From: Koen Zandberg Date: Tue, 21 Jul 2020 11:27:08 +0200 Subject: [PATCH 2/2] sched: Clear context_switch_request after potential idle sleep An interrupt serviced during the idle sleep can re-request a context switch while the scheduler is already going to switch contexts after the idle sleep. Thi sched_context_switch_request should thus be cleared after the idle sleep and not before where it could be modified during the idle sleep and get out of sync. --- core/sched.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/sched.c b/core/sched.c index 011171861c..fcfc0173e6 100644 --- a/core/sched.c +++ b/core/sched.c @@ -99,7 +99,6 @@ static void _unschedule(thread_t *active_thread) int __attribute__((used)) sched_run(void) { - sched_context_switch_request = 0; thread_t *active_thread = (thread_t *)sched_active_thread; if (!IS_USED(MODULE_CORE_IDLE_THREAD)) { @@ -115,6 +114,8 @@ int __attribute__((used)) sched_run(void) } } + sched_context_switch_request = 0; + int nextrq = bitarithm_lsb(runqueue_bitcache); thread_t *next_thread = container_of(sched_runqueues[nextrq].next->next, thread_t, rq_entry);