Rollup merge of #127807 - ChrisDenton:win-parking, r=joboet

Use futex.rs for Windows thread parking

If I'm not overlooking anything then the Windows 10+ thread parking implementation is practically the same as the futex.rs implementation. So we may as well use the same implementation for both. The old version is still kept around for Windows 7 support.

r? ````@joboet```` if you wouldn't mind double checking I've not missed something
This commit is contained in:
Trevor Gross 2024-07-16 20:10:12 -05:00 committed by GitHub
commit 446e0177ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 38 additions and 25 deletions

View file

@ -3,6 +3,11 @@ use crate::ptr::null;
use crate::sync::atomic::AtomicU32;
use crate::time::Duration;
/// An atomic for use as a futex that is at least 8-bits but may be larger.
pub type SmallAtomic = AtomicU32;
/// Must be the underlying type of SmallAtomic
pub type SmallPrimitive = u32;
pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
// Calculate the timeout as a relative timespec.
//

View file

@ -11,6 +11,11 @@
use crate::sync::atomic::AtomicU32;
use crate::time::Duration;
/// An atomic for use as a futex that is at least 8-bits but may be larger.
pub type SmallAtomic = AtomicU32;
/// Must be the underlying type of SmallAtomic
pub type SmallPrimitive = u32;
/// Wait for a futex_wake operation to wake us.
///
/// Returns directly if the futex doesn't hold the expected value.

View file

@ -6,6 +6,11 @@ use core::arch::wasm64 as wasm;
use crate::sync::atomic::AtomicU32;
use crate::time::Duration;
/// An atomic for use as a futex that is at least 8-bits but may be larger.
pub type SmallAtomic = AtomicU32;
/// Must be the underlying type of SmallAtomic
pub type SmallPrimitive = u32;
/// Wait for a futex_wake operation to wake us.
///
/// Returns directly if the futex doesn't hold the expected value.

View file

@ -10,6 +10,11 @@ use core::sync::atomic::{
};
use core::time::Duration;
/// An atomic for use as a futex that is at least 8-bits but may be larger.
pub type SmallAtomic = AtomicU8;
/// Must be the underlying type of SmallAtomic
pub type SmallPrimitive = u8;
pub unsafe trait Waitable {
type Atomic;
}

View file

@ -1,19 +1,8 @@
use crate::sync::atomic::{
self,
Ordering::{Acquire, Relaxed, Release},
};
use crate::sys::futex::{futex_wait, futex_wake};
use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use crate::sys::futex::{self, futex_wait, futex_wake};
cfg_if::cfg_if! {
if #[cfg(windows)] {
// On Windows we can have a smol futex
type Atomic = atomic::AtomicU8;
type State = u8;
} else {
type Atomic = atomic::AtomicU32;
type State = u32;
}
}
type Atomic = futex::SmallAtomic;
type State = futex::SmallPrimitive;
pub struct Mutex {
futex: Atomic,

View file

@ -1,15 +1,18 @@
#![forbid(unsafe_op_in_unsafe_fn)]
use crate::pin::Pin;
use crate::sync::atomic::AtomicU32;
use crate::sync::atomic::Ordering::{Acquire, Release};
use crate::sys::futex::{futex_wait, futex_wake};
use crate::sys::futex::{self, futex_wait, futex_wake};
use crate::time::Duration;
const PARKED: u32 = u32::MAX;
const EMPTY: u32 = 0;
const NOTIFIED: u32 = 1;
type Atomic = futex::SmallAtomic;
type State = futex::SmallPrimitive;
const PARKED: State = State::MAX;
const EMPTY: State = 0;
const NOTIFIED: State = 1;
pub struct Parker {
state: AtomicU32,
state: Atomic,
}
// Notes about memory ordering:
@ -36,7 +39,7 @@ impl Parker {
/// Construct the futex parker. The UNIX parker implementation
/// requires this to happen in-place.
pub unsafe fn new_in_place(parker: *mut Parker) {
parker.write(Self { state: AtomicU32::new(EMPTY) });
unsafe { parker.write(Self { state: Atomic::new(EMPTY) }) };
}
// Assumes this is only called by the thread that owns the Parker,

View file

@ -1,5 +1,6 @@
cfg_if::cfg_if! {
if #[cfg(any(
all(target_os = "windows", not(target_vendor = "win7")),
target_os = "linux",
target_os = "android",
all(target_arch = "wasm32", target_feature = "atomics"),
@ -18,9 +19,9 @@ cfg_if::cfg_if! {
))] {
mod id;
pub use id::Parker;
} else if #[cfg(target_os = "windows")] {
mod windows;
pub use windows::Parker;
} else if #[cfg(target_vendor = "win7")] {
mod windows7;
pub use windows7::Parker;
} else if #[cfg(all(target_vendor = "apple", not(miri)))] {
mod darwin;
pub use darwin::Parker;