1#[cfg(all(feature = "multi-core", feature = "no-atomic-cas"))]
4compile_error!(
5 "The `multi-core` feature requires atomic-cas operations to be available on the target. Enable the `atomic-cas` feature."
6);
7
8#[cfg(all(feature = "no-atomic-cas", not(target_has_atomic = "8")))]
9compile_error!(
10 "The `atomic-cas` feature requires the target to have atomic operations on at least 8-bit integers."
11);
12
13#[allow(unused_imports)]
14pub use core::sync::atomic::Ordering;
15
16#[inline(always)]
17pub fn irq_free<T>(f: impl FnOnce() -> T) -> T {
18 let state = hal::asm::disable_irq_save();
19 let result = f();
20 hal::asm::enable_irq_restr(state);
21
22 result
23}
24
25#[cfg(any(feature = "no-atomic-cas", not(target_has_atomic = "64")))]
27use core::cell::UnsafeCell;
28
29#[cfg(all(feature = "no-atomic-cas"))]
30pub struct AtomicU8 {
32 value: UnsafeCell<u8>,
33}
34
35#[allow(unused_imports)]
36#[cfg(not(all(feature = "no-atomic-cas")))]
37pub use core::sync::atomic::AtomicU8;
38
39#[cfg(all(feature = "no-atomic-cas"))]
40impl AtomicU8 {
41 pub const fn new(value: u8) -> Self {
43 Self {
44 value: UnsafeCell::new(value),
45 }
46 }
47
48 pub fn load(&self, _: Ordering) -> u8 {
50 todo!("Implement atomic load for u8");
51 }
52
53 pub fn store(&self, value: u8, _: Ordering) {
55 todo!("Implement atomic store for u8");
56 }
57
58 #[allow(dead_code)]
60 pub fn compare_exchange(
61 &self,
62 current: u8,
63 new: u8,
64 _: Ordering,
65 _: Ordering,
66 ) -> Result<u8, u8> {
67 todo!("Implement atomic compare_exchange for u8");
68 }
69
70 pub fn fetch_update<F>(&self, _: Ordering, _: Ordering, f: F) -> Result<u8, u8>
72 where
73 F: FnMut(u8) -> Option<u8>,
74 {
75 todo!("Implement atomic fetch_update for u8");
76 }
77}
78
79#[allow(unused_imports)]
80#[cfg(not(all(feature = "no-atomic-cas")))]
81pub use core::sync::atomic::AtomicBool;
82
83#[cfg(all(feature = "no-atomic-cas"))]
84pub struct AtomicBool {
86 value: UnsafeCell<bool>,
87}
88
89#[cfg(all(feature = "no-atomic-cas"))]
90impl AtomicBool {
91 pub const fn new(value: bool) -> Self {
93 Self {
94 value: UnsafeCell::new(value),
95 }
96 }
97
98 pub fn load(&self, _: Ordering) -> bool {
100 todo!("Implement atomic load for bool");
101 }
102
103 pub fn store(&self, value: bool, _: Ordering) {
105 todo!("Implement atomic store for bool");
106 }
107
108 pub fn compare_exchange(
110 &self,
111 current: bool,
112 new: bool,
113 _: Ordering,
114 _: Ordering,
115 ) -> Result<bool, bool> {
116 todo!("Implement atomic compare_exchange for bool");
117 }
118}
119
120#[allow(unused_imports)]
122#[cfg(target_has_atomic = "64")]
123pub use core::sync::atomic::AtomicU64;
124
125#[cfg(not(target_has_atomic = "64"))]
126pub struct AtomicU64 {
128 value: UnsafeCell<u64>,
129}
130
131#[cfg(not(target_has_atomic = "64"))]
132unsafe impl Sync for AtomicU64 {}
133
134#[cfg(not(target_has_atomic = "64"))]
135#[allow(dead_code)]
136impl AtomicU64 {
137 pub const fn new(value: u64) -> Self {
139 Self {
140 value: UnsafeCell::new(value),
141 }
142 }
143
144 pub fn load(&self, _: Ordering) -> u64 {
146 irq_free(|| {
147 unsafe { *self.value.get() }
149 })
150 }
151
152 pub fn store(&self, value: u64, _: Ordering) {
154 irq_free(|| {
155 unsafe {
157 *self.value.get() = value;
158 }
159 });
160 }
161
162 pub fn compare_exchange(
164 &self,
165 current: u64,
166 new: u64,
167 _: Ordering,
168 _: Ordering,
169 ) -> Result<u64, u64> {
170 irq_free(|| {
171 unsafe {
173 let value = self.value.get();
174 if *value == current {
175 *value = new;
176 Ok(current)
177 } else {
178 Err(*value)
179 }
180 }
181 })
182 }
183
184 pub fn fetch_add(&self, value: u64, _: Ordering) -> u64 {
186 irq_free(|| {
187 unsafe {
189 let ptr = self.value.get();
190 let old = *ptr;
191 *ptr = old.wrapping_add(value);
192 old
193 }
194 })
195 }
196
197 #[allow(dead_code)]
199 pub fn fetch_update<F>(&self, _: Ordering, _: Ordering, mut f: F) -> Result<u64, u64>
200 where
201 F: FnMut(u64) -> Option<u64>,
202 {
203 irq_free(|| {
204 unsafe {
206 let ptr = self.value.get();
207 let old = *ptr;
208 if let Some(new) = f(old) {
209 *ptr = new;
210 Ok(old)
211 } else {
212 Err(old)
213 }
214 }
215 })
216 }
217}