about summary refs log tree commit diff
path: root/library/std/src/sys/pal
diff options
context:
space:
mode:
authorChris Denton <chris@chrisdenton.dev>2024-03-03 22:06:00 +0000
committerChris Denton <chris@chrisdenton.dev>2024-03-05 00:19:42 +0000
commitf700641bd9eb7ec3b36b4d44eafae35ba970eea4 (patch)
tree2bcda35248fd9a6b15cd821e97e666549e44c36f /library/std/src/sys/pal
parent89b78304e82dc5114e3b2faa0fbec747a28a2b37 (diff)
downloadrust-f700641bd9eb7ec3b36b4d44eafae35ba970eea4.tar.gz
rust-f700641bd9eb7ec3b36b4d44eafae35ba970eea4.zip
Windows: Implement mutex using futex
Well, the Windows equivalent: `WaitOnAddress`, `WakeByAddressSingle` and `WakeByAddressAll`.
Diffstat (limited to 'library/std/src/sys/pal')
-rw-r--r--library/std/src/sys/pal/windows/c.rs4
-rw-r--r--library/std/src/sys/pal/windows/futex.rs52
-rw-r--r--library/std/src/sys/pal/windows/mod.rs2
3 files changed, 58 insertions, 0 deletions
diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs
index afa92409404..584e17cd196 100644
--- a/library/std/src/sys/pal/windows/c.rs
+++ b/library/std/src/sys/pal/windows/c.rs
@@ -36,6 +36,7 @@ pub type LPVOID = *mut c_void;
 pub type LPWCH = *mut WCHAR;
 pub type LPWSTR = *mut WCHAR;
 
+#[cfg(target_vendor = "win7")]
 pub type PSRWLOCK = *mut SRWLOCK;
 
 pub type socklen_t = c_int;
@@ -50,7 +51,9 @@ pub const INVALID_HANDLE_VALUE: HANDLE = ::core::ptr::without_provenance_mut(-1i
 pub const EXIT_SUCCESS: u32 = 0;
 pub const EXIT_FAILURE: u32 = 1;
 
+#[cfg(target_vendor = "win7")]
 pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { Ptr: ptr::null_mut() };
+#[cfg(target_vendor = "win7")]
 pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { Ptr: ptr::null_mut() };
 pub const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { Ptr: ptr::null_mut() };
 
@@ -373,6 +376,7 @@ extern "system" {
         dwmilliseconds: u32,
     ) -> BOOL;
     pub fn WakeByAddressSingle(address: *const c_void);
+    pub fn WakeByAddressAll(address: *const c_void);
 }
 
 #[cfg(target_vendor = "win7")]
diff --git a/library/std/src/sys/pal/windows/futex.rs b/library/std/src/sys/pal/windows/futex.rs
new file mode 100644
index 00000000000..88f20ed270b
--- /dev/null
+++ b/library/std/src/sys/pal/windows/futex.rs
@@ -0,0 +1,52 @@
+use super::api;
+use crate::sys::c;
+use crate::sys::dur2timeout;
+use core::ffi::c_void;
+use core::mem;
+use core::ptr;
+use core::time::Duration;
+
+#[inline(always)]
+pub fn wait_on_address<T, U>(address: &T, compare: U, timeout: Option<Duration>) -> bool {
+    assert_eq!(mem::size_of::<T>(), mem::size_of::<U>());
+    unsafe {
+        let addr = ptr::from_ref(address).cast::<c_void>();
+        let size = mem::size_of::<T>();
+        let compare_addr = ptr::addr_of!(compare).cast::<c_void>();
+        let timeout = timeout.map(dur2timeout).unwrap_or(c::INFINITE);
+        c::WaitOnAddress(addr, compare_addr, size, timeout) == c::TRUE
+    }
+}
+
+#[inline(always)]
+pub fn wake_by_address_single<T>(address: &T) {
+    unsafe {
+        let addr = ptr::from_ref(address).cast::<c_void>();
+        c::WakeByAddressSingle(addr);
+    }
+}
+
+#[inline(always)]
+pub fn wake_by_address_all<T>(address: &T) {
+    unsafe {
+        let addr = ptr::from_ref(address).cast::<c_void>();
+        c::WakeByAddressAll(addr);
+    }
+}
+
+#[inline(always)]
+pub fn futex_wait<T, U>(futex: &T, expected: U, timeout: Option<Duration>) -> bool {
+    // return false only on timeout
+    wait_on_address(futex, expected, timeout) || api::get_last_error().code != c::ERROR_TIMEOUT
+}
+
+#[inline(always)]
+pub fn futex_wake<T>(futex: &T) -> bool {
+    wake_by_address_single(futex);
+    false
+}
+
+#[inline(always)]
+pub fn futex_wake_all<T>(futex: &T) {
+    wake_by_address_all(futex)
+}
diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs
index a53c4034d06..6a561518fad 100644
--- a/library/std/src/sys/pal/windows/mod.rs
+++ b/library/std/src/sys/pal/windows/mod.rs
@@ -17,6 +17,8 @@ pub mod args;
 pub mod c;
 pub mod env;
 pub mod fs;
+#[cfg(not(target_vendor = "win7"))]
+pub mod futex;
 pub mod handle;
 pub mod io;
 pub mod net;