aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src
diff options
context:
space:
mode:
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.rs110
6 files changed, 91 insertions, 24 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 f2c86d8e6..d8ac4893b 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 {
@@ -41,28 +40,101 @@ pub mod raw;
41mod spawner; 40mod spawner;
42pub use spawner::*; 41pub use spawner::*;
43 42
43mod config {
44 #![allow(unused)]
45 include!(concat!(env!("OUT_DIR"), "/config.rs"));
46}
47
44/// Implementation details for embassy macros. 48/// Implementation details for embassy macros.
45/// Do not use. Used for macros and HALs only. Not covered by semver guarantees. 49/// Do not use. Used for macros and HALs only. Not covered by semver guarantees.
46#[doc(hidden)] 50#[doc(hidden)]
51#[cfg(not(feature = "nightly"))]
47pub mod _export { 52pub mod _export {
48 #[cfg(feature = "rtos-trace")] 53 use core::alloc::Layout;
49 pub use rtos_trace::trace; 54 use core::cell::{Cell, UnsafeCell};
50 55 use core::future::Future;
51 /// Expands the given block of code when `embassy-executor` is compiled with 56 use core::mem::MaybeUninit;
52 /// the `rtos-trace-interrupt` feature. 57 use core::ptr::null_mut;
53 #[doc(hidden)] 58
54 #[macro_export] 59 use critical_section::{CriticalSection, Mutex};
55 #[cfg(feature = "rtos-trace-interrupt")] 60
56 macro_rules! rtos_trace_interrupt { 61 use crate::raw::TaskPool;
57 ($($tt:tt)*) => { $($tt)* }; 62
63 struct Arena<const N: usize> {
64 buf: UnsafeCell<MaybeUninit<[u8; N]>>,
65 ptr: Mutex<Cell<*mut u8>>,
58 } 66 }
59 67
60 /// Does not expand the given block of code when `embassy-executor` is 68 unsafe impl<const N: usize> Sync for Arena<N> {}
61 /// compiled without the `rtos-trace-interrupt` feature. 69 unsafe impl<const N: usize> Send for Arena<N> {}
62 #[doc(hidden)] 70
63 #[macro_export] 71 impl<const N: usize> Arena<N> {
64 #[cfg(not(feature = "rtos-trace-interrupt"))] 72 const fn new() -> Self {
65 macro_rules! rtos_trace_interrupt { 73 Self {
66 ($($tt:tt)*) => {}; 74 buf: UnsafeCell::new(MaybeUninit::uninit()),
75 ptr: Mutex::new(Cell::new(null_mut())),
76 }
77 }
78
79 fn alloc<T>(&'static self, cs: CriticalSection) -> &'static mut MaybeUninit<T> {
80 let layout = Layout::new::<T>();
81
82 let start = self.buf.get().cast::<u8>();
83 let end = unsafe { start.add(N) };
84
85 let mut ptr = self.ptr.borrow(cs).get();
86 if ptr.is_null() {
87 ptr = self.buf.get().cast::<u8>();
88 }
89
90 let bytes_left = (end as usize) - (ptr as usize);
91 let align_offset = (ptr as usize).next_multiple_of(layout.align()) - (ptr as usize);
92
93 if align_offset + layout.size() > bytes_left {
94 panic!("embassy-executor: task arena is full. You must increase the arena size, see the documentation for details: https://docs.embassy.dev/embassy-executor/");
95 }
96
97 let res = unsafe { ptr.add(align_offset) };
98 let ptr = unsafe { ptr.add(align_offset + layout.size()) };
99
100 self.ptr.borrow(cs).set(ptr);
101
102 unsafe { &mut *(res as *mut MaybeUninit<T>) }
103 }
104 }
105
106 static ARENA: Arena<{ crate::config::TASK_ARENA_SIZE }> = Arena::new();
107
108 pub struct TaskPoolRef {
109 // type-erased `&'static mut TaskPool<F, N>`
110 // Needed because statics can't have generics.
111 ptr: Mutex<Cell<*mut ()>>,
112 }
113 unsafe impl Sync for TaskPoolRef {}
114 unsafe impl Send for TaskPoolRef {}
115
116 impl TaskPoolRef {
117 pub const fn new() -> Self {
118 Self {
119 ptr: Mutex::new(Cell::new(null_mut())),
120 }
121 }
122
123 /// Get the pool for this ref, allocating it from the arena the first time.
124 ///
125 /// safety: for a given TaskPoolRef instance, must always call with the exact
126 /// same generic params.
127 pub unsafe fn get<F: Future, const N: usize>(&'static self) -> &'static TaskPool<F, N> {
128 critical_section::with(|cs| {
129 let ptr = self.ptr.borrow(cs);
130 if ptr.get().is_null() {
131 let pool = ARENA.alloc::<TaskPool<F, N>>(cs);
132 pool.write(TaskPool::new());
133 ptr.set(pool as *mut _ as _);
134 }
135
136 unsafe { &*(ptr.get() as *const _) }
137 })
138 }
67 } 139 }
68} 140}