73 lines
1.7 KiB
Rust
73 lines
1.7 KiB
Rust
use core::{
|
|
cell::UnsafeCell,
|
|
marker::PhantomPinned,
|
|
panic::{RefUnwindSafe, UnwindSafe},
|
|
};
|
|
|
|
use crate::{
|
|
bindings::{rt_barrier, rt_barrier_wait, rt_cond, rt_mutex},
|
|
list::list_init,
|
|
sync::semaphore::c_sem_init,
|
|
};
|
|
|
|
pub struct Barrier {
|
|
b: UnsafeCell<rt_barrier>,
|
|
_pin_marker: PhantomPinned,
|
|
}
|
|
|
|
unsafe impl Send for Barrier {}
|
|
unsafe impl Sync for Barrier {}
|
|
impl UnwindSafe for Barrier {}
|
|
impl RefUnwindSafe for Barrier {}
|
|
|
|
pub struct BarrierWaitResult(bool);
|
|
|
|
impl Barrier {
|
|
pub const fn init(barrier: &'static Barrier, count: u32) -> Barrier {
|
|
let b = unsafe { &*(barrier.b.get() as *const rt_barrier) };
|
|
Barrier {
|
|
b: UnsafeCell::new(rt_barrier {
|
|
mutex: rt_mutex {
|
|
holder: 0,
|
|
wait_list: list_init(&b.mutex.wait_list),
|
|
list: list_init(&b.mutex.list),
|
|
},
|
|
cond: rt_cond {
|
|
sem: c_sem_init(&b.cond.sem, 0, 0),
|
|
},
|
|
level: 0,
|
|
threshold: count,
|
|
generation: 0,
|
|
}),
|
|
_pin_marker: PhantomPinned,
|
|
}
|
|
}
|
|
|
|
pub fn wait(&self) -> BarrierWaitResult {
|
|
BarrierWaitResult(unsafe { rt_barrier_wait(self.b.get()) })
|
|
}
|
|
}
|
|
|
|
impl BarrierWaitResult {
|
|
#[must_use]
|
|
pub fn is_leader(&self) -> bool {
|
|
self.0
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! barrier {
|
|
($name: ident, $count: expr) => {
|
|
static $name: $crate::sync::Barrier = $crate::sync::Barrier::init(&$name, $count);
|
|
};
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
#[test]
|
|
fn fast_path() {
|
|
barrier!(BARRIER, 1);
|
|
assert!(BARRIER.wait().is_leader());
|
|
}
|
|
}
|