twizzler_abi/runtime/
simple_mutex.rsuse core::{
cell::UnsafeCell,
sync::atomic::{AtomicU64, Ordering},
};
use crate::syscall::{
sys_thread_sync, ThreadSync, ThreadSyncFlags, ThreadSyncOp, ThreadSyncReference,
ThreadSyncSleep, ThreadSyncWake,
};
pub(crate) struct MutexImp {
lock: AtomicU64,
}
unsafe impl Send for MutexImp {}
impl MutexImp {
#[allow(dead_code)]
pub const fn new() -> MutexImp {
MutexImp {
lock: AtomicU64::new(0),
}
}
#[allow(dead_code)]
pub fn is_locked(&self) -> bool {
self.lock.load(Ordering::SeqCst) != 0
}
#[inline]
#[allow(dead_code)]
pub unsafe fn lock(&self) {
for _ in 0..100 {
let result = self
.lock
.compare_exchange_weak(0, 1, Ordering::SeqCst, Ordering::SeqCst);
if result.is_ok() {
return;
}
core::hint::spin_loop();
}
let _ = self
.lock
.compare_exchange(1, 2, Ordering::SeqCst, Ordering::SeqCst);
let sleep = ThreadSync::new_sleep(ThreadSyncSleep::new(
ThreadSyncReference::Virtual(&self.lock),
2,
ThreadSyncOp::Equal,
ThreadSyncFlags::empty(),
));
loop {
let state = self.lock.swap(2, Ordering::SeqCst);
if state == 0 {
break;
}
let _ = sys_thread_sync(&mut [sleep], None);
}
}
#[inline]
#[allow(dead_code)]
pub unsafe fn unlock(&self) {
if self.lock.swap(0, Ordering::SeqCst) == 1 {
return;
}
for _ in 0..200 {
if self.lock.load(Ordering::SeqCst) > 0
&& self
.lock
.compare_exchange(1, 2, Ordering::SeqCst, Ordering::SeqCst)
!= Err(0)
{
return;
}
core::hint::spin_loop();
}
let wake = ThreadSync::new_wake(ThreadSyncWake::new(
ThreadSyncReference::Virtual(&self.lock),
1,
));
let _ = sys_thread_sync(&mut [wake], None);
}
#[inline]
#[allow(dead_code)]
pub unsafe fn try_lock(&self) -> bool {
self.lock
.compare_exchange_weak(0, 1, Ordering::SeqCst, Ordering::SeqCst)
.is_ok()
}
}
pub(crate) struct Mutex<T> {
imp: MutexImp,
data: UnsafeCell<T>,
}
impl<T: Default> Default for Mutex<T> {
fn default() -> Self {
Self {
imp: MutexImp::new(),
data: Default::default(),
}
}
}
impl<T> Mutex<T> {
#[allow(dead_code)]
pub const fn new(data: T) -> Self {
Self {
imp: MutexImp::new(),
data: UnsafeCell::new(data),
}
}
#[allow(dead_code)]
pub fn lock(&self) -> LockGuard<'_, T> {
unsafe {
self.imp.lock();
}
LockGuard { lock: self }
}
#[allow(dead_code)]
pub fn try_lock(&self) -> Option<LockGuard<'_, T>> {
unsafe {
if !self.imp.try_lock() {
return None;
}
}
Some(LockGuard { lock: self })
}
}
unsafe impl<T> Send for Mutex<T> where T: Send {}
unsafe impl<T> Sync for Mutex<T> where T: Send {}
unsafe impl<T> Send for LockGuard<'_, T> where T: Send {}
unsafe impl<T> Sync for LockGuard<'_, T> where T: Send + Sync {}
pub(crate) struct LockGuard<'a, T> {
lock: &'a Mutex<T>,
}
impl<T> core::ops::Deref for LockGuard<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.lock.data.get() }
}
}
impl<T> core::ops::DerefMut for LockGuard<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.lock.data.get() }
}
}
impl<T> Drop for LockGuard<'_, T> {
fn drop(&mut self) {
unsafe { self.lock.imp.unlock() };
}
}