mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-16 06:16:30 +00:00
The workaround for nonatomic swap had yet another edge case: it would save off the _current pointer when pending a thread so that the next time slice interrupt could test it to see if the swap had actually happened before assuming that _current could be rescheduled (if it just pended itself, that's impossible). Then it would clear the pending_current pointer so future interrupts wouldn't be confused. BUT: it turns out that qemu, when faced with really rapid timer rates that exceed its (host-based) timing accuracy, is perfectly willing to "stack up" timer interrupts such the one goes pending before the previous one is finished executing. In that case, we can enter the SECOND timer interrupt, to try timeslicing a SECOND time, STILL before the PendSV exception has run to actually effect the context switch. Except this time pending_current has been cleared and we try to reschedule the pended _current thread incorrectly. In theory real hardware could do this too, though it would involve absolutely crazy interrupt latency problems. Work around this by moving the clear to the thread itself, immediately after it wakes up from the pend call it retakes a lock and clears pending_current if it still matches _current. That is not a perfect fix: there remains a 2-3 instruction race at that moment where we return from pend and before we can lock interrupts again where a timer interrupt will see an incorrect pointer. But I hammered at this and couldn't make qemu do that (i.e. return from a timer interrupt but flag a new one in just a cycle or two). Signed-off-by: Andy Ross <andrew.j.ross@intel.com> |
||
---|---|---|
.. | ||
include | ||
atomic_c.c | ||
CMakeLists.txt | ||
compiler_stack_protect.c | ||
device.c | ||
errno.c | ||
idle.c | ||
init.c | ||
int_latency_bench.c | ||
Kconfig | ||
Kconfig.power_mgmt | ||
mailbox.c | ||
mem_domain.c | ||
mem_slab.c | ||
mempool.c | ||
msg_q.c | ||
mutex.c | ||
pipes.c | ||
poll.c | ||
queue.c | ||
sched.c | ||
sem.c | ||
smp.c | ||
stack.c | ||
system_work_q.c | ||
thread_abort.c | ||
thread.c | ||
timeout.c | ||
timer.c | ||
userspace_handler.c | ||
userspace.c | ||
version.c | ||
work_q.c |