use core::cell::UnsafeCell;
use core::ffi::c_void;
use core::ops::{Deref, DerefMut};
#[repr(transparent)]
pub struct SpinLockRaw(usize);
impl SpinLockRaw {
pub const fn new() -> Self {
Self(0)
}
}
pub struct SpinLockGuard<'a, T> {
lock: &'a SpinLock<T>,
old_irql: u8,
}
impl<'a, T> Drop for SpinLockGuard<'a, T> {
fn drop(&mut self) {
unsafe {
KeReleaseSpinLock(&self.lock.raw as *const _ as *mut _, self.old_irql);
}
}
}
impl<'a, T> Deref for SpinLockGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.lock.data.get() }
}
}
impl<'a, T> DerefMut for SpinLockGuard<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.lock.data.get() }
}
}
pub struct SpinLock<T> {
raw: SpinLockRaw,
data: UnsafeCell<T>,
}
unsafe impl<T: Send> Send for SpinLock<T> {}
unsafe impl<T: Send> Sync for SpinLock<T> {}
impl<T> SpinLock<T> {
pub const fn new(data: T) -> Self {
Self {
raw: SpinLockRaw::new(),
data: UnsafeCell::new(data),
}
}
pub fn init(&mut self) {
unsafe {
KeInitializeSpinLock(&mut self.raw as *mut _ as *mut _);
}
}
pub fn lock(&self) -> SpinLockGuard<'_, T> {
let mut old_irql: u8 = 0;
unsafe {
KeAcquireSpinLock(&self.raw as *const _ as *mut _, &mut old_irql);
}
SpinLockGuard {
lock: self,
old_irql,
}
}
pub fn try_lock(&self) -> Option<SpinLockGuard<'_, T>> {
let mut old_irql: u8 = 0;
let acquired = unsafe {
KeTryToAcquireSpinLockAtDpcLevel(&self.raw as *const _ as *mut _)
};
if acquired != 0 {
Some(SpinLockGuard {
lock: self,
old_irql,
})
} else {
None
}
}
pub unsafe fn get_unchecked(&self) -> &mut T {
unsafe { &mut *self.data.get() }
}
}
#[repr(C)]
pub struct FastMutexRaw {
count: i32,
owner: *mut c_void,
contention: u32,
event: [u8; 24], old_irql: u32,
}
pub struct FastMutexGuard<'a, T> {
mutex: &'a FastMutex<T>,
}
impl<'a, T> Drop for FastMutexGuard<'a, T> {
fn drop(&mut self) {
unsafe {
ExReleaseFastMutex(&self.mutex.raw as *const _ as *mut _);
}
}
}
impl<'a, T> Deref for FastMutexGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.mutex.data.get() }
}
}
impl<'a, T> DerefMut for FastMutexGuard<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.mutex.data.get() }
}
}
pub struct FastMutex<T> {
raw: FastMutexRaw,
data: UnsafeCell<T>,
}
unsafe impl<T: Send> Send for FastMutex<T> {}
unsafe impl<T: Send> Sync for FastMutex<T> {}
impl<T> FastMutex<T> {
pub fn new(data: T) -> Self {
Self {
raw: FastMutexRaw {
count: 1,
owner: core::ptr::null_mut(),
contention: 0,
event: [0; 24],
old_irql: 0,
},
data: UnsafeCell::new(data),
}
}
pub fn init(&mut self) {
unsafe {
ExInitializeFastMutex(&mut self.raw as *mut _ as *mut _);
}
}
pub fn lock(&self) -> FastMutexGuard<'_, T> {
unsafe {
ExAcquireFastMutex(&self.raw as *const _ as *mut _);
}
FastMutexGuard { mutex: self }
}
pub fn try_lock(&self) -> Option<FastMutexGuard<'_, T>> {
let acquired = unsafe {
ExTryToAcquireFastMutex(&self.raw as *const _ as *mut _)
};
if acquired != 0 {
Some(FastMutexGuard { mutex: self })
} else {
None
}
}
}
pub struct Guarded<T, L> {
data: T,
lock: L,
}
impl<T, L> Guarded<T, L> {
pub fn new(data: T, lock: L) -> Self {
Self { data, lock }
}
}
#[repr(transparent)]
pub struct PushLockRaw(usize);
impl PushLockRaw {
pub const fn new() -> Self {
Self(0)
}
}
pub struct PushLock<T> {
raw: PushLockRaw,
data: UnsafeCell<T>,
}
unsafe impl<T: Send> Send for PushLock<T> {}
unsafe impl<T: Send + Sync> Sync for PushLock<T> {}
impl<T> PushLock<T> {
pub const fn new(data: T) -> Self {
Self {
raw: PushLockRaw::new(),
data: UnsafeCell::new(data),
}
}
pub fn init(&mut self) {
unsafe {
ExInitializePushLock(&mut self.raw as *mut _ as *mut _);
}
}
pub fn lock_exclusive(&self) -> PushLockExclusiveGuard<'_, T> {
unsafe {
ExAcquirePushLockExclusive(&self.raw as *const _ as *mut _);
}
PushLockExclusiveGuard { lock: self }
}
pub fn lock_shared(&self) -> PushLockSharedGuard<'_, T> {
unsafe {
ExAcquirePushLockShared(&self.raw as *const _ as *mut _);
}
PushLockSharedGuard { lock: self }
}
}
pub struct PushLockExclusiveGuard<'a, T> {
lock: &'a PushLock<T>,
}
impl<'a, T> Drop for PushLockExclusiveGuard<'a, T> {
fn drop(&mut self) {
unsafe {
ExReleasePushLockExclusive(&self.lock.raw as *const _ as *mut _);
}
}
}
impl<'a, T> Deref for PushLockExclusiveGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.lock.data.get() }
}
}
impl<'a, T> DerefMut for PushLockExclusiveGuard<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.lock.data.get() }
}
}
pub struct PushLockSharedGuard<'a, T> {
lock: &'a PushLock<T>,
}
impl<'a, T> Drop for PushLockSharedGuard<'a, T> {
fn drop(&mut self) {
unsafe {
ExReleasePushLockShared(&self.lock.raw as *const _ as *mut _);
}
}
}
impl<'a, T> Deref for PushLockSharedGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.lock.data.get() }
}
}
extern "system" {
fn KeInitializeSpinLock(SpinLock: *mut c_void);
fn KeAcquireSpinLock(SpinLock: *mut c_void, OldIrql: *mut u8);
fn KeReleaseSpinLock(SpinLock: *mut c_void, NewIrql: u8);
fn KeTryToAcquireSpinLockAtDpcLevel(SpinLock: *mut c_void) -> u32;
fn ExInitializeFastMutex(FastMutex: *mut c_void);
fn ExAcquireFastMutex(FastMutex: *mut c_void);
fn ExReleaseFastMutex(FastMutex: *mut c_void);
fn ExTryToAcquireFastMutex(FastMutex: *mut c_void) -> u8;
fn ExInitializePushLock(PushLock: *mut c_void);
fn ExAcquirePushLockExclusive(PushLock: *mut c_void);
fn ExReleasePushLockExclusive(PushLock: *mut c_void);
fn ExAcquirePushLockShared(PushLock: *mut c_void);
fn ExReleasePushLockShared(PushLock: *mut c_void);
}