Files
yggdrasil/lib/libyalloc/src/util.rs

86 lines
2.1 KiB
Rust

use core::ptr::NonNull;
#[cfg(any(not(feature = "dep-of-kernel"), rust_analyzer))]
use core::{
cell::UnsafeCell,
ops::{Deref, DerefMut},
sync::atomic::{AtomicBool, Ordering},
};
pub enum Assert<const T: bool> {}
pub trait IsTrue {}
impl IsTrue for Assert<true> {}
pub trait NonNullExt<T> {
unsafe fn add_ext(self, offset: usize) -> Self;
}
impl<T> NonNullExt<T> for NonNull<T> {
unsafe fn add_ext(self, offset: usize) -> Self {
NonNull::new_unchecked(self.as_ptr().add(offset))
}
}
#[cfg(any(not(feature = "dep-of-kernel"), rust_analyzer))]
pub struct Spinlock<T: ?Sized> {
state: AtomicBool,
data: UnsafeCell<T>,
}
#[cfg(any(not(feature = "dep-of-kernel"), rust_analyzer))]
pub struct SpinlockGuard<'a, T: ?Sized> {
lock: &'a Spinlock<T>,
}
#[cfg(any(not(feature = "dep-of-kernel"), rust_analyzer))]
impl<T: ?Sized> Spinlock<T> {
pub const fn new(value: T) -> Self
where
T: Sized,
{
Self {
state: AtomicBool::new(false),
data: UnsafeCell::new(value),
}
}
pub fn lock<'a>(&'a self) -> SpinlockGuard<'a, T> {
while self
.state
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
.is_err()
{
core::hint::spin_loop();
}
// Locked
SpinlockGuard { lock: self }
}
}
#[cfg(any(not(feature = "dep-of-kernel"), rust_analyzer))]
impl<'a, T: ?Sized> Deref for SpinlockGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.lock.data.get() }
}
}
#[cfg(any(not(feature = "dep-of-kernel"), rust_analyzer))]
impl<'a, T: ?Sized> DerefMut for SpinlockGuard<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.lock.data.get() }
}
}
#[cfg(any(not(feature = "dep-of-kernel"), rust_analyzer))]
impl<'a, T: ?Sized> Drop for SpinlockGuard<'a, T> {
fn drop(&mut self) {
self.lock.state.store(false, Ordering::Release);
}
}
#[cfg(any(not(feature = "dep-of-kernel"), rust_analyzer))]
unsafe impl<T: ?Sized> Sync for Spinlock<T> {}