Commit c514b0b7 authored by Jeremy Soller's avatar Jeremy Soller

Fix semaphore deadlocks

parent c9e48bf1
Pipeline #2376 passed with stages
in 13 minutes and 22 seconds
......@@ -6,9 +6,14 @@ use syscall;
use platform::types::{c_int, c_uint, c_void};
pub struct Semaphore {
lock: i32,
count: i32,
}
type pte_osThreadHandle = usize;
type pte_osMutexHandle = *mut i32;
type pte_osSemaphoreHandle = *mut i32;
type pte_osSemaphoreHandle = *mut Semaphore;
type pte_osThreadEntryPoint = unsafe extern "C" fn(params: *mut c_void) -> c_int;
#[repr(C)]
......@@ -151,7 +156,7 @@ pub unsafe extern "C" fn pte_osThreadCheckCancel(handle: pte_osThreadHandle) ->
pub unsafe extern "C" fn pte_osThreadSleep(msecs: c_uint) {
let tm = syscall::TimeSpec {
tv_sec: msecs as i64 / 1000,
tv_nsec: (msecs as i32 % 1000) * 1000,
tv_nsec: (msecs % 1000) as i32 * 1000000,
};
let mut rmtp = mem::uninitialized();
let _ = syscall::nanosleep(&tm, &mut rmtp);
......@@ -265,7 +270,10 @@ pte_osResult pte_osSemaphoreCancellablePend(pte_osSemaphoreHandle semHandle, uns
#[no_mangle]
pub unsafe extern "C" fn pte_osSemaphoreCreate(initialValue: c_int, pHandle: *mut pte_osSemaphoreHandle) -> pte_osResult {
*pHandle = Box::into_raw(Box::new(initialValue));
*pHandle = Box::into_raw(Box::new(Semaphore {
lock: 0,
count: initialValue,
}));
PTE_OS_OK
}
......@@ -277,21 +285,26 @@ pub unsafe extern "C" fn pte_osSemaphoreDelete(handle: pte_osSemaphoreHandle) ->
#[no_mangle]
pub unsafe extern "C" fn pte_osSemaphorePost(handle: pte_osSemaphoreHandle, count: c_int) -> pte_osResult {
if intrinsics::atomic_xadd(handle, 1) <= 0 {
while match syscall::futex(handle, syscall::FUTEX_WAKE, 1, 0, ptr::null_mut()) {
Ok(waiters) => waiters < 1,
Err(err) => return PTE_OS_GENERAL_FAILURE,
} {
syscall::sched_yield();
}
}
let semaphore = &mut *handle;
pte_osMutexLock(&mut semaphore.lock);
intrinsics::atomic_xadd(&mut semaphore.count, 1);
pte_osMutexUnlock(&mut semaphore.lock);
PTE_OS_OK
}
#[no_mangle]
pub unsafe extern "C" fn pte_osSemaphorePend(handle: pte_osSemaphoreHandle, pTimeout: *mut c_uint) -> pte_osResult {
if intrinsics::atomic_xsub(handle, 1) < 0 {
let _ = syscall::futex(handle, syscall::FUTEX_WAIT, *handle, 0, ptr::null_mut());
//TODO: pTimeout
let semaphore = &mut *handle;
let mut acquired = false;
while ! acquired {
pte_osMutexLock(&mut semaphore.lock);
if intrinsics::atomic_load(&mut semaphore.count) > 0 {
intrinsics::atomic_xsub(&mut semaphore.count, 1);
acquired = true;
}
pte_osMutexUnlock(&mut semaphore.lock);
let _ = syscall::sched_yield();
}
PTE_OS_OK
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment