From 0b49b056981f4c5bcbdbb7fada1a8379e0793c86 Mon Sep 17 00:00:00 2001 From: Botahamec Date: Fri, 28 Oct 2022 22:20:05 -0400 Subject: Implemented SpinLock --- src/lib.rs | 7 +++++-- src/lock.rs | 7 ++++++- src/mutex.rs | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 615086d..2358ba2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ #![warn(clippy::pedantic)] #![warn(clippy::nursery)] #![allow(clippy::module_name_repetitions)] +#![allow(clippy::declare_interior_mutable_const)] use std::any::type_name; use std::fmt::{self, Debug}; @@ -10,11 +11,13 @@ use once_cell::sync::Lazy; use thread_local::ThreadLocal; mod lock; -pub mod mutex; +mod mutex; use lock::{Key, Lock}; +use mutex::RawSpin; -pub use mutex::Mutex; +pub use mutex::{Mutex, MutexGuard}; +pub type SpinLock = Mutex; static KEY: Lazy> = Lazy::new(ThreadLocal::new); diff --git a/src/lock.rs b/src/lock.rs index c69ce21..101a061 100644 --- a/src/lock.rs +++ b/src/lock.rs @@ -38,6 +38,11 @@ impl Lock { } } + /// Checks whether this `Lock` is currently locked. + pub fn is_locked(&self) -> bool { + self.is_locked.load(Ordering::Relaxed) + } + /// Attempt to lock the `Lock`. /// /// If the lock is already locked, then this'll return false. If it is @@ -56,7 +61,7 @@ impl Lock { /// /// This should only be called if the key to the lock has been "lost". That /// means the program no longer has a reference to the key. - unsafe fn force_unlock(&self) { + pub unsafe fn force_unlock(&self) { self.is_locked.store(false, Ordering::Release); } diff --git a/src/mutex.rs b/src/mutex.rs index a152eda..6c2e254 100644 --- a/src/mutex.rs +++ b/src/mutex.rs @@ -1,6 +1,7 @@ use std::cell::UnsafeCell; use std::ops::{Deref, DerefMut}; +use crate::lock::Lock; use crate::ThreadKey; /// Implements a raw C-like mutex. @@ -31,6 +32,38 @@ pub unsafe trait RawMutex { unsafe fn unlock(&self); } +/// A raw mutex which just spins +pub struct RawSpin { + lock: Lock, +} + +unsafe impl RawMutex for RawSpin { + const INIT: Self = Self { lock: Lock::new() }; + + fn lock(&self) { + loop { + std::hint::spin_loop(); + + if let Some(key) = self.lock.try_lock() { + std::mem::forget(key); + return; + } + } + } + + fn try_lock(&self) -> bool { + self.lock.try_lock().is_some() + } + + fn is_locked(&self) -> bool { + self.lock.is_locked() + } + + unsafe fn unlock(&self) { + self.lock.force_unlock(); + } +} + /// A mutual exclusion primitive useful for protecting shared data, which /// cannot deadlock. /// -- cgit v1.2.3