• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2025 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 use core::sync::atomic::{AtomicBool, Ordering};
15 
16 use crate::arch::BareSpinLock as BareSpinLockApi;
17 
18 pub struct AtomicSpinLockGuard<'a> {
19     lock: &'a BareSpinLock,
20 }
21 
22 impl Drop for AtomicSpinLockGuard<'_> {
drop(&mut self)23     fn drop(&mut self) {
24         self.lock.unlock();
25     }
26 }
27 
28 pub struct BareSpinLock {
29     locked: AtomicBool,
30 }
31 
32 impl BareSpinLock {
new() -> Self33     pub const fn new() -> Self {
34         Self {
35             locked: AtomicBool::new(false),
36         }
37     }
38 
39     // Only to be called by AtomicSpinlockSentinel::drop().
unlock(&self)40     fn unlock(&self) {
41         self.locked.store(false, Ordering::Release);
42     }
43 }
44 
45 impl Default for BareSpinLock {
default() -> Self46     fn default() -> Self {
47         Self::new()
48     }
49 }
50 
51 impl BareSpinLockApi for BareSpinLock {
52     type Guard<'a> = AtomicSpinLockGuard<'a>;
53 
try_lock(&self) -> Option<Self::Guard<'_>>54     fn try_lock(&self) -> Option<Self::Guard<'_>> {
55         self.locked
56             .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
57             .map(|_| AtomicSpinLockGuard { lock: self })
58             .ok()
59     }
60 }
61