embassy/embassy-executor/src/arch/std.rs
2023-08-12 22:17:03 +02:00

80 lines
2 KiB
Rust

#[cfg(feature = "executor-interrupt")]
compile_error!("`executor-interrupt` is not supported with `arch-std`.");
#[cfg(not(feature = "thread-context"))]
compile_error!("`arch-std` requires `thread-context`.");
#[cfg(feature = "executor-thread")]
pub use thread::*;
#[cfg(feature = "executor-thread")]
mod thread {
use std::sync::{Condvar, Mutex};
#[cfg(feature = "nightly")]
pub use embassy_macros::main_std as main;
use crate::raw::OpaqueThreadContext;
use crate::thread::ThreadContext;
/// TODO
// Name pending
pub struct StdThreadCtx {
signaler: &'static Signaler,
}
impl Default for StdThreadCtx {
fn default() -> Self {
Self {
signaler: &*Box::leak(Box::new(Signaler::new())),
}
}
}
impl ThreadContext for StdThreadCtx {
fn context(&self) -> OpaqueThreadContext {
OpaqueThreadContext(self.signaler as *const _ as usize)
}
fn wait(&mut self) {
self.signaler.wait()
}
}
#[export_name = "__thread_mode_pender"]
fn __thread_mode_pender(core_id: OpaqueThreadContext) {
let signaler: &'static Signaler = unsafe { std::mem::transmute(core_id) };
signaler.signal()
}
struct Signaler {
mutex: Mutex<bool>,
condvar: Condvar,
}
impl Signaler {
fn new() -> Self {
Self {
mutex: Mutex::new(false),
condvar: Condvar::new(),
}
}
fn wait(&self) {
let mut signaled = self.mutex.lock().unwrap();
while !*signaled {
signaled = self.condvar.wait(signaled).unwrap();
}
*signaled = false;
}
fn signal(&self) {
let mut signaled = self.mutex.lock().unwrap();
*signaled = true;
self.condvar.notify_one();
}
}
/// TODO
// Type alias for backwards compatibility
pub type Executor = crate::thread::ThreadModeExecutor<StdThreadCtx>;
}