embassy_supervisor/
graph_ref.rs1use crate::TaskNode;
2
3#[cfg(feature = "trace-self")]
4static SELF_NODE_CFG: crate::NodeCfg = crate::NodeCfg::new("supervisor", crate::Mode::Pause, None);
5
6pub struct GraphRef {
8 nodes: &'static [Option<&'static TaskNode>],
9 #[cfg(feature = "trace")]
10 chain: Chain,
11 #[cfg(feature = "trace-self")]
12 self_node: Option<TaskNode>,
13}
14
15impl GraphRef {
16 pub const fn new(nodes: &'static [Option<&'static TaskNode>]) -> Self {
18 Self {
19 nodes,
20 #[cfg(feature = "trace")]
21 chain: Chain::new(),
22 #[cfg(feature = "trace-self")]
23 self_node: Some(TaskNode::new(&SELF_NODE_CFG, false)),
24 }
25 }
26
27 pub const fn nodes(&self) -> &'static [Option<&'static TaskNode>] {
29 self.nodes
30 }
31
32 #[cfg(feature = "trace-self")]
33 pub const fn self_node(&'static self) -> Option<&'static TaskNode> {
35 self.self_node.as_ref()
36 }
37}
38
39#[cfg(feature = "data-deps")]
40pub(crate) static NO_GRAPH: GraphRef = GraphRef {
41 nodes: &[],
42 #[cfg(feature = "trace")]
43 chain: Chain::new(),
44 #[cfg(feature = "trace-self")]
45 self_node: None,
46};
47
48#[cfg(feature = "trace")]
49mod chain {
50 use core::cell::Cell;
51 use core::sync::atomic::Ordering;
52
53 use embassy_sync::blocking_mutex::Mutex;
54 use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
55 use portable_atomic::AtomicBool;
56
57 use super::GraphRef;
58
59 type Link = Mutex<CriticalSectionRawMutex, Cell<Option<&'static GraphRef>>>;
60
61 const fn unlinked() -> Link {
62 Mutex::new(Cell::new(None))
63 }
64
65 pub(super) struct Chain {
67 next: Link,
68 linked: AtomicBool,
72 }
73
74 impl Chain {
75 pub(super) const fn new() -> Self {
76 Self {
77 next: unlinked(),
78 linked: AtomicBool::new(false),
79 }
80 }
81 }
82
83 static HEAD: Link = unlinked();
85
86 impl GraphRef {
87 pub fn register(&'static self) {
92 if self.chain.linked.swap(true, Ordering::AcqRel) {
93 return;
94 }
95 HEAD.lock(|head| {
96 self.chain.next.lock(|next| next.set(head.get()));
97 head.set(Some(self));
98 });
99 }
100 }
101
102 pub fn graphs() -> Graphs {
104 Graphs {
105 next: HEAD.lock(Cell::get),
106 }
107 }
108
109 pub struct Graphs {
111 next: Option<&'static GraphRef>,
112 }
113
114 impl Iterator for Graphs {
115 type Item = &'static GraphRef;
116
117 fn next(&mut self) -> Option<Self::Item> {
118 let cur = self.next?;
119 self.next = cur.chain.next.lock(Cell::get);
120 Some(cur)
121 }
122 }
123}
124
125#[cfg(feature = "trace")]
126use chain::Chain;
127#[cfg(feature = "trace")]
128pub use chain::{Graphs, graphs};