Skip to content
Snippets Groups Projects
Verified Commit 9040c2a2 authored by Jacob Lorentzon's avatar Jacob Lorentzon Committed by Jeremy Soller
Browse files

fix semaphores

parent 75cc16a5
No related branches found
No related tags found
No related merge requests found
use crate::platform::types::*; use crate::platform::types::*;
// TODO: Statically verify size and align
#[repr(C)] #[repr(C)]
#[derive(Copy)] #[derive(Clone, Copy)]
pub union sem_t { pub union sem_t {
pub size: [c_char; 32usize], pub size: [c_char; 4],
pub align: c_long, pub align: c_long,
_bindgen_union_align: [u64; 4usize],
} }
impl Clone for sem_t { pub type RlctSempahore = crate::sync::Semaphore;
fn clone(&self) -> Self {
*self #[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));
// #[no_mangle]
pub extern "C" fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int { 0
unimplemented!();
} }
// #[no_mangle] #[no_mangle]
pub extern "C" fn sem_destroy(sem: *mut sem_t) -> c_int { pub unsafe extern "C" fn sem_destroy(sem: *mut sem_t) -> c_int {
unimplemented!(); core::ptr::drop_in_place(sem.cast::<RlctSempahore>());
0
} }
/*
*#[no_mangle]
*pub extern "C" fn sem_open(name: *const c_char,
* oflag: c_int, ...) -> *mut sem_t {
* unimplemented!();
*}
*/
// TODO: va_list
// #[no_mangle] // #[no_mangle]
pub extern "C" fn sem_close(sem: *mut sem_t) -> c_int { pub unsafe extern "C" fn sem_open(name: *const c_char, oflag: c_int, /* (va_list) value: c_uint */) -> *mut sem_t {
unimplemented!(); todo!("named semaphores")
} }
// #[no_mangle] // #[no_mangle]
pub extern "C" fn sem_unlink(name: *const c_char) -> c_int { pub unsafe extern "C" fn sem_close(sem: *mut sem_t) -> c_int {
unimplemented!(); todo!("named semaphores")
} }
// #[no_mangle] // #[no_mangle]
pub extern "C" fn sem_wait(sem: *mut sem_t) -> c_int { pub unsafe extern "C" fn sem_unlink(name: *const c_char) -> c_int {
unimplemented!(); todo!("named semaphores")
} }
// #[no_mangle] #[no_mangle]
pub extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int { pub unsafe extern "C" fn sem_wait(sem: *mut sem_t) -> c_int {
unimplemented!(); get(sem).wait(None);
0
} }
// #[no_mangle] #[no_mangle]
pub extern "C" fn sem_post(sem: *mut sem_t) -> c_int { pub unsafe extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int {
unimplemented!(); get(sem).try_wait();
0
} }
// #[no_mangle] #[no_mangle]
pub extern "C" fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int { pub unsafe extern "C" fn sem_post(sem: *mut sem_t) -> c_int {
unimplemented!(); get(sem).post(1);
0
}
#[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()
} }
...@@ -7,43 +7,57 @@ use crate::{ ...@@ -7,43 +7,57 @@ use crate::{
platform::{types::*, Pal, Sys}, platform::{types::*, Pal, Sys},
}; };
use core::sync::atomic::Ordering; use core::sync::atomic::{AtomicU32, Ordering};
pub struct Semaphore { pub struct Semaphore {
lock: AtomicLock, count: AtomicU32,
} }
impl Semaphore { impl Semaphore {
pub const fn new(value: c_int) -> Self { pub const fn new(value: c_uint) -> Self {
Self { Self {
lock: AtomicLock::new(value), count: AtomicU32::new(value),
} }
} }
pub fn post(&self, count: c_int) { // TODO: Acquire-Release ordering?
self.lock.fetch_add(count, Ordering::SeqCst);
self.lock.notify_all(); 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 wait(&self, timeout_opt: Option<&timespec>) -> Result<(), ()> { pub fn try_wait(&self) -> u32 {
loop { loop {
let value = self.lock.load(Ordering::SeqCst); let value = self.count.load(Ordering::SeqCst);
if value > 0 {
match self.lock.compare_exchange( if value == 0 { return 0 }
value,
value - 1, match self.count.compare_exchange_weak(
Ordering::SeqCst, value,
Ordering::SeqCst, value - 1,
) { Ordering::SeqCst,
Ok(_) => { Ordering::SeqCst,
// Acquired ) {
return Ok(()); Ok(_) => {
} // Acquired
Err(_) => (), return value;
} }
// Try again (as long as value > 0) Err(_) => (),
continue;
} }
// Try again (as long as value > 0)
}
}
pub fn wait(&self, timeout_opt: Option<&timespec>) -> Result<(), ()> {
loop {
let value = self.try_wait();
if value == 0 {
return Ok(());
}
if let Some(timeout) = timeout_opt { if let Some(timeout) = timeout_opt {
let mut time = timespec::default(); let mut time = timespec::default();
clock_gettime(CLOCK_MONOTONIC, &mut time); clock_gettime(CLOCK_MONOTONIC, &mut time);
...@@ -64,12 +78,16 @@ impl Semaphore { ...@@ -64,12 +78,16 @@ impl Semaphore {
} }
relative.tv_sec -= time.tv_sec; relative.tv_sec -= time.tv_sec;
relative.tv_nsec -= time.tv_nsec; relative.tv_nsec -= time.tv_nsec;
self.lock.wait_if(value, Some(&relative));
crate::sync::futex_wait(&self.count, value, Some(&relative));
} }
} else { } else {
// Use futex to wait for the next change, without a timeout // 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)
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment