blob: c6c28629bd254e3fc03228c36bcd9cc135d97523 [file] [log] [blame]
// Copyright 2025 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#![no_std]
use core::sync::atomic::{AtomicBool, Ordering};
use spinlock_core::BareSpinLockApi;
pub struct AtomicSpinLockGuard<'a> {
lock: &'a BareSpinLock,
}
impl Drop for AtomicSpinLockGuard<'_> {
fn drop(&mut self) {
self.lock.unlock();
}
}
pub struct BareSpinLock {
locked: AtomicBool,
}
impl BareSpinLock {
pub const fn new() -> Self {
Self {
locked: AtomicBool::new(false),
}
}
// Only to be called by AtomicSpinlockSentinel::drop().
fn unlock(&self) {
self.locked.store(false, Ordering::Release);
}
}
impl Default for BareSpinLock {
fn default() -> Self {
Self::new()
}
}
impl BareSpinLockApi for BareSpinLock {
type Guard<'a> = AtomicSpinLockGuard<'a>;
fn try_lock(&self) -> Option<Self::Guard<'_>> {
self.locked
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
.map(|_| AtomicSpinLockGuard { lock: self })
.ok()
}
}