From 4c4b12c307bf77516299eb73f9da00ef777b9814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 14 Aug 2023 15:16:40 +0200 Subject: [PATCH] Make PenderContext opaque --- embassy-executor/src/arch/cortex_m.rs | 6 ++++-- embassy-executor/src/arch/riscv32.rs | 2 +- embassy-executor/src/arch/std.rs | 2 +- embassy-executor/src/arch/wasm.rs | 2 +- embassy-executor/src/arch/xtensa.rs | 2 +- embassy-executor/src/raw/mod.rs | 25 ++++++++++++++++++++++--- 6 files changed, 30 insertions(+), 9 deletions(-) diff --git a/embassy-executor/src/arch/cortex_m.rs b/embassy-executor/src/arch/cortex_m.rs index 7f8a97ef1..439db0fc0 100644 --- a/embassy-executor/src/arch/cortex_m.rs +++ b/embassy-executor/src/arch/cortex_m.rs @@ -36,6 +36,7 @@ unsafe fn nvic_pend(irq: u16) { #[export_name = "__pender"] fn __pender(context: PenderContext) { unsafe { + let context: usize = core::mem::transmute(context); // 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 { @@ -56,6 +57,7 @@ fn __pender(_context: PenderContext) { #[export_name = "__pender"] fn __pender(context: PenderContext) { unsafe { + let context: usize = core::mem::transmute(context); // Safety: `context` is the same value we passed to `InterruptExecutor::start`, which must // be a valid interrupt request number. nvic_pend(context as u16) @@ -78,7 +80,7 @@ mod thread { impl ThreadContext for Context { fn context(&self) -> PenderContext { - usize::MAX + unsafe { core::mem::transmute(usize::MAX) } } fn wait(&mut self) { @@ -106,7 +108,7 @@ mod interrupt { T: InterruptNumber, { fn context(&self) -> PenderContext { - self.number() as usize + unsafe { core::mem::transmute(self.number() as usize) } } fn enable(&self) { diff --git a/embassy-executor/src/arch/riscv32.rs b/embassy-executor/src/arch/riscv32.rs index 886056e84..f76a4bcf6 100644 --- a/embassy-executor/src/arch/riscv32.rs +++ b/embassy-executor/src/arch/riscv32.rs @@ -28,7 +28,7 @@ mod thread { impl ThreadContext for Context { fn context(&self) -> PenderContext { - 0 + unsafe { core::mem::transmute(0) } } fn wait(&mut self) { diff --git a/embassy-executor/src/arch/std.rs b/embassy-executor/src/arch/std.rs index d2a069d1c..d55de118d 100644 --- a/embassy-executor/src/arch/std.rs +++ b/embassy-executor/src/arch/std.rs @@ -29,7 +29,7 @@ mod thread { impl ThreadContext for Context { fn context(&self) -> PenderContext { - self.signaler as *const _ as usize + unsafe { core::mem::transmute(self.signaler) } } fn wait(&mut self) { diff --git a/embassy-executor/src/arch/wasm.rs b/embassy-executor/src/arch/wasm.rs index 634f48d1a..452c3e394 100644 --- a/embassy-executor/src/arch/wasm.rs +++ b/embassy-executor/src/arch/wasm.rs @@ -49,7 +49,7 @@ mod thread { pub fn new() -> Self { let ctx = &*Box::leak(Box::new(WasmContext::new())); Self { - inner: raw::Executor::new(ctx as *const _ as usize), + inner: raw::Executor::new(unsafe { core::mem::transmute(ctx) }), ctx, not_send: PhantomData, } diff --git a/embassy-executor/src/arch/xtensa.rs b/embassy-executor/src/arch/xtensa.rs index 3986c6c19..1aea9f230 100644 --- a/embassy-executor/src/arch/xtensa.rs +++ b/embassy-executor/src/arch/xtensa.rs @@ -26,7 +26,7 @@ mod thread { impl ThreadContext for Context { fn context(&self) -> PenderContext { - 0 + unsafe { core::mem::transmute(0) } } fn wait(&mut self) { diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index a0a940e25..4a6e45535 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -292,10 +292,29 @@ impl TaskPool { } /// Context given to the thread-mode executor's pender. -pub type PenderContext = usize; - +#[repr(transparent)] #[derive(Clone, Copy)] -pub(crate) struct Pender(PenderContext); +pub struct PenderContext(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. +/// +/// Platform/architecture implementations must provide a function that can be referred to as: +/// +/// ```rust +/// use embassy_executor::raw::PenderContext; +/// +/// extern "Rust" { +/// fn __pender(context: PenderContext); +/// } +/// ``` +#[derive(Clone, Copy)] +pub struct Pender(PenderContext); unsafe impl Send for Pender {} unsafe impl Sync for Pender {}