diff options
| author | Chris Denton <chris@chrisdenton.dev> | 2024-03-03 22:06:00 +0000 |
|---|---|---|
| committer | Chris Denton <chris@chrisdenton.dev> | 2024-03-05 00:19:42 +0000 |
| commit | f700641bd9eb7ec3b36b4d44eafae35ba970eea4 (patch) | |
| tree | 2bcda35248fd9a6b15cd821e97e666549e44c36f /library/std/src/sys/pal | |
| parent | 89b78304e82dc5114e3b2faa0fbec747a28a2b37 (diff) | |
| download | rust-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.rs | 4 | ||||
| -rw-r--r-- | library/std/src/sys/pal/windows/futex.rs | 52 | ||||
| -rw-r--r-- | library/std/src/sys/pal/windows/mod.rs | 2 |
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; |
