Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a2cf636

Browse files
authoredJul 17, 2024
Rollup merge of rust-lang#127813 - ChrisDenton:win-futex, r=joboet
Prevent double reference in generic futex In the Windows futex implementation we were a little lax at allowing references to references (i.e. `&&`) which can lead to deadlocks due to reading the wrong memory address. This uses a trait to tighten the constraints and ensure this doesn't happen. r? libs
2 parents aeae332 + e0ea701 commit a2cf636

File tree

2 files changed

+8
-5
lines changed

2 files changed

+8
-5
lines changed
 

‎std/src/sys/pal/windows/futex.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub type SmallAtomic = AtomicU8;
1515
/// Must be the underlying type of SmallAtomic
1616
pub type SmallPrimitive = u8;
1717

18+
pub unsafe trait Futex {}
1819
pub unsafe trait Waitable {
1920
type Atomic;
2021
}
@@ -24,6 +25,7 @@ macro_rules! unsafe_waitable_int {
2425
unsafe impl Waitable for $int {
2526
type Atomic = $atomic;
2627
}
28+
unsafe impl Futex for $atomic {}
2729
)*
2830
};
2931
}
@@ -46,6 +48,7 @@ unsafe impl<T> Waitable for *const T {
4648
unsafe impl<T> Waitable for *mut T {
4749
type Atomic = AtomicPtr<T>;
4850
}
51+
unsafe impl<T> Futex for AtomicPtr<T> {}
4952

5053
pub fn wait_on_address<W: Waitable>(
5154
address: &W::Atomic,
@@ -61,14 +64,14 @@ pub fn wait_on_address<W: Waitable>(
6164
}
6265
}
6366

64-
pub fn wake_by_address_single<T>(address: &T) {
67+
pub fn wake_by_address_single<T: Futex>(address: &T) {
6568
unsafe {
6669
let addr = ptr::from_ref(address).cast::<c_void>();
6770
c::WakeByAddressSingle(addr);
6871
}
6972
}
7073

71-
pub fn wake_by_address_all<T>(address: &T) {
74+
pub fn wake_by_address_all<T: Futex>(address: &T) {
7275
unsafe {
7376
let addr = ptr::from_ref(address).cast::<c_void>();
7477
c::WakeByAddressAll(addr);
@@ -80,11 +83,11 @@ pub fn futex_wait<W: Waitable>(futex: &W::Atomic, expected: W, timeout: Option<D
8083
wait_on_address(futex, expected, timeout) || api::get_last_error() != WinError::TIMEOUT
8184
}
8285

83-
pub fn futex_wake<T>(futex: &T) -> bool {
86+
pub fn futex_wake<T: Futex>(futex: &T) -> bool {
8487
wake_by_address_single(futex);
8588
false
8689
}
8790

88-
pub fn futex_wake_all<T>(futex: &T) {
91+
pub fn futex_wake_all<T: Futex>(futex: &T) {
8992
wake_by_address_all(futex)
9093
}

‎std/src/sys/sync/once/futex.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl<'a> Drop for CompletionGuard<'a> {
5757
// up on the Once. `futex_wake_all` does its own synchronization, hence
5858
// we do not need `AcqRel`.
5959
if self.state.swap(self.set_state_on_drop_to, Release) == QUEUED {
60-
futex_wake_all(&self.state);
60+
futex_wake_all(self.state);
6161
}
6262
}
6363
}

0 commit comments

Comments
 (0)
Failed to load comments.