aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor
diff options
context:
space:
mode:
authorDániel Buga <[email protected]>2024-12-07 14:45:16 +0100
committerDániel Buga <[email protected]>2024-12-17 17:53:12 +0100
commitedb8f21a741358f7c80b744f008f1e5acc77b429 (patch)
tree3fbddca087b439a0191cfe7c55fd5267bb80de16 /embassy-executor
parentc1120c7138c10a4cbdadb75d47eb23be9b65c231 (diff)
Take critical section instead of unsafe
Diffstat (limited to 'embassy-executor')
-rw-r--r--embassy-executor/src/raw/mod.rs9
-rw-r--r--embassy-executor/src/raw/run_queue_atomics.rs11
-rw-r--r--embassy-executor/src/raw/run_queue_critical_section.rs16
3 files changed, 22 insertions, 14 deletions
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs
index 6503b556f..c79fdae60 100644
--- a/embassy-executor/src/raw/mod.rs
+++ b/embassy-executor/src/raw/mod.rs
@@ -411,15 +411,6 @@ impl SyncExecutor {
411 self.run_queue.dequeue_all(|p| { 411 self.run_queue.dequeue_all(|p| {
412 let task = p.header(); 412 let task = p.header();
413 413
414 if !task.state.run_dequeue() {
415 // If task is not running, ignore it. This can happen in the following scenario:
416 // - Task gets dequeued, poll starts
417 // - While task is being polled, it gets woken. It gets placed in the queue.
418 // - Task poll finishes, returning done=true
419 // - RUNNING bit is cleared, but the task is already in the queue.
420 return;
421 }
422
423 #[cfg(feature = "trace")] 414 #[cfg(feature = "trace")]
424 trace::task_exec_begin(self, &p); 415 trace::task_exec_begin(self, &p);
425 416
diff --git a/embassy-executor/src/raw/run_queue_atomics.rs b/embassy-executor/src/raw/run_queue_atomics.rs
index efdafdff0..aad90d767 100644
--- a/embassy-executor/src/raw/run_queue_atomics.rs
+++ b/embassy-executor/src/raw/run_queue_atomics.rs
@@ -81,7 +81,16 @@ impl RunQueue {
81 // safety: there are no concurrent accesses to `next` 81 // safety: there are no concurrent accesses to `next`
82 next = unsafe { task.header().run_queue_item.next.get() }; 82 next = unsafe { task.header().run_queue_item.next.get() };
83 83
84 on_task(task); 84 let run_task = task.header().state.run_dequeue();
85
86 if run_task {
87 // If task is not running, ignore it. This can happen in the following scenario:
88 // - Task gets dequeued, poll starts
89 // - While task is being polled, it gets woken. It gets placed in the queue.
90 // - Task poll finishes, returning done=true
91 // - RUNNING bit is cleared, but the task is already in the queue.
92 on_task(task);
93 }
85 } 94 }
86 } 95 }
87} 96}
diff --git a/embassy-executor/src/raw/run_queue_critical_section.rs b/embassy-executor/src/raw/run_queue_critical_section.rs
index 90f09e8c8..4f1b2855a 100644
--- a/embassy-executor/src/raw/run_queue_critical_section.rs
+++ b/embassy-executor/src/raw/run_queue_critical_section.rs
@@ -63,11 +63,19 @@ impl RunQueue {
63 // If the task re-enqueues itself, the `next` pointer will get overwritten. 63 // If the task re-enqueues itself, the `next` pointer will get overwritten.
64 // Therefore, first read the next pointer, and only then process the task. 64 // Therefore, first read the next pointer, and only then process the task.
65 65
66 // safety: we know if the task is enqueued, no one else will touch the `next` pointer. 66 let run_task = critical_section::with(|cs| {
67 let cs = unsafe { CriticalSection::new() }; 67 next = task.header().run_queue_item.next.borrow(cs).get();
68 next = task.header().run_queue_item.next.borrow(cs).get(); 68 task.header().state.run_dequeue(cs)
69 });
69 70
70 on_task(task); 71 if run_task {
72 // If task is not running, ignore it. This can happen in the following scenario:
73 // - Task gets dequeued, poll starts
74 // - While task is being polled, it gets woken. It gets placed in the queue.
75 // - Task poll finishes, returning done=true
76 // - RUNNING bit is cleared, but the task is already in the queue.
77 on_task(task);
78 }
71 } 79 }
72 } 80 }
73} 81}