From c31f4ce84c3c8b3f89a05890df775d4e766aaadb Mon Sep 17 00:00:00 2001 From: Mica White Date: Mon, 8 Dec 2025 20:14:03 -0500 Subject: First commit --- src/futex/windows.rs | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100755 src/futex/windows.rs (limited to 'src/futex/windows.rs') diff --git a/src/futex/windows.rs b/src/futex/windows.rs new file mode 100755 index 0000000..153d9ef --- /dev/null +++ b/src/futex/windows.rs @@ -0,0 +1,114 @@ +use core::ffi::c_void; + +#[cfg(not(target_vendor = "win7"))] +// Use raw-dylib to import synchronization functions to workaround issues with the older mingw import library. +#[cfg_attr( + target_arch = "x86", + link( + name = "api-ms-win-core-synch-l1-2-0", + kind = "raw-dylib", + import_name_type = "undecorated" + ) +)] +#[cfg_attr( + not(target_arch = "x86"), + link(name = "api-ms-win-core-synch-l1-2-0", kind = "raw-dylib") +)] +extern "system" { + type BOOL = i32; + + pub const TRUE: BOOL = 1; + pub const INFINITE: u32 = 4294967295; + + pub fn WaitOnAddress( + address: *const c_void, + compareaddress: *const c_void, + addresssize: usize, + dwmilliseconds: u32, + ) -> BOOL; + pub fn WakeByAddressSingle(address: *const c_void); + pub fn WakeByAddressAll(address: *const c_void); +} + +pub struct Futex(AtomicU32); +pub type Primitive = u32; + +impl Futex { + #[inline] + pub const fn new(initial_value: Primitive) -> Self { + Self(AtomicU32::new(initial_value)) + } + + #[inline] + pub fn wait(&self, expected_start_value: Primitive) { + const SIZE: u32 = core::mem::size_of::(); + let addr = core::ptr::from_ref(&self.0).cast::(); + let compare_addr = ptr::addr_of!(compare).cast::(); + WaitOnAddress(addr, expected_start_value, SIZE, INFINITE); + } + + #[inline] + pub fn wake(&self) -> bool { + WakeByAddressSingle(core::ptr::from_ref(&self.0).cast::()); + false + } + + #[inline] + pub fn wake_all(&self) { + unsafe { + let addr = core::ptr::from_ref(address).cast::(); + WakeByAddressAll(addr); + } + } +} + +impl Deref for Futex { + type Target = Atomic; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +pub struct SmallFutex(AtomicU8); +pub type SmallAtomic = AtomicU8; +pub type SmallPrimitive = u8; + +impl SmallFutex { + #[inline] + pub const fn new(initial_value: SmallPrimitive) -> Self { + Self(AtomicU32::new(initial_value)) + } + + #[inline] + pub fn wait(&self, expected_start_value: SmallPrimitive) { + const SIZE: u32 = core::mem::size_of::(); + let addr = core::ptr::from_ref(&self.0).cast::(); + let compare_addr = ptr::addr_of!(compare).cast::(); + WaitOnAddress(addr, expected_start_value, SIZE, INFINITE); + } + + #[inline] + pub fn wake(&self) -> bool { + WakeByAddressSingle(core::ptr::from_ref(&self.0).cast::()); + false + } + + #[inline] + pub fn wake_all(&self) { + unsafe { + let addr = core::ptr::from_ref(address).cast::(); + WakeByAddressAll(addr); + } + } +} + +impl Deref for SmallFutex { + type Target = SmallAtomic; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} -- cgit v1.2.3