diff --git a/src/platform/redox/pte.rs b/src/platform/redox/pte.rs index 835c6be4c356c1d0efd313b1f1acbb23e9ed0403..a4dd41c1c08bb4d512b46788a2ea57b42fa344a3 100644 --- a/src/platform/redox/pte.rs +++ b/src/platform/redox/pte.rs @@ -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 }