fix semaphores
This commit is contained in:
+49
-38
@@ -1,61 +1,72 @@
|
||||
use crate::platform::types::*;
|
||||
|
||||
// TODO: Statically verify size and align
|
||||
#[repr(C)]
|
||||
#[derive(Copy)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub union sem_t {
|
||||
pub size: [c_char; 32usize],
|
||||
pub size: [c_char; 4],
|
||||
pub align: c_long,
|
||||
_bindgen_union_align: [u64; 4usize],
|
||||
}
|
||||
impl Clone for sem_t {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
pub type RlctSempahore = crate::sync::Semaphore;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sem_init(sem: *mut sem_t, _pshared: c_int, value: c_uint) -> c_int {
|
||||
sem.cast::<RlctSempahore>().write(RlctSempahore::new(value));
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sem_destroy(sem: *mut sem_t) -> c_int {
|
||||
core::ptr::drop_in_place(sem.cast::<RlctSempahore>());
|
||||
0
|
||||
}
|
||||
|
||||
|
||||
// TODO: va_list
|
||||
// #[no_mangle]
|
||||
pub extern "C" fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int {
|
||||
unimplemented!();
|
||||
pub unsafe extern "C" fn sem_open(name: *const c_char, oflag: c_int, /* (va_list) value: c_uint */) -> *mut sem_t {
|
||||
todo!("named semaphores")
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
pub extern "C" fn sem_destroy(sem: *mut sem_t) -> c_int {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/*
|
||||
*#[no_mangle]
|
||||
*pub extern "C" fn sem_open(name: *const c_char,
|
||||
* oflag: c_int, ...) -> *mut sem_t {
|
||||
* unimplemented!();
|
||||
*}
|
||||
*/
|
||||
|
||||
// #[no_mangle]
|
||||
pub extern "C" fn sem_close(sem: *mut sem_t) -> c_int {
|
||||
unimplemented!();
|
||||
pub unsafe extern "C" fn sem_close(sem: *mut sem_t) -> c_int {
|
||||
todo!("named semaphores")
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
pub extern "C" fn sem_unlink(name: *const c_char) -> c_int {
|
||||
unimplemented!();
|
||||
pub unsafe extern "C" fn sem_unlink(name: *const c_char) -> c_int {
|
||||
todo!("named semaphores")
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
pub extern "C" fn sem_wait(sem: *mut sem_t) -> c_int {
|
||||
unimplemented!();
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sem_wait(sem: *mut sem_t) -> c_int {
|
||||
get(sem).wait(None);
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
pub extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int {
|
||||
unimplemented!();
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int {
|
||||
get(sem).try_wait();
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
pub extern "C" fn sem_post(sem: *mut sem_t) -> c_int {
|
||||
unimplemented!();
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sem_post(sem: *mut sem_t) -> c_int {
|
||||
get(sem).post(1);
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
pub extern "C" fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int {
|
||||
unimplemented!();
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int {
|
||||
sval.write(get(sem).value() as c_int);
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
unsafe fn get<'any>(sem: *mut sem_t) -> &'any RlctSempahore {
|
||||
&*sem.cast()
|
||||
}
|
||||
|
||||
+43
-25
@@ -7,43 +7,57 @@ use crate::{
|
||||
platform::{types::*, Pal, Sys},
|
||||
};
|
||||
|
||||
use core::sync::atomic::Ordering;
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
pub struct Semaphore {
|
||||
lock: AtomicLock,
|
||||
count: AtomicU32,
|
||||
}
|
||||
|
||||
impl Semaphore {
|
||||
pub const fn new(value: c_int) -> Self {
|
||||
pub const fn new(value: c_uint) -> Self {
|
||||
Self {
|
||||
lock: AtomicLock::new(value),
|
||||
count: AtomicU32::new(value),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn post(&self, count: c_int) {
|
||||
self.lock.fetch_add(count, Ordering::SeqCst);
|
||||
self.lock.notify_all();
|
||||
// TODO: Acquire-Release ordering?
|
||||
|
||||
pub fn post(&self, count: c_uint) {
|
||||
self.count.fetch_add(count, Ordering::SeqCst);
|
||||
// TODO: notify one?
|
||||
crate::sync::futex_wake(&self.count, i32::MAX);
|
||||
}
|
||||
|
||||
pub fn try_wait(&self) -> u32 {
|
||||
loop {
|
||||
let value = self.count.load(Ordering::SeqCst);
|
||||
|
||||
if value == 0 { return 0 }
|
||||
|
||||
match self.count.compare_exchange_weak(
|
||||
value,
|
||||
value - 1,
|
||||
Ordering::SeqCst,
|
||||
Ordering::SeqCst,
|
||||
) {
|
||||
Ok(_) => {
|
||||
// Acquired
|
||||
return value;
|
||||
}
|
||||
Err(_) => (),
|
||||
}
|
||||
// Try again (as long as value > 0)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wait(&self, timeout_opt: Option<×pec>) -> Result<(), ()> {
|
||||
loop {
|
||||
let value = self.lock.load(Ordering::SeqCst);
|
||||
if value > 0 {
|
||||
match self.lock.compare_exchange(
|
||||
value,
|
||||
value - 1,
|
||||
Ordering::SeqCst,
|
||||
Ordering::SeqCst,
|
||||
) {
|
||||
Ok(_) => {
|
||||
// Acquired
|
||||
return Ok(());
|
||||
}
|
||||
Err(_) => (),
|
||||
}
|
||||
// Try again (as long as value > 0)
|
||||
continue;
|
||||
let value = self.try_wait();
|
||||
|
||||
if value == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(timeout) = timeout_opt {
|
||||
let mut time = timespec::default();
|
||||
clock_gettime(CLOCK_MONOTONIC, &mut time);
|
||||
@@ -64,12 +78,16 @@ impl Semaphore {
|
||||
}
|
||||
relative.tv_sec -= time.tv_sec;
|
||||
relative.tv_nsec -= time.tv_nsec;
|
||||
self.lock.wait_if(value, Some(&relative));
|
||||
|
||||
crate::sync::futex_wait(&self.count, value, Some(&relative));
|
||||
}
|
||||
} else {
|
||||
// Use futex to wait for the next change, without a timeout
|
||||
self.lock.wait_if(value, None);
|
||||
crate::sync::futex_wait(&self.count, value, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn value(&self) -> c_uint {
|
||||
self.count.load(Ordering::SeqCst)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user