aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/raw/mod.rs
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-11-14 22:32:48 +0100
committerDario Nieuwenhuis <[email protected]>2023-11-15 18:43:27 +0100
commitbef9b7a8539c3dddb1cf6ab46db161f1ca56b1a1 (patch)
tree6d15736eec0029c13093bee120bd2189aa9537ac /embassy-executor/src/raw/mod.rs
parent50a983fd9b8f10fa5153757593e9f8cfccc902ac (diff)
executor: remove atomic-polyfill.
Diffstat (limited to 'embassy-executor/src/raw/mod.rs')
-rw-r--r--embassy-executor/src/raw/mod.rs58
1 files changed, 15 insertions, 43 deletions
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs
index 6d2c1c18a..ed0bedd25 100644
--- a/embassy-executor/src/raw/mod.rs
+++ b/embassy-executor/src/raw/mod.rs
@@ -7,7 +7,14 @@
7//! Using this module requires respecting subtle safety contracts. If you can, prefer using the safe 7//! Using this module requires respecting subtle safety contracts. If you can, prefer using the safe
8//! [executor wrappers](crate::Executor) and the [`embassy_executor::task`](embassy_macros::task) macro, which are fully safe. 8//! [executor wrappers](crate::Executor) and the [`embassy_executor::task`](embassy_macros::task) macro, which are fully safe.
9 9
10#[cfg_attr(target_has_atomic = "ptr", path = "run_queue_atomics.rs")]
11#[cfg_attr(not(target_has_atomic = "ptr"), path = "run_queue_critical_section.rs")]
10mod run_queue; 12mod run_queue;
13
14#[cfg_attr(target_has_atomic = "8", path = "state_atomics.rs")]
15#[cfg_attr(not(target_has_atomic = "8"), path = "state_critical_section.rs")]
16mod state;
17
11#[cfg(feature = "integrated-timers")] 18#[cfg(feature = "integrated-timers")]
12mod timer_queue; 19mod timer_queue;
13pub(crate) mod util; 20pub(crate) mod util;
@@ -21,7 +28,6 @@ use core::pin::Pin;
21use core::ptr::NonNull; 28use core::ptr::NonNull;
22use core::task::{Context, Poll}; 29use core::task::{Context, Poll};
23 30
24use atomic_polyfill::{AtomicU32, Ordering};
25#[cfg(feature = "integrated-timers")] 31#[cfg(feature = "integrated-timers")]
26use embassy_time::driver::{self, AlarmHandle}; 32use embassy_time::driver::{self, AlarmHandle};
27#[cfg(feature = "integrated-timers")] 33#[cfg(feature = "integrated-timers")]
@@ -30,21 +36,14 @@ use embassy_time::Instant;
30use rtos_trace::trace; 36use rtos_trace::trace;
31 37
32use self::run_queue::{RunQueue, RunQueueItem}; 38use self::run_queue::{RunQueue, RunQueueItem};
39use self::state::State;
33use self::util::{SyncUnsafeCell, UninitCell}; 40use self::util::{SyncUnsafeCell, UninitCell};
34pub use self::waker::task_from_waker; 41pub use self::waker::task_from_waker;
35use super::SpawnToken; 42use super::SpawnToken;
36 43
37/// Task is spawned (has a future)
38pub(crate) const STATE_SPAWNED: u32 = 1 << 0;
39/// Task is in the executor run queue
40pub(crate) const STATE_RUN_QUEUED: u32 = 1 << 1;
41/// Task is in the executor timer queue
42#[cfg(feature = "integrated-timers")]
43pub(crate) const STATE_TIMER_QUEUED: u32 = 1 << 2;
44
45/// Raw task header for use in task pointers. 44/// Raw task header for use in task pointers.
46pub(crate) struct TaskHeader { 45pub(crate) struct TaskHeader {
47 pub(crate) state: AtomicU32, 46 pub(crate) state: State,
48 pub(crate) run_queue_item: RunQueueItem, 47 pub(crate) run_queue_item: RunQueueItem,
49 pub(crate) executor: SyncUnsafeCell<Option<&'static SyncExecutor>>, 48 pub(crate) executor: SyncUnsafeCell<Option<&'static SyncExecutor>>,
50 poll_fn: SyncUnsafeCell<Option<unsafe fn(TaskRef)>>, 49 poll_fn: SyncUnsafeCell<Option<unsafe fn(TaskRef)>>,
@@ -116,7 +115,7 @@ impl<F: Future + 'static> TaskStorage<F> {
116 pub const fn new() -> Self { 115 pub const fn new() -> Self {
117 Self { 116 Self {
118 raw: TaskHeader { 117 raw: TaskHeader {
119 state: AtomicU32::new(0), 118 state: State::new(),
120 run_queue_item: RunQueueItem::new(), 119 run_queue_item: RunQueueItem::new(),
121 executor: SyncUnsafeCell::new(None), 120 executor: SyncUnsafeCell::new(None),
122 // Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss` 121 // Note: this is lazily initialized so that a static `TaskStorage` will go in `.bss`
@@ -161,7 +160,7 @@ impl<F: Future + 'static> TaskStorage<F> {
161 match future.poll(&mut cx) { 160 match future.poll(&mut cx) {
162 Poll::Ready(_) => { 161 Poll::Ready(_) => {
163 this.future.drop_in_place(); 162 this.future.drop_in_place();
164 this.raw.state.fetch_and(!STATE_SPAWNED, Ordering::AcqRel); 163 this.raw.state.despawn();
165 164
166 #[cfg(feature = "integrated-timers")] 165 #[cfg(feature = "integrated-timers")]
167 this.raw.expires_at.set(Instant::MAX); 166 this.raw.expires_at.set(Instant::MAX);
@@ -193,11 +192,7 @@ impl<F: Future + 'static> AvailableTask<F> {
193 /// 192 ///
194 /// This function returns `None` if a task has already been spawned and has not finished running. 193 /// This function returns `None` if a task has already been spawned and has not finished running.
195 pub fn claim(task: &'static TaskStorage<F>) -> Option<Self> { 194 pub fn claim(task: &'static TaskStorage<F>) -> Option<Self> {
196 task.raw 195 task.raw.state.spawn().then(|| Self { task })
197 .state
198 .compare_exchange(0, STATE_SPAWNED | STATE_RUN_QUEUED, Ordering::AcqRel, Ordering::Acquire)
199 .ok()
200 .map(|_| Self { task })
201 } 196 }
202 197
203 fn initialize_impl<S>(self, future: impl FnOnce() -> F) -> SpawnToken<S> { 198 fn initialize_impl<S>(self, future: impl FnOnce() -> F) -> SpawnToken<S> {
@@ -394,8 +389,7 @@ impl SyncExecutor {
394 #[cfg(feature = "integrated-timers")] 389 #[cfg(feature = "integrated-timers")]
395 task.expires_at.set(Instant::MAX); 390 task.expires_at.set(Instant::MAX);
396 391
397 let state = task.state.fetch_and(!STATE_RUN_QUEUED, Ordering::AcqRel); 392 if !task.state.run_dequeue() {
398 if state & STATE_SPAWNED == 0 {
399 // If task is not running, ignore it. This can happen in the following scenario: 393 // If task is not running, ignore it. This can happen in the following scenario:
400 // - Task gets dequeued, poll starts 394 // - Task gets dequeued, poll starts
401 // - While task is being polled, it gets woken. It gets placed in the queue. 395 // - While task is being polled, it gets woken. It gets placed in the queue.
@@ -546,18 +540,7 @@ impl Executor {
546/// You can obtain a `TaskRef` from a `Waker` using [`task_from_waker`]. 540/// You can obtain a `TaskRef` from a `Waker` using [`task_from_waker`].
547pub fn wake_task(task: TaskRef) { 541pub fn wake_task(task: TaskRef) {
548 let header = task.header(); 542 let header = task.header();
549 543 if header.state.run_enqueue() {
550 let res = header.state.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |state| {
551 // If already scheduled, or if not started,
552 if (state & STATE_RUN_QUEUED != 0) || (state & STATE_SPAWNED == 0) {
553 None
554 } else {
555 // Mark it as scheduled
556 Some(state | STATE_RUN_QUEUED)
557 }
558 });
559
560 if res.is_ok() {
561 // We have just marked the task as scheduled, so enqueue it. 544 // We have just marked the task as scheduled, so enqueue it.
562 unsafe { 545 unsafe {
563 let executor = header.executor.get().unwrap_unchecked(); 546 let executor = header.executor.get().unwrap_unchecked();
@@ -571,18 +554,7 @@ pub fn wake_task(task: TaskRef) {
571/// You can obtain a `TaskRef` from a `Waker` using [`task_from_waker`]. 554/// You can obtain a `TaskRef` from a `Waker` using [`task_from_waker`].
572pub fn wake_task_no_pend(task: TaskRef) { 555pub fn wake_task_no_pend(task: TaskRef) {
573 let header = task.header(); 556 let header = task.header();
574 557 if header.state.run_enqueue() {
575 let res = header.state.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |state| {
576 // If already scheduled, or if not started,
577 if (state & STATE_RUN_QUEUED != 0) || (state & STATE_SPAWNED == 0) {
578 None
579 } else {
580 // Mark it as scheduled
581 Some(state | STATE_RUN_QUEUED)
582 }
583 });
584
585 if res.is_ok() {
586 // We have just marked the task as scheduled, so enqueue it. 558 // We have just marked the task as scheduled, so enqueue it.
587 unsafe { 559 unsafe {
588 let executor = header.executor.get().unwrap_unchecked(); 560 let executor = header.executor.get().unwrap_unchecked();