aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-11-24 21:37:27 +0100
committerDario Nieuwenhuis <[email protected]>2023-11-24 23:52:09 +0100
commit171cdb94c7906670723b0965ca66d72a2352ac73 (patch)
tree92481f40c2ea3de70055e5b967629b5c93c4b298 /embassy-executor/src
parent1fbc150fd6392d8268aa35d15380c02e363c4eb8 (diff)
executor: add support for main/task macros in stable (allocates tasks in an arena)
Diffstat (limited to 'embassy-executor/src')
-rw-r--r--embassy-executor/src/arch/cortex_m.rs1
-rw-r--r--embassy-executor/src/arch/riscv32.rs1
-rw-r--r--embassy-executor/src/arch/std.rs1
-rw-r--r--embassy-executor/src/arch/wasm.rs1
-rw-r--r--embassy-executor/src/arch/xtensa.rs1
-rw-r--r--embassy-executor/src/lib.rs95
6 files changed, 92 insertions, 8 deletions
diff --git a/embassy-executor/src/arch/cortex_m.rs b/embassy-executor/src/arch/cortex_m.rs
index 55299c94f..4a6d58575 100644
--- a/embassy-executor/src/arch/cortex_m.rs
+++ b/embassy-executor/src/arch/cortex_m.rs
@@ -51,7 +51,6 @@ mod thread {
51 use core::arch::asm; 51 use core::arch::asm;
52 use core::marker::PhantomData; 52 use core::marker::PhantomData;
53 53
54 #[cfg(feature = "nightly")]
55 pub use embassy_macros::main_cortex_m as main; 54 pub use embassy_macros::main_cortex_m as main;
56 55
57 use crate::{raw, Spawner}; 56 use crate::{raw, Spawner};
diff --git a/embassy-executor/src/arch/riscv32.rs b/embassy-executor/src/arch/riscv32.rs
index 6814e7844..ca12c3403 100644
--- a/embassy-executor/src/arch/riscv32.rs
+++ b/embassy-executor/src/arch/riscv32.rs
@@ -7,7 +7,6 @@ pub use thread::*;
7mod thread { 7mod thread {
8 use core::marker::PhantomData; 8 use core::marker::PhantomData;
9 9
10 #[cfg(feature = "nightly")]
11 pub use embassy_macros::main_riscv as main; 10 pub use embassy_macros::main_riscv as main;
12 use portable_atomic::{AtomicBool, Ordering}; 11 use portable_atomic::{AtomicBool, Ordering};
13 12
diff --git a/embassy-executor/src/arch/std.rs b/embassy-executor/src/arch/std.rs
index 5b2f7e2e4..598bb0509 100644
--- a/embassy-executor/src/arch/std.rs
+++ b/embassy-executor/src/arch/std.rs
@@ -8,7 +8,6 @@ mod thread {
8 use std::marker::PhantomData; 8 use std::marker::PhantomData;
9 use std::sync::{Condvar, Mutex}; 9 use std::sync::{Condvar, Mutex};
10 10
11 #[cfg(feature = "nightly")]
12 pub use embassy_macros::main_std as main; 11 pub use embassy_macros::main_std as main;
13 12
14 use crate::{raw, Spawner}; 13 use crate::{raw, Spawner};
diff --git a/embassy-executor/src/arch/wasm.rs b/embassy-executor/src/arch/wasm.rs
index 15aed867a..3faa92575 100644
--- a/embassy-executor/src/arch/wasm.rs
+++ b/embassy-executor/src/arch/wasm.rs
@@ -8,7 +8,6 @@ mod thread {
8 8
9 use core::marker::PhantomData; 9 use core::marker::PhantomData;
10 10
11 #[cfg(feature = "nightly")]
12 pub use embassy_macros::main_wasm as main; 11 pub use embassy_macros::main_wasm as main;
13 use js_sys::Promise; 12 use js_sys::Promise;
14 use wasm_bindgen::prelude::*; 13 use wasm_bindgen::prelude::*;
diff --git a/embassy-executor/src/arch/xtensa.rs b/embassy-executor/src/arch/xtensa.rs
index d335594e2..6ed9f9e72 100644
--- a/embassy-executor/src/arch/xtensa.rs
+++ b/embassy-executor/src/arch/xtensa.rs
@@ -8,7 +8,6 @@ mod thread {
8 use core::marker::PhantomData; 8 use core::marker::PhantomData;
9 use core::sync::atomic::{AtomicBool, Ordering}; 9 use core::sync::atomic::{AtomicBool, Ordering};
10 10
11 #[cfg(feature = "nightly")]
12 pub use embassy_macros::main_riscv as main; 11 pub use embassy_macros::main_riscv as main;
13 12
14 use crate::{raw, Spawner}; 13 use crate::{raw, Spawner};
diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs
index 3b61b4ba5..ac7dbb035 100644
--- a/embassy-executor/src/lib.rs
+++ b/embassy-executor/src/lib.rs
@@ -1,5 +1,5 @@
1#![cfg_attr(not(any(feature = "arch-std", feature = "arch-wasm")), no_std)] 1#![cfg_attr(not(any(feature = "arch-std", feature = "arch-wasm")), no_std)]
2#![cfg_attr(all(feature = "nightly", feature = "arch-xtensa"), feature(asm_experimental_arch))] 2#![cfg_attr(feature = "arch-xtensa", feature(asm_experimental_arch))]
3#![allow(clippy::new_without_default)] 3#![allow(clippy::new_without_default)]
4#![doc = include_str!("../README.md")] 4#![doc = include_str!("../README.md")]
5#![warn(missing_docs)] 5#![warn(missing_docs)]
@@ -7,7 +7,6 @@
7// This mod MUST go first, so that the others see its macros. 7// This mod MUST go first, so that the others see its macros.
8pub(crate) mod fmt; 8pub(crate) mod fmt;
9 9
10#[cfg(feature = "nightly")]
11pub use embassy_macros::task; 10pub use embassy_macros::task;
12 11
13macro_rules! check_at_most_one { 12macro_rules! check_at_most_one {
@@ -44,4 +43,94 @@ pub use spawner::*;
44/// Implementation details for embassy macros. 43/// Implementation details for embassy macros.
45/// Do not use. Used for macros and HALs only. Not covered by semver guarantees. 44/// Do not use. Used for macros and HALs only. Not covered by semver guarantees.
46#[doc(hidden)] 45#[doc(hidden)]
47pub mod _export {} 46#[cfg(not(feature = "nightly"))]
47pub mod _export {
48 use core::alloc::Layout;
49 use core::cell::{Cell, UnsafeCell};
50 use core::future::Future;
51 use core::mem::MaybeUninit;
52 use core::ptr::null_mut;
53
54 use critical_section::{CriticalSection, Mutex};
55
56 use crate::raw::TaskPool;
57
58 struct Arena<const N: usize> {
59 buf: UnsafeCell<MaybeUninit<[u8; N]>>,
60 ptr: Mutex<Cell<*mut u8>>,
61 }
62
63 unsafe impl<const N: usize> Sync for Arena<N> {}
64 unsafe impl<const N: usize> Send for Arena<N> {}
65
66 impl<const N: usize> Arena<N> {
67 const fn new() -> Self {
68 Self {
69 buf: UnsafeCell::new(MaybeUninit::uninit()),
70 ptr: Mutex::new(Cell::new(null_mut())),
71 }
72 }
73
74 fn alloc<T>(&'static self, cs: CriticalSection) -> &'static mut MaybeUninit<T> {
75 let layout = Layout::new::<T>();
76
77 let start = self.buf.get().cast::<u8>();
78 let end = unsafe { start.add(N) };
79
80 let mut ptr = self.ptr.borrow(cs).get();
81 if ptr.is_null() {
82 ptr = self.buf.get().cast::<u8>();
83 }
84
85 let bytes_left = (end as usize) - (ptr as usize);
86 let align_offset = (ptr as usize).next_multiple_of(layout.align()) - (ptr as usize);
87
88 if align_offset + layout.size() > bytes_left {
89 panic!("arena full");
90 }
91
92 let res = unsafe { ptr.add(align_offset) };
93 let ptr = unsafe { ptr.add(align_offset + layout.size()) };
94
95 self.ptr.borrow(cs).set(ptr);
96
97 unsafe { &mut *(res as *mut MaybeUninit<T>) }
98 }
99 }
100
101 const ARENA_SIZE: usize = 16 * 1024;
102 static ARENA: Arena<ARENA_SIZE> = Arena::new();
103
104 pub struct TaskPoolRef {
105 // type-erased `&'static mut TaskPool<F, N>`
106 // Needed because statics can't have generics.
107 ptr: Mutex<Cell<*mut ()>>,
108 }
109 unsafe impl Sync for TaskPoolRef {}
110 unsafe impl Send for TaskPoolRef {}
111
112 impl TaskPoolRef {
113 pub const fn new() -> Self {
114 Self {
115 ptr: Mutex::new(Cell::new(null_mut())),
116 }
117 }
118
119 /// Get the pool for this ref, allocating it from the arena the first time.
120 ///
121 /// safety: for a given TaskPoolRef instance, must always call with the exact
122 /// same generic params.
123 pub unsafe fn get<F: Future, const N: usize>(&'static self) -> &'static TaskPool<F, N> {
124 critical_section::with(|cs| {
125 let ptr = self.ptr.borrow(cs);
126 if ptr.get().is_null() {
127 let pool = ARENA.alloc::<TaskPool<F, N>>(cs);
128 pool.write(TaskPool::new());
129 ptr.set(pool as *mut _ as _);
130 }
131
132 unsafe { &*(ptr.get() as *const _) }
133 })
134 }
135 }
136}