Work around xtensa deadlock, take 2

This commit is contained in:
Dániel Buga 2023-05-13 13:44:19 +02:00
parent 82f7e104d9
commit 5fe36b6bb0

View file

@ -63,21 +63,29 @@ mod thread {
loop {
unsafe {
self.inner.poll();
// Manual critical section implementation that only masks interrupts handlers.
// We must not acquire the cross-core on dual-core systems because that would
// prevent the other core from doing useful work while this core is sleeping.
let token: critical_section::RawRestoreState;
core::arch::asm!("rsil {0}, 5", out(reg) token);
// we do not care about race conditions between the load and store operations, interrupts
// will only set this value to true.
// if there is work to do, loop back to polling
// TODO can we relax this?
critical_section::with(|_| {
if SIGNAL_WORK_THREAD_MODE.load(Ordering::SeqCst) {
SIGNAL_WORK_THREAD_MODE.store(false, Ordering::SeqCst);
} else {
// waiti sets the PS.INTLEVEL when slipping into sleep
// because critical sections in Xtensa are implemented via increasing
// PS.INTLEVEL the critical section ends here
// take care not add code after `waiti` if it needs to be inside the CS
core::arch::asm!("waiti 0"); // critical section ends here
}
});
if SIGNAL_WORK_THREAD_MODE.load(Ordering::SeqCst) {
SIGNAL_WORK_THREAD_MODE.store(false, Ordering::SeqCst);
core::arch::asm!(
"wsr.ps {0}",
"rsync", in(reg) token)
} else {
// waiti sets the PS.INTLEVEL when slipping into sleep
// because critical sections in Xtensa are implemented via increasing
// PS.INTLEVEL the critical section ends here
// take care not add code after `waiti` if it needs to be inside the CS
core::arch::asm!("waiti 0"); // critical section ends here
}
}
}
}