Use futex.rs for Windows thread parking

This commit is contained in:
Chris Denton 2024-07-16 10:08:26 +00:00
parent 2823cfb1e5
commit 51bdcf66d3
No known key found for this signature in database
GPG Key ID: 713472F2F45627DE
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::sync::atomic::AtomicU32;
use crate::time::Duration; 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 { pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
// Calculate the timeout as a relative timespec. // Calculate the timeout as a relative timespec.
// //

View File

@ -11,6 +11,11 @@
use crate::sync::atomic::AtomicU32; use crate::sync::atomic::AtomicU32;
use crate::time::Duration; 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. /// Wait for a futex_wake operation to wake us.
/// ///
/// Returns directly if the futex doesn't hold the expected value. /// 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::sync::atomic::AtomicU32;
use crate::time::Duration; 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. /// Wait for a futex_wake operation to wake us.
/// ///
/// Returns directly if the futex doesn't hold the expected value. /// 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; 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 { pub unsafe trait Waitable {
type Atomic; type Atomic;
} }

View File

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

View File

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

View File

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