use crate::alloc::allocator::AllocError;
use crate::sched::event;
use crate::sync::Error;
use crate::syscall;
pub type SemaphoreID = usize;
pub struct IpcSemaphore {
semaphore_id: SemaphoreID,
event_id: usize,
}
impl IpcSemaphore {
pub fn new() -> Result<IpcSemaphore, AllocError> {
let (s, e) = syscall::ipc_semaphore_register()?;
Ok(IpcSemaphore {
semaphore_id: s,
event_id: e,
})
}
pub fn try_acquire(&self) -> Result<SemaphorePermit<'_>, Error> {
syscall::ipc_semaphore_try_aquire(self.semaphore_id).and_then(|v| {
if v {
Ok(SemaphorePermit::new(self))
} else {
Err(Error::WouldBlock)
}
})
}
pub fn acquire(&self, timeout: u32) -> Result<SemaphorePermit<'_>, Error> {
syscall::ipc_semaphore_try_aquire(self.semaphore_id).and_then(|v| {
if v {
Ok(SemaphorePermit::new(self))
} else {
match syscall::event_await(self.event_id, timeout) {
Ok(_) => {
syscall::ipc_semaphore_try_aquire(self.semaphore_id).ok();
Ok(SemaphorePermit::new(self))
}
Err(event::Error::TimeOut) => Err(Error::TimeOut),
Err(_) => Err(Error::Poisoned),
}
}
})
}
pub fn available_permits(&self) -> usize {
0
}
pub fn add_permits(&self, _n: usize) {}
}
unsafe impl Sync for IpcSemaphore {}
pub struct SemaphorePermit<'a> {
_semaphore: &'a IpcSemaphore,
}
impl<'a> SemaphorePermit<'a> {
fn new(semaphore: &'a IpcSemaphore) -> Self {
SemaphorePermit {
_semaphore: semaphore,
}
}
pub fn forget(self) {}
}
impl<'a> Drop for SemaphorePermit<'a> {
fn drop(&mut self) {}
}
pub(crate) struct IpcSemaphoreInternal {
semaphore_id: SemaphoreID,
_event_id: usize,
}
impl IpcSemaphoreInternal {
pub(crate) fn new(semaphore_id: SemaphoreID, event_id: usize) -> IpcSemaphoreInternal {
IpcSemaphoreInternal {
semaphore_id,
_event_id: event_id,
}
}
pub(crate) fn id(&self) -> SemaphoreID {
self.semaphore_id
}
}