Remove the Pender enum
This commit is contained in:
		
							parent
							
								
									454a7cbf4c
								
							
						
					
					
						commit
						f6007869bf
					
				@ -1,28 +1,84 @@
 | 
			
		||||
#[cfg(feature = "executor-thread")]
 | 
			
		||||
pub use thread::*;
 | 
			
		||||
 | 
			
		||||
use crate::raw::PenderContext;
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "executor-interrupt")]
 | 
			
		||||
 | 
			
		||||
/// # Safety
 | 
			
		||||
///
 | 
			
		||||
/// `irq` must be a valid interrupt request number
 | 
			
		||||
unsafe fn nvic_pend(irq: u16) {
 | 
			
		||||
    use cortex_m::interrupt::InterruptNumber;
 | 
			
		||||
 | 
			
		||||
    #[derive(Clone, Copy)]
 | 
			
		||||
    struct Irq(u16);
 | 
			
		||||
    unsafe impl InterruptNumber for Irq {
 | 
			
		||||
        fn number(self) -> u16 {
 | 
			
		||||
            self.0
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let irq = Irq(irq);
 | 
			
		||||
 | 
			
		||||
    // STIR is faster, but is only available in v7 and higher.
 | 
			
		||||
    #[cfg(not(armv6m))]
 | 
			
		||||
    {
 | 
			
		||||
        let mut nvic: cortex_m::peripheral::NVIC = unsafe { core::mem::transmute(()) };
 | 
			
		||||
        nvic.request(irq);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(armv6m)]
 | 
			
		||||
    cortex_m::peripheral::NVIC::pend(irq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(all(feature = "executor-thread", feature = "executor-interrupt"))]
 | 
			
		||||
#[export_name = "__pender"]
 | 
			
		||||
fn __pender(context: PenderContext) {
 | 
			
		||||
    unsafe {
 | 
			
		||||
        // Safety: `context` is either `usize::MAX` created by `Executor::run`, or a valid interrupt
 | 
			
		||||
        // request number given to `InterruptExecutor::start`.
 | 
			
		||||
        if context as usize == usize::MAX {
 | 
			
		||||
            core::arch::asm!("sev")
 | 
			
		||||
        } else {
 | 
			
		||||
            nvic_pend(context as u16)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(all(feature = "executor-thread", not(feature = "executor-interrupt")))]
 | 
			
		||||
#[export_name = "__pender"]
 | 
			
		||||
fn __pender(_context: PenderContext) {
 | 
			
		||||
    unsafe { core::arch::asm!("sev") }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(all(not(feature = "executor-thread"), feature = "executor-interrupt"))]
 | 
			
		||||
#[export_name = "__pender"]
 | 
			
		||||
fn __pender(context: PenderContext) {
 | 
			
		||||
    unsafe {
 | 
			
		||||
        // Safety: `context` is the same value we passed to `InterruptExecutor::start`, which must
 | 
			
		||||
        // be a valid interrupt request number.
 | 
			
		||||
        nvic_pend(context as u16)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "executor-thread")]
 | 
			
		||||
mod thread {
 | 
			
		||||
 | 
			
		||||
    #[cfg(feature = "nightly")]
 | 
			
		||||
    pub use embassy_macros::main_cortex_m as main;
 | 
			
		||||
 | 
			
		||||
    use crate::raw::OpaqueThreadContext;
 | 
			
		||||
    use crate::raw::PenderContext;
 | 
			
		||||
    use crate::thread::ThreadContext;
 | 
			
		||||
 | 
			
		||||
    #[export_name = "__thread_mode_pender"]
 | 
			
		||||
    fn __thread_mode_pender(_context: OpaqueThreadContext) {
 | 
			
		||||
        unsafe { core::arch::asm!("sev") }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// TODO
 | 
			
		||||
    // Name pending
 | 
			
		||||
    #[derive(Default)] // Default enables Executor::new
 | 
			
		||||
    pub struct Context;
 | 
			
		||||
 | 
			
		||||
    impl ThreadContext for Context {
 | 
			
		||||
        fn context(&self) -> OpaqueThreadContext {
 | 
			
		||||
            OpaqueThreadContext(0)
 | 
			
		||||
        fn context(&self) -> PenderContext {
 | 
			
		||||
            usize::MAX
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn wait(&mut self) {
 | 
			
		||||
@ -35,7 +91,6 @@ mod thread {
 | 
			
		||||
    pub type Executor = crate::thread::ThreadModeExecutor<Context>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// None of this has to be public, I guess?
 | 
			
		||||
#[cfg(feature = "executor-interrupt")]
 | 
			
		||||
pub use interrupt::*;
 | 
			
		||||
#[cfg(feature = "executor-interrupt")]
 | 
			
		||||
@ -44,23 +99,14 @@ mod interrupt {
 | 
			
		||||
    use cortex_m::peripheral::NVIC;
 | 
			
		||||
 | 
			
		||||
    use crate::interrupt::InterruptContext;
 | 
			
		||||
    use crate::raw::OpaqueInterruptContext;
 | 
			
		||||
 | 
			
		||||
    #[derive(Clone, Copy)]
 | 
			
		||||
    struct CortexMInterruptContext(u16);
 | 
			
		||||
 | 
			
		||||
    unsafe impl cortex_m::interrupt::InterruptNumber for CortexMInterruptContext {
 | 
			
		||||
        fn number(self) -> u16 {
 | 
			
		||||
            self.0
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    use crate::raw::PenderContext;
 | 
			
		||||
 | 
			
		||||
    impl<T> InterruptContext for T
 | 
			
		||||
    where
 | 
			
		||||
        T: InterruptNumber,
 | 
			
		||||
    {
 | 
			
		||||
        fn context(&self) -> OpaqueInterruptContext {
 | 
			
		||||
            OpaqueInterruptContext(self.number() as usize)
 | 
			
		||||
        fn context(&self) -> PenderContext {
 | 
			
		||||
            self.number() as usize
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn enable(&self) {
 | 
			
		||||
@ -68,21 +114,6 @@ mod interrupt {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[export_name = "__interrupt_mode_pender"]
 | 
			
		||||
    fn __interrupt_mode_pender(interrupt: OpaqueInterruptContext) {
 | 
			
		||||
        let interrupt = CortexMInterruptContext(unsafe { core::mem::transmute::<_, usize>(interrupt) as u16 });
 | 
			
		||||
 | 
			
		||||
        // STIR is faster, but is only available in v7 and higher.
 | 
			
		||||
        #[cfg(not(armv6m))]
 | 
			
		||||
        {
 | 
			
		||||
            let mut nvic: NVIC = unsafe { core::mem::transmute(()) };
 | 
			
		||||
            nvic.request(interrupt);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #[cfg(armv6m)]
 | 
			
		||||
        NVIC::pend(interrupt);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// TODO
 | 
			
		||||
    // Type alias for backwards compatibility
 | 
			
		||||
    pub type InterruptExecutor = crate::interrupt::InterruptModeExecutor;
 | 
			
		||||
 | 
			
		||||
@ -10,14 +10,14 @@ mod thread {
 | 
			
		||||
    #[cfg(feature = "nightly")]
 | 
			
		||||
    pub use embassy_macros::main_riscv as main;
 | 
			
		||||
 | 
			
		||||
    use crate::raw::OpaqueThreadContext;
 | 
			
		||||
    use crate::raw::PenderContext;
 | 
			
		||||
    use crate::thread::ThreadContext;
 | 
			
		||||
 | 
			
		||||
    /// global atomic used to keep track of whether there is work to do since sev() is not available on RISCV
 | 
			
		||||
    static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false);
 | 
			
		||||
 | 
			
		||||
    #[export_name = "__thread_mode_pender"]
 | 
			
		||||
    fn __thread_mode_pender(_context: OpaqueThreadContext) {
 | 
			
		||||
    #[export_name = "__pender"]
 | 
			
		||||
    fn __thread_mode_pender(_context: PenderContext) {
 | 
			
		||||
        SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -27,8 +27,8 @@ mod thread {
 | 
			
		||||
    pub struct Context;
 | 
			
		||||
 | 
			
		||||
    impl ThreadContext for Context {
 | 
			
		||||
        fn context(&self) -> OpaqueThreadContext {
 | 
			
		||||
            OpaqueThreadContext(0)
 | 
			
		||||
        fn context(&self) -> PenderContext {
 | 
			
		||||
            0
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn wait(&mut self) {
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@ mod thread {
 | 
			
		||||
    #[cfg(feature = "nightly")]
 | 
			
		||||
    pub use embassy_macros::main_std as main;
 | 
			
		||||
 | 
			
		||||
    use crate::raw::OpaqueThreadContext;
 | 
			
		||||
    use crate::raw::PenderContext;
 | 
			
		||||
    use crate::thread::ThreadContext;
 | 
			
		||||
 | 
			
		||||
    /// TODO
 | 
			
		||||
@ -28,8 +28,8 @@ mod thread {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    impl ThreadContext for Context {
 | 
			
		||||
        fn context(&self) -> OpaqueThreadContext {
 | 
			
		||||
            OpaqueThreadContext(self.signaler as *const _ as usize)
 | 
			
		||||
        fn context(&self) -> PenderContext {
 | 
			
		||||
            self.signaler as *const _ as usize
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn wait(&mut self) {
 | 
			
		||||
@ -37,8 +37,8 @@ mod thread {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[export_name = "__thread_mode_pender"]
 | 
			
		||||
    fn __thread_mode_pender(context: OpaqueThreadContext) {
 | 
			
		||||
    #[export_name = "__pender"]
 | 
			
		||||
    fn __pender(context: PenderContext) {
 | 
			
		||||
        let signaler: &'static Signaler = unsafe { std::mem::transmute(context) };
 | 
			
		||||
        signaler.signal()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -14,11 +14,11 @@ mod thread {
 | 
			
		||||
    use wasm_bindgen::prelude::*;
 | 
			
		||||
 | 
			
		||||
    use crate::raw::util::UninitCell;
 | 
			
		||||
    use crate::raw::{OpaqueThreadContext, Pender};
 | 
			
		||||
    use crate::raw::PenderContext;
 | 
			
		||||
    use crate::{raw, Spawner};
 | 
			
		||||
 | 
			
		||||
    #[export_name = "__thread_mode_pender"]
 | 
			
		||||
    fn __thread_mode_pender(context: OpaqueThreadContext) {
 | 
			
		||||
    fn __thread_mode_pender(context: PenderContext) {
 | 
			
		||||
        let signaler: &'static WasmContext = unsafe { std::mem::transmute(context) };
 | 
			
		||||
        let _ = signaler.promise.then(unsafe { signaler.closure.as_mut() });
 | 
			
		||||
    }
 | 
			
		||||
@ -49,7 +49,7 @@ mod thread {
 | 
			
		||||
        pub fn new() -> Self {
 | 
			
		||||
            let ctx = &*Box::leak(Box::new(WasmContext::new()));
 | 
			
		||||
            Self {
 | 
			
		||||
                inner: raw::Executor::new(Pender::Thread(OpaqueThreadContext(ctx as *const _ as usize))),
 | 
			
		||||
                inner: raw::Executor::new(ctx as *const _ as usize),
 | 
			
		||||
                ctx,
 | 
			
		||||
                not_send: PhantomData,
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -8,14 +8,14 @@ mod thread {
 | 
			
		||||
    use core::marker::PhantomData;
 | 
			
		||||
    use core::sync::atomic::{AtomicBool, Ordering};
 | 
			
		||||
 | 
			
		||||
    use crate::raw::OpaqueThreadContext;
 | 
			
		||||
    use crate::raw::PenderContext;
 | 
			
		||||
    use crate::thread::ThreadContext;
 | 
			
		||||
 | 
			
		||||
    /// 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);
 | 
			
		||||
 | 
			
		||||
    #[export_name = "__thread_mode_pender"]
 | 
			
		||||
    fn __thread_mode_pender(_context: OpaqueThreadContext) {
 | 
			
		||||
    fn __thread_mode_pender(_context: PenderContext) {
 | 
			
		||||
        SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -25,8 +25,8 @@ mod thread {
 | 
			
		||||
    pub struct Context;
 | 
			
		||||
 | 
			
		||||
    impl ThreadContext for Context {
 | 
			
		||||
        fn context(&self) -> OpaqueThreadContext {
 | 
			
		||||
            OpaqueThreadContext(0)
 | 
			
		||||
        fn context(&self) -> PenderContext {
 | 
			
		||||
            0
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn wait(&mut self) {
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,7 @@ use core::mem::MaybeUninit;
 | 
			
		||||
 | 
			
		||||
use atomic_polyfill::{AtomicBool, Ordering};
 | 
			
		||||
 | 
			
		||||
use crate::raw::{self, OpaqueInterruptContext, Pender};
 | 
			
		||||
use crate::raw::{self, PenderContext};
 | 
			
		||||
 | 
			
		||||
/// Architecture-specific interface for an interrupt-mode executor. This trait describes what data
 | 
			
		||||
/// should be passed to the [`InterruptExecutor`]'s pender, and how to enable the interrupt that
 | 
			
		||||
@ -15,7 +15,7 @@ pub trait InterruptContext {
 | 
			
		||||
    /// A pointer-sized piece of data that is passed to the pender function.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Usually, the context contains the interrupt that should be used to wake the executor.
 | 
			
		||||
    fn context(&self) -> OpaqueInterruptContext;
 | 
			
		||||
    fn context(&self) -> PenderContext;
 | 
			
		||||
 | 
			
		||||
    /// Enabled the interrupt request.
 | 
			
		||||
    fn enable(&self);
 | 
			
		||||
@ -104,7 +104,7 @@ impl InterruptModeExecutor {
 | 
			
		||||
        unsafe {
 | 
			
		||||
            (&mut *self.executor.get())
 | 
			
		||||
                .as_mut_ptr()
 | 
			
		||||
                .write(raw::Executor::new(Pender::Interrupt(irq.context())))
 | 
			
		||||
                .write(raw::Executor::new(irq.context()))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let executor = unsafe { (&*self.executor.get()).assume_init_ref() };
 | 
			
		||||
 | 
			
		||||
@ -292,54 +292,20 @@ impl<F: Future + 'static, const N: usize> TaskPool<F, N> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Context given to the thread-mode executor's pender.
 | 
			
		||||
#[repr(transparent)]
 | 
			
		||||
#[derive(Clone, Copy)]
 | 
			
		||||
pub struct OpaqueThreadContext(pub(crate) usize);
 | 
			
		||||
pub type PenderContext = usize;
 | 
			
		||||
 | 
			
		||||
/// Context given to the interrupt-mode executor's pender.
 | 
			
		||||
#[derive(Clone, Copy)]
 | 
			
		||||
#[repr(transparent)]
 | 
			
		||||
pub struct OpaqueInterruptContext(pub(crate) usize);
 | 
			
		||||
 | 
			
		||||
/// Platform/architecture-specific action executed when an executor has pending work.
 | 
			
		||||
///
 | 
			
		||||
/// When a task within an executor is woken, the `Pender` is called. This does a
 | 
			
		||||
/// platform/architecture-specific action to signal there is pending work in the executor.
 | 
			
		||||
/// When this happens, you must arrange for [`Executor::poll`] to be called.
 | 
			
		||||
///
 | 
			
		||||
/// You can think of it as a waker, but for the whole executor.
 | 
			
		||||
#[derive(Clone, Copy)]
 | 
			
		||||
pub enum Pender {
 | 
			
		||||
    /// Pender for a thread-mode executor.
 | 
			
		||||
    #[cfg(feature = "executor-thread")]
 | 
			
		||||
    Thread(OpaqueThreadContext),
 | 
			
		||||
 | 
			
		||||
    /// Pender for an interrupt-mode executor.
 | 
			
		||||
    #[cfg(feature = "executor-interrupt")]
 | 
			
		||||
    Interrupt(OpaqueInterruptContext),
 | 
			
		||||
}
 | 
			
		||||
pub(crate) struct Pender(PenderContext);
 | 
			
		||||
 | 
			
		||||
unsafe impl Send for Pender {}
 | 
			
		||||
unsafe impl Sync for Pender {}
 | 
			
		||||
 | 
			
		||||
impl Pender {
 | 
			
		||||
    pub(crate) fn pend(self) {
 | 
			
		||||
        match self {
 | 
			
		||||
            #[cfg(feature = "executor-thread")]
 | 
			
		||||
            Pender::Thread(core_id) => {
 | 
			
		||||
        extern "Rust" {
 | 
			
		||||
                    fn __thread_mode_pender(core_id: OpaqueThreadContext);
 | 
			
		||||
                }
 | 
			
		||||
                unsafe { __thread_mode_pender(core_id) };
 | 
			
		||||
            }
 | 
			
		||||
            #[cfg(feature = "executor-interrupt")]
 | 
			
		||||
            Pender::Interrupt(interrupt) => {
 | 
			
		||||
                extern "Rust" {
 | 
			
		||||
                    fn __interrupt_mode_pender(interrupt: OpaqueInterruptContext);
 | 
			
		||||
                }
 | 
			
		||||
                unsafe { __interrupt_mode_pender(interrupt) };
 | 
			
		||||
            }
 | 
			
		||||
            fn __pender(context: PenderContext);
 | 
			
		||||
        }
 | 
			
		||||
        unsafe { __pender(self.0) };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -499,9 +465,9 @@ impl Executor {
 | 
			
		||||
    /// When the executor has work to do, it will call the [`Pender`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// See [`Executor`] docs for details on `Pender`.
 | 
			
		||||
    pub fn new(pender: Pender) -> Self {
 | 
			
		||||
    pub fn new(context: PenderContext) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            inner: SyncExecutor::new(pender),
 | 
			
		||||
            inner: SyncExecutor::new(Pender(context)),
 | 
			
		||||
            _not_sync: PhantomData,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -2,8 +2,8 @@
 | 
			
		||||
 | 
			
		||||
use core::marker::PhantomData;
 | 
			
		||||
 | 
			
		||||
use crate::raw::{OpaqueThreadContext, Pender};
 | 
			
		||||
use crate::{raw, Spawner};
 | 
			
		||||
use crate::raw::{self, PenderContext};
 | 
			
		||||
use crate::Spawner;
 | 
			
		||||
 | 
			
		||||
/// Architecture-specific interface for a thread-mode executor. This trait describes what the
 | 
			
		||||
/// executor should do when idle, and what data should be passed to its pender.
 | 
			
		||||
@ -13,7 +13,7 @@ pub trait ThreadContext: Sized {
 | 
			
		||||
    ///
 | 
			
		||||
    /// For example, on multi-core systems, this can be used to store the ID of the core that
 | 
			
		||||
    /// should be woken up.
 | 
			
		||||
    fn context(&self) -> OpaqueThreadContext;
 | 
			
		||||
    fn context(&self) -> PenderContext;
 | 
			
		||||
 | 
			
		||||
    /// Waits for the executor to be waken.
 | 
			
		||||
    ///
 | 
			
		||||
@ -50,7 +50,7 @@ impl<C: ThreadContext> ThreadModeExecutor<C> {
 | 
			
		||||
    /// Create a new Executor using the given thread context.
 | 
			
		||||
    pub fn with_context(context: C) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            inner: raw::Executor::new(Pender::Thread(context.context())),
 | 
			
		||||
            inner: raw::Executor::new(context.context()),
 | 
			
		||||
            context,
 | 
			
		||||
            not_send: PhantomData,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user