aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/raw
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-executor/src/raw')
-rw-r--r--embassy-executor/src/raw/mod.rs70
-rw-r--r--embassy-executor/src/raw/trace.rs74
2 files changed, 72 insertions, 72 deletions
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs
index b4adfe01b..882e4605b 100644
--- a/embassy-executor/src/raw/mod.rs
+++ b/embassy-executor/src/raw/mod.rs
@@ -97,76 +97,6 @@ pub(crate) struct TaskHeader {
97 all_tasks_next: AtomicPtr<TaskHeader>, 97 all_tasks_next: AtomicPtr<TaskHeader>,
98} 98}
99 99
100/// A thread-safe tracker for all tasks in the system
101///
102/// This struct uses an intrusive linked list approach to track all tasks
103/// without additional memory allocations. It maintains a global list of
104/// tasks that can be traversed to find all currently existing tasks.
105#[cfg(feature = "trace")]
106pub struct TaskTracker {
107 head: AtomicPtr<TaskHeader>,
108}
109
110#[cfg(feature = "trace")]
111impl TaskTracker {
112 /// Creates a new empty task tracker
113 ///
114 /// Initializes a tracker with no tasks in its list.
115 pub const fn new() -> Self {
116 Self {
117 head: AtomicPtr::new(core::ptr::null_mut()),
118 }
119 }
120
121 /// Adds a task to the tracker
122 ///
123 /// This method inserts a task at the head of the intrusive linked list.
124 /// The operation is thread-safe and lock-free, using atomic operations
125 /// to ensure consistency even when called from different contexts.
126 ///
127 /// # Arguments
128 /// * `task` - The task reference to add to the tracker
129 pub fn add(&self, task: TaskRef) {
130 let task_ptr = task.as_ptr() as *mut TaskHeader;
131
132 loop {
133 let current_head = self.head.load(Ordering::Acquire);
134 unsafe {
135 (*task_ptr).all_tasks_next.store(current_head, Ordering::Relaxed);
136 }
137
138 if self
139 .head
140 .compare_exchange(current_head, task_ptr, Ordering::Release, Ordering::Relaxed)
141 .is_ok()
142 {
143 break;
144 }
145 }
146 }
147
148 /// Performs an operation on each task in the tracker
149 ///
150 /// This method traverses the entire list of tasks and calls the provided
151 /// function for each task. This allows inspecting or processing all tasks
152 /// in the system without modifying the tracker's structure.
153 ///
154 /// # Arguments
155 /// * `f` - A function to call for each task in the tracker
156 pub fn for_each<F>(&self, mut f: F)
157 where
158 F: FnMut(TaskRef),
159 {
160 let mut current = self.head.load(Ordering::Acquire);
161 while !current.is_null() {
162 let task = unsafe { TaskRef::from_ptr(current) };
163 f(task);
164
165 current = unsafe { (*current).all_tasks_next.load(Ordering::Acquire) };
166 }
167 }
168}
169
170/// This is essentially a `&'static TaskStorage<F>` where the type of the future has been erased. 100/// This is essentially a `&'static TaskStorage<F>` where the type of the future has been erased.
171#[derive(Clone, Copy, PartialEq)] 101#[derive(Clone, Copy, PartialEq)]
172pub struct TaskRef { 102pub struct TaskRef {
diff --git a/embassy-executor/src/raw/trace.rs b/embassy-executor/src/raw/trace.rs
index eb960f721..b59da0526 100644
--- a/embassy-executor/src/raw/trace.rs
+++ b/embassy-executor/src/raw/trace.rs
@@ -82,11 +82,11 @@
82#![allow(unused)] 82#![allow(unused)]
83 83
84use core::cell::UnsafeCell; 84use core::cell::UnsafeCell;
85use core::sync::atomic::{AtomicUsize, Ordering}; 85use core::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
86 86
87use rtos_trace::TaskInfo; 87use rtos_trace::TaskInfo;
88 88
89use crate::raw::{SyncExecutor, TaskHeader, TaskRef, TaskTracker}; 89use crate::raw::{SyncExecutor, TaskHeader, TaskRef};
90use crate::spawner::{SpawnError, SpawnToken, Spawner}; 90use crate::spawner::{SpawnError, SpawnToken, Spawner};
91 91
92/// Extension trait adding tracing capabilities to the Spawner 92/// Extension trait adding tracing capabilities to the Spawner
@@ -139,6 +139,76 @@ impl TraceExt for Spawner {
139#[cfg(feature = "trace")] 139#[cfg(feature = "trace")]
140pub static TASK_TRACKER: TaskTracker = TaskTracker::new(); 140pub static TASK_TRACKER: TaskTracker = TaskTracker::new();
141 141
142/// A thread-safe tracker for all tasks in the system
143///
144/// This struct uses an intrusive linked list approach to track all tasks
145/// without additional memory allocations. It maintains a global list of
146/// tasks that can be traversed to find all currently existing tasks.
147#[cfg(feature = "trace")]
148pub struct TaskTracker {
149 head: AtomicPtr<TaskHeader>,
150}
151
152#[cfg(feature = "trace")]
153impl TaskTracker {
154 /// Creates a new empty task tracker
155 ///
156 /// Initializes a tracker with no tasks in its list.
157 pub const fn new() -> Self {
158 Self {
159 head: AtomicPtr::new(core::ptr::null_mut()),
160 }
161 }
162
163 /// Adds a task to the tracker
164 ///
165 /// This method inserts a task at the head of the intrusive linked list.
166 /// The operation is thread-safe and lock-free, using atomic operations
167 /// to ensure consistency even when called from different contexts.
168 ///
169 /// # Arguments
170 /// * `task` - The task reference to add to the tracker
171 pub fn add(&self, task: TaskRef) {
172 let task_ptr = task.as_ptr() as *mut TaskHeader;
173
174 loop {
175 let current_head = self.head.load(Ordering::Acquire);
176 unsafe {
177 (*task_ptr).all_tasks_next.store(current_head, Ordering::Relaxed);
178 }
179
180 if self
181 .head
182 .compare_exchange(current_head, task_ptr, Ordering::Release, Ordering::Relaxed)
183 .is_ok()
184 {
185 break;
186 }
187 }
188 }
189
190 /// Performs an operation on each task in the tracker
191 ///
192 /// This method traverses the entire list of tasks and calls the provided
193 /// function for each task. This allows inspecting or processing all tasks
194 /// in the system without modifying the tracker's structure.
195 ///
196 /// # Arguments
197 /// * `f` - A function to call for each task in the tracker
198 pub fn for_each<F>(&self, mut f: F)
199 where
200 F: FnMut(TaskRef),
201 {
202 let mut current = self.head.load(Ordering::Acquire);
203 while !current.is_null() {
204 let task = unsafe { TaskRef::from_ptr(current) };
205 f(task);
206
207 current = unsafe { (*current).all_tasks_next.load(Ordering::Acquire) };
208 }
209 }
210}
211
142#[cfg(not(feature = "rtos-trace"))] 212#[cfg(not(feature = "rtos-trace"))]
143extern "Rust" { 213extern "Rust" {
144 /// This callback is called when the executor begins polling. This will always 214 /// This callback is called when the executor begins polling. This will always