about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChris Denton <chris@chrisdenton.dev>2024-07-16 14:56:18 +0000
committerChris Denton <chris@chrisdenton.dev>2024-07-17 05:57:39 +0000
commit0585c4a23ed7489ab21aa586eec4700b567cee03 (patch)
tree624a338b23616753f576084d715e5b27b8bac094
parenta28b35eb35ef874d068b8a66e9ff7460fa23a672 (diff)
downloadrust-0585c4a23ed7489ab21aa586eec4700b567cee03.tar.gz
rust-0585c4a23ed7489ab21aa586eec4700b567cee03.zip
Prevent double reference in generic futex
-rw-r--r--library/std/src/sys/pal/windows/futex.rs11
-rw-r--r--library/std/src/sys/sync/once/futex.rs2
2 files changed, 8 insertions, 5 deletions
diff --git a/library/std/src/sys/pal/windows/futex.rs b/library/std/src/sys/pal/windows/futex.rs
index cb802fdd9c9..c54810e06cd 100644
--- a/library/std/src/sys/pal/windows/futex.rs
+++ b/library/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<T> Waitable for *const T {
 unsafe impl<T> Waitable for *mut T {
     type Atomic = AtomicPtr<T>;
 }
+unsafe impl<T> Futex for AtomicPtr<T> {}
 
 pub fn wait_on_address<W: Waitable>(
     address: &W::Atomic,
@@ -61,14 +64,14 @@ pub fn wait_on_address<W: Waitable>(
     }
 }
 
-pub fn wake_by_address_single<T>(address: &T) {
+pub fn wake_by_address_single<T: Futex>(address: &T) {
     unsafe {
         let addr = ptr::from_ref(address).cast::<c_void>();
         c::WakeByAddressSingle(addr);
     }
 }
 
-pub fn wake_by_address_all<T>(address: &T) {
+pub fn wake_by_address_all<T: Futex>(address: &T) {
     unsafe {
         let addr = ptr::from_ref(address).cast::<c_void>();
         c::WakeByAddressAll(addr);
@@ -80,11 +83,11 @@ pub fn futex_wait<W: Waitable>(futex: &W::Atomic, expected: W, timeout: Option<D
     wait_on_address(futex, expected, timeout) || api::get_last_error() != WinError::TIMEOUT
 }
 
-pub fn futex_wake<T>(futex: &T) -> bool {
+pub fn futex_wake<T: Futex>(futex: &T) -> bool {
     wake_by_address_single(futex);
     false
 }
 
-pub fn futex_wake_all<T>(futex: &T) {
+pub fn futex_wake_all<T: Futex>(futex: &T) {
     wake_by_address_all(futex)
 }
diff --git a/library/std/src/sys/sync/once/futex.rs b/library/std/src/sys/sync/once/futex.rs
index 609085dcd47..8a231e65ad1 100644
--- a/library/std/src/sys/sync/once/futex.rs
+++ b/library/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);
         }
     }
 }