浏览代码

Fix semaphore deadlocks

Jeremy Soller 6 年之前
父节点
当前提交
c514b0b705
共有 1 个文件被更改,包括 26 次插入13 次删除
  1. 26 13
      src/platform/redox/pte.rs

+ 26 - 13
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
 }