use alloc::vec::Vec;
pub(crate) use ax_fs_ng::os::sync::SleepMutex as FsMutex;
pub(crate) use ax_runtime::task::sync::{
InterruptibleMutexExt, LockdepMutexExt, Mutex, MutexGuard, PreemptGuard,
PreemptIrqSaveGuard as NoPreemptIrqSave, RawIrqSaveMutex, RawSpinLock, RawSpinLockGuard, RawSpinRwLock,
};
#[repr(transparent)]
pub(crate) struct IrqMutex<T: ?Sized>(ax_runtime::task::sync::RawSpinLock<T>);
pub(crate) type IrqMutexGuard<'a, T> = ax_runtime::task::sync::RawSpinLockIrqSaveGuard<'a, T>;
impl<T> IrqMutex<T> {
#[track_caller]
pub(crate) const fn new(value: T) -> Self {
Self(ax_runtime::task::sync::RawSpinLock::new(value))
}
#[track_caller]
pub(crate) fn lock(&self) -> IrqMutexGuard<'_, T> {
self.0.lock_irqsave()
}
#[track_caller]
pub(crate) fn lock_nested(&self, subclass: u32) -> IrqMutexGuard<'_, T> {
self.0.lock_irqsave_nested(subclass)
}
#[track_caller]
pub(crate) fn try_lock(&self) -> Option<IrqMutexGuard<'_, T>> {
self.0.try_lock_irqsave()
}
}
impl<T: Default> Default for IrqMutex<T> {
fn default() -> Self {
Self::new(T::default())
}
}
pub(crate) fn try_reserve_irq_vec<T>(
queue: &IrqMutex<Vec<T>>,
additional: usize,
) -> Result<(), ()> {
if additional == 0 {
return Ok(());
}
let mut replacement = Vec::new();
loop {
let reserve_target = {
let entries = queue.lock();
if entries.capacity().saturating_sub(entries.len()) >= additional {
return Ok(());
}
let required = entries.len().checked_add(additional).ok_or(())?;
required.max(entries.capacity().saturating_mul(2)).max(4)
};
replacement
.try_reserve_exact(reserve_target)
.map_err(|_| ())?;
let mut entries = queue.lock();
if entries.capacity().saturating_sub(entries.len()) >= additional {
return Ok(());
}
let Some(required) = entries.len().checked_add(additional) else {
return Err(());
};
if replacement.capacity() < required {
continue;
}
replacement.extend(entries.drain(..));
core::mem::swap(&mut *entries, &mut replacement);
drop(entries);
return Ok(());
}
}
pub(crate) fn try_push_irq_vec<T>(queue: &IrqMutex<Vec<T>>, value: T) -> Result<(), T> {
loop {
if try_reserve_irq_vec(queue, 1).is_err() {
return Err(value);
}
let mut entries = queue.lock();
if entries.len() == entries.capacity() {
continue;
}
entries.push(value);
return Ok(());
}
}
impl<T: core::fmt::Debug> core::fmt::Debug for IrqMutex<T> {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.0.fmt(formatter)
}
}
pub(crate) type NoPreemptMutex<T> = RawSpinLock<T>;
pub(crate) type RwLock<T> = RawSpinRwLock<T>;