use super::UPIntrFreeCell;
use alloc::collections::VecDeque;
use tg_task_manage::ThreadId;
pub struct Semaphore {
pub inner: UPIntrFreeCell<SemaphoreInner>,
}
pub struct SemaphoreInner {
pub count: isize,
pub wait_queue: VecDeque<ThreadId>,
}
impl Semaphore {
pub fn new(res_count: usize) -> Self {
Self {
inner: unsafe {
UPIntrFreeCell::new(SemaphoreInner {
count: res_count as isize,
wait_queue: VecDeque::new(),
})
},
}
}
pub fn up(&self) -> Option<ThreadId> {
let mut inner = self.inner.exclusive_access();
inner.count += 1;
inner.wait_queue.pop_front()
}
pub fn down(&self, tid: ThreadId) -> bool {
let mut inner = self.inner.exclusive_access();
inner.count -= 1;
if inner.count < 0 {
inner.wait_queue.push_back(tid);
drop(inner);
false
} else {
true
}
}
}