cortexm_common: disable IRQ during thread_sched_idle

A race condition is present where an IRQ is serviced between the
priority increase of the PENDSV and the sleep. When the IRQ
is serviced before the WFI sleep, the core will sleep until the next
IRQ and the thread activated by the IRQ will not be scheduled until
a new IRQ triggers.

This commit wraps an IRQ disable and restore around the priority
modification and sleep to prevent interrupts from being serviced until
the WFI call returns.
This commit is contained in:
Koen Zandberg 2020-07-16 11:11:15 +02:00
parent 90911f4bf9
commit eec7aa2e42
No known key found for this signature in database
GPG Key ID: 0895A893E6D2985B

View File

@ -462,6 +462,7 @@ void sched_arch_idle(void)
* According to [this](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0321a/BIHJICIE.html), * According to [this](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0321a/BIHJICIE.html),
* dynamically changing the priority is not supported on CortexM0(+). * dynamically changing the priority is not supported on CortexM0(+).
*/ */
unsigned state = irq_disable();
NVIC_SetPriority(PendSV_IRQn, CPU_CORTEXM_PENDSV_IRQ_PRIO + 1); NVIC_SetPriority(PendSV_IRQn, CPU_CORTEXM_PENDSV_IRQ_PRIO + 1);
__DSB(); __DSB();
__ISB(); __ISB();
@ -471,5 +472,6 @@ void sched_arch_idle(void)
#else #else
__WFI(); __WFI();
#endif #endif
irq_restore(state);
NVIC_SetPriority(PendSV_IRQn, CPU_CORTEXM_PENDSV_IRQ_PRIO); NVIC_SetPriority(PendSV_IRQn, CPU_CORTEXM_PENDSV_IRQ_PRIO);
} }