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
13use crate::hal;
14
15#[allow(unused_imports)]
16pub use core::sync::atomic::Ordering;
17
18#[inline(always)]
19pub fn irq_free<T>(f: impl FnOnce() -> T) -> T {
20 let state = hal::asm::disable_irq_save();
21 let result = f();
22 hal::asm::enable_irq_restr(state);
23
24 result
25}
26
27#[cfg(any(feature = "no-atomic-cas", not(target_has_atomic = "64")))]
29use core::cell::UnsafeCell;
30
31#[cfg(all(feature = "no-atomic-cas"))]
32pub struct AtomicU8 {
34 value: UnsafeCell<u8>,
35}
36
37#[allow(unused_imports)]
38#[cfg(not(all(feature = "no-atomic-cas")))]
39pub use core::sync::atomic::AtomicU8;
40
41#[cfg(all(feature = "no-atomic-cas"))]
42impl AtomicU8 {
43 pub const fn new(value: u8) -> Self {
45 Self {
46 value: UnsafeCell::new(value),
47 }
48 }
49
50 pub fn load(&self, _: Ordering) -> u8 {
52 todo!("Implement atomic load for u8");
53 }
54
55 pub fn store(&self, value: u8, _: Ordering) {
57 todo!("Implement atomic store for u8");
58 }
59
60 #[allow(dead_code)]
62 pub fn compare_exchange(
63 &self,
64 current: u8,
65 new: u8,
66 _: Ordering,
67 _: Ordering,
68 ) -> Result<u8, u8> {
69 todo!("Implement atomic compare_exchange for u8");
70 }
71
72 pub fn fetch_update<F>(&self, _: Ordering, _: Ordering, f: F) -> Result<u8, u8>
74 where
75 F: FnMut(u8) -> Option<u8>,
76 {
77 todo!("Implement atomic fetch_update for u8");
78 }
79}
80
81#[allow(unused_imports)]
82#[cfg(not(all(feature = "no-atomic-cas")))]
83pub use core::sync::atomic::AtomicBool;
84
85#[cfg(all(feature = "no-atomic-cas"))]
86pub struct AtomicBool {
88 value: UnsafeCell<bool>,
89}
90
91#[cfg(all(feature = "no-atomic-cas"))]
92impl AtomicBool {
93 pub const fn new(value: bool) -> Self {
95 Self {
96 value: UnsafeCell::new(value),
97 }
98 }
99
100 pub fn load(&self, _: Ordering) -> bool {
102 todo!("Implement atomic load for bool");
103 }
104
105 pub fn store(&self, value: bool, _: Ordering) {
107 todo!("Implement atomic store for bool");
108 }
109
110 pub fn compare_exchange(
112 &self,
113 current: bool,
114 new: bool,
115 _: Ordering,
116 _: Ordering,
117 ) -> Result<bool, bool> {
118 todo!("Implement atomic compare_exchange for bool");
119 }
120}
121
122#[allow(unused_imports)]
124#[cfg(target_has_atomic = "64")]
125pub use core::sync::atomic::AtomicU64;
126
127#[cfg(not(target_has_atomic = "64"))]
128pub struct AtomicU64 {
130 value: UnsafeCell<u64>,
131}
132
133#[cfg(not(target_has_atomic = "64"))]
134unsafe impl Sync for AtomicU64 {}
135
136#[cfg(not(target_has_atomic = "64"))]
137#[allow(dead_code)]
138impl AtomicU64 {
139 pub const fn new(value: u64) -> Self {
141 Self {
142 value: UnsafeCell::new(value),
143 }
144 }
145
146 pub fn load(&self, _: Ordering) -> u64 {
148 irq_free(|| {
149 unsafe { *self.value.get() }
151 })
152 }
153
154 pub fn store(&self, value: u64, _: Ordering) {
156 irq_free(|| {
157 unsafe {
159 *self.value.get() = value;
160 }
161 });
162 }
163
164 pub fn compare_exchange(
166 &self,
167 current: u64,
168 new: u64,
169 _: Ordering,
170 _: Ordering,
171 ) -> Result<u64, u64> {
172 irq_free(|| {
173 unsafe {
175 let value = self.value.get();
176 if *value == current {
177 *value = new;
178 Ok(current)
179 } else {
180 Err(*value)
181 }
182 }
183 })
184 }
185
186 pub fn fetch_add(&self, value: u64, _: Ordering) -> u64 {
188 irq_free(|| {
189 unsafe {
191 let ptr = self.value.get();
192 let old = *ptr;
193 *ptr = old.wrapping_add(value);
194 old
195 }
196 })
197 }
198
199 #[allow(dead_code)]
201 pub fn fetch_update<F>(&self, _: Ordering, _: Ordering, mut f: F) -> Result<u64, u64>
202 where
203 F: FnMut(u64) -> Option<u64>,
204 {
205 irq_free(|| {
206 unsafe {
208 let ptr = self.value.get();
209 let old = *ptr;
210 if let Some(new) = f(old) {
211 *ptr = new;
212 Ok(old)
213 } else {
214 Err(old)
215 }
216 }
217 })
218 }
219}