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