From e0ea7017a67d4b122ff99760381510f254c976b0 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 16 Jul 2024 14:56:18 +0000 Subject: [PATCH] Prevent double reference in generic futex --- std/src/sys/pal/windows/futex.rs | 11 +++++++---- std/src/sys/sync/once/futex.rs | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/std/src/sys/pal/windows/futex.rs b/std/src/sys/pal/windows/futex.rs index cb802fdd9c96d..c54810e06cdd6 100644 --- a/std/src/sys/pal/windows/futex.rs +++ b/std/src/sys/pal/windows/futex.rs @@ -15,6 +15,7 @@ pub type SmallAtomic = AtomicU8; /// Must be the underlying type of SmallAtomic pub type SmallPrimitive = u8; +pub unsafe trait Futex {} pub unsafe trait Waitable { type Atomic; } @@ -24,6 +25,7 @@ macro_rules! unsafe_waitable_int { unsafe impl Waitable for $int { type Atomic = $atomic; } + unsafe impl Futex for $atomic {} )* }; } @@ -46,6 +48,7 @@ unsafe impl Waitable for *const T { unsafe impl Waitable for *mut T { type Atomic = AtomicPtr; } +unsafe impl Futex for AtomicPtr {} pub fn wait_on_address( address: &W::Atomic, @@ -61,14 +64,14 @@ pub fn wait_on_address( } } -pub fn wake_by_address_single(address: &T) { +pub fn wake_by_address_single(address: &T) { unsafe { let addr = ptr::from_ref(address).cast::(); c::WakeByAddressSingle(addr); } } -pub fn wake_by_address_all(address: &T) { +pub fn wake_by_address_all(address: &T) { unsafe { let addr = ptr::from_ref(address).cast::(); c::WakeByAddressAll(addr); @@ -80,11 +83,11 @@ pub fn futex_wait(futex: &W::Atomic, expected: W, timeout: Option(futex: &T) -> bool { +pub fn futex_wake(futex: &T) -> bool { wake_by_address_single(futex); false } -pub fn futex_wake_all(futex: &T) { +pub fn futex_wake_all(futex: &T) { wake_by_address_all(futex) } diff --git a/std/src/sys/sync/once/futex.rs b/std/src/sys/sync/once/futex.rs index 609085dcd4712..8a231e65ad134 100644 --- a/std/src/sys/sync/once/futex.rs +++ b/std/src/sys/sync/once/futex.rs @@ -57,7 +57,7 @@ impl<'a> Drop for CompletionGuard<'a> { // up on the Once. `futex_wake_all` does its own synchronization, hence // we do not need `AcqRel`. if self.state.swap(self.set_state_on_drop_to, Release) == QUEUED { - futex_wake_all(&self.state); + futex_wake_all(self.state); } } }