use core::{
mem::MaybeUninit,
ops::{Deref, DerefMut},
};
use crate::{
io,
sys::suspend::{
sceKernelPowerLock, sceKernelPowerUnlock, sceKernelVolatileMemLock,
sceKernelVolatileMemTryLock, sceKernelVolatileMemUnlock,
},
};
pub use crate::sys::power::PowerLockKind;
#[derive(Debug)]
#[must_use = "if unused the lock will immediately unlock"]
pub struct PowerLockGuard {
lock_kind: PowerLockKind,
}
impl PowerLockGuard {
#[inline]
fn new(lock_kind: PowerLockKind) -> io::Result<Self> {
sceKernelPowerLock(lock_kind).into_result()?;
Ok(Self { lock_kind })
}
}
impl Drop for PowerLockGuard {
#[inline]
fn drop(&mut self) {
let res = sceKernelPowerUnlock(self.lock_kind);
if res.is_err() {
let _ = sceKernelPowerUnlock(self.lock_kind);
}
}
}
#[derive(Debug)]
#[must_use = "if unused the lock will immediately unlock"]
pub struct VolatileMemoryLockGuard<'a> {
mem: &'a mut [u8],
}
impl<'a> VolatileMemoryLockGuard<'a> {
#[inline]
fn lock() -> io::Result<Self> {
let mut ptr = MaybeUninit::uninit();
let mut size = 0;
unsafe {
sceKernelVolatileMemLock(0, ptr.as_mut_ptr(), &mut size).into_result()?;
let ptr = ptr.assume_init();
debug_assert!(!ptr.is_null());
Ok(Self {
mem: core::slice::from_raw_parts_mut(ptr, size),
})
}
}
#[inline]
fn try_lock() -> io::Result<Self> {
let mut ptr = MaybeUninit::uninit();
let mut size = 0;
unsafe {
sceKernelVolatileMemTryLock(0, ptr.as_mut_ptr(), &mut size).into_result()?;
let ptr = ptr.assume_init();
debug_assert!(!ptr.is_null());
Ok(Self {
mem: core::slice::from_raw_parts_mut(ptr, size),
})
}
}
}
impl<'a> Drop for VolatileMemoryLockGuard<'a> {
#[inline]
fn drop(&mut self) {
unsafe {
let res = sceKernelVolatileMemUnlock(0);
if res.is_err() {
let _ = sceKernelVolatileMemUnlock(0);
}
}
}
}
impl<'a> Deref for VolatileMemoryLockGuard<'a> {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.mem
}
}
impl<'a> DerefMut for VolatileMemoryLockGuard<'a> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.mem
}
}
#[inline]
pub fn lock(lock_kind: PowerLockKind) -> io::Result<PowerLockGuard> {
PowerLockGuard::new(lock_kind)
}
#[inline]
pub fn acquire_volatile_memory<'a>() -> io::Result<VolatileMemoryLockGuard<'a>> {
VolatileMemoryLockGuard::try_lock()
}
#[inline]
pub fn acquire_volatile_memory_blocking<'a>() -> io::Result<VolatileMemoryLockGuard<'a>> {
VolatileMemoryLockGuard::lock()
}