-
Notifications
You must be signed in to change notification settings - Fork 806
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Adds a executor for the Xtensa arch - Light sleep implemented with assembly, so we don't pull in the xtensa_lx crates (yet) - lock behind a nightly feature due to Xtensa asm support not upstream
- Loading branch information
Showing
3 changed files
with
78 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
use core::marker::PhantomData; | ||
use core::ptr; | ||
|
||
use atomic_polyfill::{AtomicBool, Ordering}; | ||
|
||
use super::{raw, Spawner}; | ||
|
||
/// global atomic used to keep track of whether there is work to do since sev() is not available on Xtensa | ||
/// | ||
static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false); | ||
|
||
/// Xtensa Executor | ||
pub struct Executor { | ||
inner: raw::Executor, | ||
not_send: PhantomData<*mut ()>, | ||
} | ||
|
||
impl Executor { | ||
/// Create a new Executor. | ||
pub fn new() -> Self { | ||
Self { | ||
// use Signal_Work_Thread_Mode as substitute for local interrupt register | ||
inner: raw::Executor::new( | ||
|_| { | ||
SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst); | ||
}, | ||
ptr::null_mut(), | ||
), | ||
not_send: PhantomData, | ||
} | ||
} | ||
|
||
/// Run the executor. | ||
/// | ||
/// The `init` closure is called with a [`Spawner`] that spawns tasks on | ||
/// this executor. Use it to spawn the initial task(s). After `init` returns, | ||
/// the executor starts running the tasks. | ||
/// | ||
/// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`), | ||
/// for example by passing it as an argument to the initial tasks. | ||
/// | ||
/// This function requires `&'static mut self`. This means you have to store the | ||
/// Executor instance in a place where it'll live forever and grants you mutable | ||
/// access. There's a few ways to do this: | ||
/// | ||
/// - a [Forever](crate::util::Forever) (safe) | ||
/// - a `static mut` (unsafe) | ||
/// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) | ||
/// | ||
/// This function never returns. | ||
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! { | ||
init(self.inner.spawner()); | ||
|
||
loop { | ||
unsafe { | ||
self.inner.poll(); | ||
// 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 | ||
core::arch::asm!("waiti 0"); /* wait for any prio interrupt */ | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters