#![doc = include_str!("../../docs/sync_model.md")]
pub mod bellringer;
pub mod irq;
pub mod semaphore;
use crate::arch::x86_64::is_int_enabled;
use crate::black_magic::Void;
use core::cell::SyncUnsafeCell;
use core::ops::{Deref, DerefMut};
use core::sync::atomic::{AtomicBool, Ordering};
pub use irq::*;
static L2_AVAILABLE: AtomicBool = AtomicBool::new(true);
static L2_GUARD: L2Sync<Void> = L2Sync::new(Void::new());
#[inline(always)]
#[allow(non_snake_case)]
pub fn IS_L2_AVAILABLE() -> bool {
return L2_AVAILABLE.load(Ordering::Relaxed);
}
#[allow(non_snake_case)]
#[inline(always)]
pub fn ENTER_L2() {
let r = L2_AVAILABLE.compare_exchange(
true,
false,
Ordering::Relaxed,
Ordering::Relaxed,
);
debug_assert_eq!(r, Ok(true));
}
#[inline(always)]
#[allow(non_snake_case)]
pub fn LEAVE_L2() {
let r = L2_AVAILABLE.compare_exchange(
false,
true,
Ordering::Relaxed,
Ordering::Relaxed,
);
debug_assert_eq!(r, Ok(false));
}
#[inline(always)]
#[allow(non_snake_case)]
pub fn LEAVE_L2_CLEAR_QUEUE() {
todo!();
}
pub struct L2Guard<'a, T: 'a> {
lock: &'a L2Sync<T>,
}
impl<T> Deref for L2Guard<'_, T> {
type Target = T;
fn deref(&self) -> &T { unsafe { &*self.lock.data.get() } }
}
impl<T> DerefMut for L2Guard<'_, T> {
fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.lock.data.get() } }
}
impl<T> Drop for L2Guard<'_, T> {
fn drop(&mut self) { LEAVE_L2(); }
}
pub struct L2Sync<T> {
data: SyncUnsafeCell<T>,
}
impl<T> L2Sync<T> {
pub const fn new(data: T) -> Self {
Self { data: SyncUnsafeCell::new(data) }
}
pub fn lock(&self) -> L2Guard<T> {
ENTER_L2();
L2Guard { lock: self }
}
pub unsafe fn get_ref_unguarded(&self) -> &T { &*self.data.get() }
pub unsafe fn get_ref_mut_unguarded(&self) -> &mut T {
&mut *self.data.get()
}
}
pub struct L3Sync<T> {
data: SyncUnsafeCell<T>,
}
impl<T> L3Sync<T> {
pub const fn new(data: T) -> Self {
Self { data: SyncUnsafeCell::new(data) }
}
pub fn l3_get_ref(&self) -> &T {
debug_assert!(
!is_int_enabled(),
"trying to get a ref to L3 synced object with interrupt enabled"
);
unsafe { &*self.data.get() }
}
pub fn l3_get_ref_mut(&self) -> &mut T {
debug_assert!(
!is_int_enabled(),
"trying to get a mut ref to L3 synced object with interrupt enabled"
);
unsafe { &mut *self.data.get() }
}
pub unsafe fn l3_get_ref_mut_unchecked(&self) -> &mut T {
unsafe { &mut *self.data.get() }
}
}