|
1 |
| -#![cfg_attr(docsrs, feature(doc_cfg))] |
2 | 1 | #![no_std]
|
3 |
| -#![cfg_attr(target_arch = "avr", feature(llvm_asm))] |
4 |
| -#![cfg_attr(target_arch = "avr", feature(extended_key_value_attributes))] |
5 | 2 | #![doc = include_str!("../README.md")]
|
6 | 3 |
|
7 | 4 | pub use bare_metal::CriticalSection;
|
@@ -58,141 +55,47 @@ pub fn with<R>(f: impl FnOnce(CriticalSection) -> R) -> R {
|
58 | 55 | }
|
59 | 56 | }
|
60 | 57 |
|
61 |
| -cfg_if::cfg_if! { |
62 |
| - if #[cfg(feature = "custom-impl")] { |
63 |
| - /// Methods required for a custom critical section implementation. |
64 |
| - /// |
65 |
| - /// This trait is not intended to be used except when implementing a custom critical section. |
66 |
| - /// |
67 |
| - /// Implementations must uphold the contract specified in [`crate::acquire`] and [`crate::release`]. |
68 |
| - #[cfg_attr(docsrs, doc(cfg(feature = "custom-impl")))] |
69 |
| - pub unsafe trait Impl { |
70 |
| - /// Acquire the critical section. |
71 |
| - unsafe fn acquire() -> u8; |
72 |
| - /// Release the critical section. |
73 |
| - unsafe fn release(token: u8); |
74 |
| - } |
75 |
| - |
76 |
| - /// Set the custom critical section implementation. |
77 |
| - /// |
78 |
| - /// # Example |
79 |
| - /// |
80 |
| - /// ``` |
81 |
| - /// struct MyCriticalSection; |
82 |
| - /// critical_section::custom_impl!(MyCriticalSection); |
83 |
| - /// |
84 |
| - /// unsafe impl critical_section::Impl for MyCriticalSection { |
85 |
| - /// unsafe fn acquire() -> u8 { |
86 |
| - /// // ... |
87 |
| - /// # return 0 |
88 |
| - /// } |
89 |
| - /// |
90 |
| - /// unsafe fn release(token: u8) { |
91 |
| - /// // ... |
92 |
| - /// } |
93 |
| - /// } |
94 |
| - /// |
95 |
| - #[cfg_attr(docsrs, doc(cfg(feature = "custom-impl")))] |
96 |
| - #[macro_export] |
97 |
| - macro_rules! custom_impl { |
98 |
| - ($t: ty) => { |
99 |
| - #[no_mangle] |
100 |
| - unsafe fn _critical_section_acquire() -> u8 { |
101 |
| - <$t as $crate::Impl>::acquire() |
102 |
| - } |
103 |
| - #[no_mangle] |
104 |
| - unsafe fn _critical_section_release(token: u8) { |
105 |
| - <$t as $crate::Impl>::release(token) |
106 |
| - } |
107 |
| - }; |
108 |
| - } |
109 |
| - } else if #[cfg(cortex_m)] { |
110 |
| - #[no_mangle] |
111 |
| - unsafe fn _critical_section_acquire() -> u8 { |
112 |
| - let primask = cortex_m::register::primask::read(); |
113 |
| - cortex_m::interrupt::disable(); |
114 |
| - primask.is_active() as _ |
115 |
| - } |
116 |
| - |
117 |
| - #[no_mangle] |
118 |
| - unsafe fn _critical_section_release(token: u8) { |
119 |
| - if token != 0 { |
120 |
| - cortex_m::interrupt::enable() |
121 |
| - } |
122 |
| - } |
123 |
| - } else if #[cfg(target_arch = "avr")] { |
124 |
| - #[no_mangle] |
125 |
| - unsafe fn _critical_section_acquire() -> u8 { |
126 |
| - let mut sreg: u8; |
127 |
| - llvm_asm!( |
128 |
| - "in $0, 0x3F |
129 |
| - cli" |
130 |
| - : "=r"(sreg) |
131 |
| - ::: "volatile" |
132 |
| - ); |
133 |
| - sreg |
134 |
| - } |
135 |
| - |
136 |
| - #[no_mangle] |
137 |
| - unsafe fn _critical_section_release(token: u8) { |
138 |
| - if token & 0x80 == 0x80 { |
139 |
| - llvm_asm!("sei" :::: "volatile"); |
140 |
| - } |
141 |
| - } |
142 |
| - } else if #[cfg(target_arch = "riscv32")] { |
143 |
| - #[no_mangle] |
144 |
| - unsafe fn _critical_section_acquire() -> u8 { |
145 |
| - let interrupts_active = riscv::register::mstatus::read().mie(); |
146 |
| - riscv::interrupt::disable(); |
147 |
| - interrupts_active as _ |
148 |
| - } |
149 |
| - |
150 |
| - #[no_mangle] |
151 |
| - unsafe fn _critical_section_release(token: u8) { |
152 |
| - if token != 0 { |
153 |
| - riscv::interrupt::enable(); |
154 |
| - } |
155 |
| - } |
156 |
| - } else if #[cfg(any(unix, windows, wasm, target_arch = "wasm32"))] { |
157 |
| - extern crate std; |
158 |
| - use std::sync::{Once, Mutex, MutexGuard}; |
159 |
| - use core::cell::Cell; |
160 |
| - |
161 |
| - static INIT: Once = Once::new(); |
162 |
| - static mut GLOBAL_LOCK: Option<Mutex<()>> = None; |
163 |
| - static mut GLOBAL_GUARD: Option<MutexGuard<'static, ()>> = None; |
164 |
| - |
165 |
| - std::thread_local!(static IS_LOCKED: Cell<bool> = Cell::new(false)); |
| 58 | +/// Methods required for a custom critical section implementation. |
| 59 | +/// |
| 60 | +/// This trait is not intended to be used except when implementing a custom critical section. |
| 61 | +/// |
| 62 | +/// Implementations must uphold the contract specified in [`crate::acquire`] and [`crate::release`]. |
| 63 | +pub unsafe trait Impl { |
| 64 | + /// Acquire the critical section. |
| 65 | + unsafe fn acquire() -> u8; |
| 66 | + /// Release the critical section. |
| 67 | + unsafe fn release(token: u8); |
| 68 | +} |
166 | 69 |
|
| 70 | +/// Set the custom critical section implementation. |
| 71 | +/// |
| 72 | +/// # Example |
| 73 | +/// |
| 74 | +/// ``` |
| 75 | +/// struct MyCriticalSection; |
| 76 | +/// critical_section::custom_impl!(MyCriticalSection); |
| 77 | +/// |
| 78 | +/// unsafe impl critical_section::Impl for MyCriticalSection { |
| 79 | +/// unsafe fn acquire() -> u8 { |
| 80 | +/// // ... |
| 81 | +/// # return 0 |
| 82 | +/// } |
| 83 | +/// |
| 84 | +/// unsafe fn release(token: u8) { |
| 85 | +/// // ... |
| 86 | +/// } |
| 87 | +/// } |
| 88 | +/// |
| 89 | +#[macro_export] |
| 90 | +macro_rules! set_impl { |
| 91 | + ($t: ty) => { |
167 | 92 | #[no_mangle]
|
168 | 93 | unsafe fn _critical_section_acquire() -> u8 {
|
169 |
| - INIT.call_once(|| unsafe { |
170 |
| - GLOBAL_LOCK.replace(Mutex::new(())); |
171 |
| - }); |
172 |
| - |
173 |
| - // Allow reentrancy by checking thread local state |
174 |
| - IS_LOCKED.with(|l| { |
175 |
| - if !l.get() { |
176 |
| - let guard = GLOBAL_LOCK.as_ref().unwrap().lock().unwrap(); |
177 |
| - GLOBAL_GUARD.replace(guard); |
178 |
| - l.set(true); |
179 |
| - 1 |
180 |
| - } else { |
181 |
| - 0 |
182 |
| - } |
183 |
| - }) |
| 94 | + <$t as $crate::Impl>::acquire() |
184 | 95 | }
|
185 |
| - |
186 | 96 | #[no_mangle]
|
187 | 97 | unsafe fn _critical_section_release(token: u8) {
|
188 |
| - if token == 1 { |
189 |
| - GLOBAL_GUARD.take(); |
190 |
| - IS_LOCKED.with(|l| { |
191 |
| - l.set(false); |
192 |
| - }); |
193 |
| - } |
| 98 | + <$t as $crate::Impl>::release(token) |
194 | 99 | }
|
195 |
| - } else { |
196 |
| - compile_error!("Critical section is not implemented for this target. Make sure you've specified the correct --target. You may need to supply a custom critical section implementation with the `custom-impl` feature"); |
197 |
| - } |
| 100 | + }; |
198 | 101 | }
|
0 commit comments