summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cargo_vcs_info.json7
-rw-r--r--Android.bp42
-rw-r--r--Cargo.toml28
-rw-r--r--Cargo.toml.orig19
-rw-r--r--METADATA10
-rw-r--r--TEST_MAPPING12
-rw-r--r--build.rs10
-rw-r--r--cargo2android.json11
-rw-r--r--src/lib.rs2
-rw-r--r--src/parking_lot.rs38
-rw-r--r--src/spinwait.rs4
-rw-r--r--src/thread_parker/generic.rs9
-rw-r--r--src/thread_parker/linux.rs2
-rw-r--r--src/thread_parker/mod.rs6
-rw-r--r--src/thread_parker/redox.rs2
-rw-r--r--src/thread_parker/sgx.rs2
-rw-r--r--src/thread_parker/unix.rs2
-rw-r--r--src/thread_parker/wasm.rs2
-rw-r--r--src/thread_parker/wasm_atomic.rs32
-rw-r--r--src/thread_parker/windows/keyed_event.rs78
-rw-r--r--src/thread_parker/windows/mod.rs4
-rw-r--r--src/thread_parker/windows/waitaddress.rs61
-rw-r--r--src/word_lock.rs17
23 files changed, 197 insertions, 203 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index ec3f28f..b278af6 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,5 @@
{
"git": {
- "sha1": "847b5cab64fe3a87f853de0cac479d78e5a7ee77"
- },
- "path_in_vcs": "core"
-} \ No newline at end of file
+ "sha1": "f3ea9e2082735525e84b30acd39c3f1d9d845c9a"
+ }
+}
diff --git a/Android.bp b/Android.bp
index 8ae1551..dee3192 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,5 +1,4 @@
-// This file is generated by cargo2android.py --config cargo2android.json.
-// Do not modify this file as changes will be overridden on upgrade.
+// This file is generated by cargo2android.py --run --device --dependencies --tests.
package {
default_applicable_licenses: [
@@ -43,39 +42,46 @@ rust_library {
name: "libparking_lot_core",
host_supported: true,
crate_name: "parking_lot_core",
- cargo_env_compat: true,
- cargo_pkg_version: "0.9.1",
srcs: ["src/lib.rs"],
edition: "2018",
rustlibs: [
"libcfg_if",
+ "libinstant",
"liblibc",
"libsmallvec",
],
- apex_available: [
- "//apex_available:platform",
- "com.android.bluetooth",
- "com.android.virt",
- ],
- min_sdk_version: "29",
}
-rust_test {
- name: "parking_lot_core_test_src_lib",
- host_supported: true,
+rust_defaults {
+ name: "parking_lot_core_defaults",
crate_name: "parking_lot_core",
- cargo_env_compat: true,
- cargo_pkg_version: "0.9.1",
srcs: ["src/lib.rs"],
test_suites: ["general-tests"],
auto_gen_config: true,
- test_options: {
- unit_test: true,
- },
edition: "2018",
rustlibs: [
"libcfg_if",
+ "libinstant",
"liblibc",
"libsmallvec",
],
}
+
+rust_test_host {
+ name: "parking_lot_core_host_test_src_lib",
+ defaults: ["parking_lot_core_defaults"],
+ test_options: {
+ unit_test: true,
+ },
+}
+
+rust_test {
+ name: "parking_lot_core_device_test_src_lib",
+ defaults: ["parking_lot_core_defaults"],
+}
+
+// dependent_library ["feature_list"]
+// cfg-if-1.0.0
+// instant-0.1.9
+// libc-0.2.86 "default,std"
+// smallvec-1.6.1
diff --git a/Cargo.toml b/Cargo.toml
index 2fdf5e8..a9184c2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,16 +3,17 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies.
+# to registry (e.g., crates.io) dependencies
#
-# If you are reading this file be aware that the original Cargo.toml
-# will likely look very different (and much more reasonable).
-# See Cargo.toml.orig for the original contents.
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
[package]
edition = "2018"
name = "parking_lot_core"
-version = "0.9.1"
+version = "0.8.3"
authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
description = "An advanced API for creating custom synchronization primitives."
keywords = ["mutex", "condvar", "rwlock", "once", "thread"]
@@ -20,12 +21,15 @@ categories = ["concurrency"]
license = "Apache-2.0/MIT"
repository = "https://github.com/Amanieu/parking_lot"
[dependencies.backtrace]
-version = "0.3.60"
+version = "0.3.49"
optional = true
[dependencies.cfg-if]
version = "1.0.0"
+[dependencies.instant]
+version = "0.1.4"
+
[dependencies.petgraph]
version = "0.5.1"
optional = true
@@ -34,16 +38,16 @@ optional = true
version = "1.6.1"
[dependencies.thread-id]
-version = "4.0.0"
+version = "3.3.0"
optional = true
[features]
deadlock_detection = ["petgraph", "thread-id", "backtrace"]
nightly = []
[target."cfg(target_os = \"redox\")".dependencies.redox_syscall]
-version = "0.2.8"
+version = "0.2.4"
[target."cfg(unix)".dependencies.libc]
-version = "0.2.95"
-[target."cfg(windows)".dependencies.windows-sys]
-version = "0.32"
-features = ["Win32_Foundation", "Win32_System_LibraryLoader", "Win32_System_SystemServices", "Win32_System_WindowsProgramming"]
+version = "0.2.71"
+[target."cfg(windows)".dependencies.winapi]
+version = "0.3.8"
+features = ["winnt", "ntstatus", "minwindef", "winerror", "winbase", "errhandlingapi", "handleapi"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index f053e45..e4af2fc 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "parking_lot_core"
-version = "0.9.1"
+version = "0.8.3"
authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
description = "An advanced API for creating custom synchronization primitives."
license = "Apache-2.0/MIT"
@@ -13,22 +13,19 @@ edition = "2018"
cfg-if = "1.0.0"
smallvec = "1.6.1"
petgraph = { version = "0.5.1", optional = true }
-thread-id = { version = "4.0.0", optional = true }
-backtrace = { version = "0.3.60", optional = true }
+thread-id = { version = "3.3.0", optional = true }
+backtrace = { version = "0.3.49", optional = true }
+instant = "0.1.4"
[target.'cfg(unix)'.dependencies]
-libc = "0.2.95"
+libc = "0.2.71"
[target.'cfg(target_os = "redox")'.dependencies]
-redox_syscall = "0.2.8"
+redox_syscall = "0.2.4"
[target.'cfg(windows)'.dependencies]
-windows-sys = { version = "0.32", features = [
- "Win32_Foundation",
- "Win32_System_LibraryLoader",
- "Win32_System_SystemServices",
- "Win32_System_WindowsProgramming",
-] }
+winapi = { version = "0.3.8", features = ["winnt", "ntstatus", "minwindef",
+ "winerror", "winbase", "errhandlingapi", "handleapi"] }
[features]
nightly = []
diff --git a/METADATA b/METADATA
index 138cd87..a3eea08 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/parking_lot_core/parking_lot_core-0.9.1.crate"
+ value: "https://static.crates.io/crates/parking_lot_core/parking_lot_core-0.8.3.crate"
}
- version: "0.9.1"
+ version: "0.8.3"
license_type: NOTICE
last_upgrade_date {
- year: 2022
- month: 3
- day: 1
+ year: 2021
+ month: 2
+ day: 12
}
}
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 9284a57..98e9fcf 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,18 +1,8 @@
// Generated by update_crate_tests.py for tests that depend on this crate.
{
- "imports": [
- {
- "path": "external/rust/crates/vulkano"
- }
- ],
"presubmit": [
{
- "name": "parking_lot_core_test_src_lib"
- }
- ],
- "presubmit-rust": [
- {
- "name": "parking_lot_core_test_src_lib"
+ "name": "parking_lot_core_device_test_src_lib"
}
]
}
diff --git a/build.rs b/build.rs
deleted file mode 100644
index d29c769..0000000
--- a/build.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Automatically detect tsan in a way that's compatible with both stable (which
-// doesn't support sanitizers) and nightly (which does). Works because build
-// scripts gets `cfg` info, even if the cfg is unstable.
-fn main() {
- println!("cargo:rerun-if-changed=build.rs");
- let santizer_list = std::env::var("CARGO_CFG_SANITIZE").unwrap_or_default();
- if santizer_list.contains("thread") {
- println!("cargo:rustc-cfg=tsan_enabled");
- }
-}
diff --git a/cargo2android.json b/cargo2android.json
deleted file mode 100644
index 22531ba..0000000
--- a/cargo2android.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "apex-available": [
- "//apex_available:platform",
- "com.android.bluetooth",
- "com.android.virt"
- ],
- "device": true,
- "min-sdk-version": "29",
- "run": true,
- "tests": true
-}
diff --git a/src/lib.rs b/src/lib.rs
index 4845356..27087f4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -46,7 +46,7 @@
#![cfg_attr(
all(
feature = "nightly",
- target_family = "wasm",
+ target_arch = "wasm32",
target_feature = "atomics"
),
feature(stdsimd)
diff --git a/src/parking_lot.rs b/src/parking_lot.rs
index 9b84525..519ce9e 100644
--- a/src/parking_lot.rs
+++ b/src/parking_lot.rs
@@ -12,33 +12,9 @@ use core::{
ptr,
sync::atomic::{AtomicPtr, AtomicUsize, Ordering},
};
+use instant::Instant;
use smallvec::SmallVec;
-use std::time::{Duration, Instant};
-
-// Don't use Instant on wasm32-unknown-unknown, it just panics.
-cfg_if::cfg_if! {
- if #[cfg(all(
- target_family = "wasm",
- target_os = "unknown",
- target_vendor = "unknown"
- ))] {
- #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
- struct TimeoutInstant;
- impl TimeoutInstant {
- fn now() -> TimeoutInstant {
- TimeoutInstant
- }
- }
- impl core::ops::Add<Duration> for TimeoutInstant {
- type Output = Self;
- fn add(self, _rhs: Duration) -> Self::Output {
- TimeoutInstant
- }
- }
- } else {
- use std::time::Instant as TimeoutInstant;
- }
-}
+use std::time::Duration;
static NUM_THREADS: AtomicUsize = AtomicUsize::new(0);
@@ -71,7 +47,7 @@ impl HashTable {
let new_size = (num_threads * LOAD_FACTOR).next_power_of_two();
let hash_bits = 0usize.leading_zeros() - new_size.leading_zeros() - 1;
- let now = TimeoutInstant::now();
+ let now = Instant::now();
let mut entries = Vec::with_capacity(new_size);
for i in 0..new_size {
// We must ensure the seed is not zero
@@ -101,7 +77,7 @@ struct Bucket {
impl Bucket {
#[inline]
- pub fn new(timeout: TimeoutInstant, seed: u32) -> Self {
+ pub fn new(timeout: Instant, seed: u32) -> Self {
Self {
mutex: WordLock::new(),
queue_head: Cell::new(ptr::null()),
@@ -113,7 +89,7 @@ impl Bucket {
struct FairTimeout {
// Next time at which point be_fair should be set
- timeout: TimeoutInstant,
+ timeout: Instant,
// the PRNG state for calculating the next timeout
seed: u32,
@@ -121,14 +97,14 @@ struct FairTimeout {
impl FairTimeout {
#[inline]
- fn new(timeout: TimeoutInstant, seed: u32) -> FairTimeout {
+ fn new(timeout: Instant, seed: u32) -> FairTimeout {
FairTimeout { timeout, seed }
}
// Determine whether we should force a fair unlock, and update the timeout
#[inline]
fn should_timeout(&mut self) -> bool {
- let now = TimeoutInstant::now();
+ let now = Instant::now();
if now > self.timeout {
// Time between 0 and 1ms.
let nanos = self.gen_u32() % 1_000_000;
diff --git a/src/spinwait.rs b/src/spinwait.rs
index a57f4c1..ad0327a 100644
--- a/src/spinwait.rs
+++ b/src/spinwait.rs
@@ -6,14 +6,14 @@
// copied, modified, or distributed except according to those terms.
use crate::thread_parker;
-use core::hint::spin_loop;
+use std::sync::atomic::spin_loop_hint;
// Wastes some CPU time for the given number of iterations,
// using a hint to indicate to the CPU that we are spinning.
#[inline]
fn cpu_relax(iterations: u32) {
for _ in 0..iterations {
- spin_loop()
+ spin_loop_hint()
}
}
diff --git a/src/thread_parker/generic.rs b/src/thread_parker/generic.rs
index 990bcb7..5236e14 100644
--- a/src/thread_parker/generic.rs
+++ b/src/thread_parker/generic.rs
@@ -8,10 +8,9 @@
//! A simple spin lock based thread parker. Used on platforms without better
//! parking facilities available.
-use core::sync::atomic::{AtomicBool, Ordering};
-use core::hint::spin_loop;
+use core::sync::atomic::{spin_loop_hint, AtomicBool, Ordering};
+use instant::Instant;
use std::thread;
-use std::time::Instant;
// Helper type for putting a thread to sleep until some other thread wakes it up
pub struct ThreadParker {
@@ -43,7 +42,7 @@ impl super::ThreadParkerT for ThreadParker {
#[inline]
unsafe fn park(&self) {
while self.parked.load(Ordering::Acquire) != false {
- spin_loop();
+ spin_loop_hint();
}
}
@@ -53,7 +52,7 @@ impl super::ThreadParkerT for ThreadParker {
if Instant::now() >= timeout {
return false;
}
- spin_loop();
+ spin_loop_hint();
}
true
}
diff --git a/src/thread_parker/linux.rs b/src/thread_parker/linux.rs
index 5d4e229..766e63b 100644
--- a/src/thread_parker/linux.rs
+++ b/src/thread_parker/linux.rs
@@ -9,9 +9,9 @@ use core::{
ptr,
sync::atomic::{AtomicI32, Ordering},
};
+use instant::Instant;
use libc;
use std::thread;
-use std::time::Instant;
// x32 Linux uses a non-standard type for tv_nsec in timespec.
// See https://sourceware.org/bugzilla/show_bug.cgi?id=16437
diff --git a/src/thread_parker/mod.rs b/src/thread_parker/mod.rs
index fc162f4..a7e4bb6 100644
--- a/src/thread_parker/mod.rs
+++ b/src/thread_parker/mod.rs
@@ -1,5 +1,5 @@
use cfg_if::cfg_if;
-use std::time::Instant;
+use instant::Instant;
/// Trait for the platform thread parker implementation.
///
@@ -68,12 +68,12 @@ cfg_if! {
mod imp;
} else if #[cfg(all(
feature = "nightly",
- target_family = "wasm",
+ target_arch = "wasm32",
target_feature = "atomics"
))] {
#[path = "wasm_atomic.rs"]
mod imp;
- } else if #[cfg(target_family = "wasm")] {
+ } else if #[cfg(target_arch = "wasm32")] {
#[path = "wasm.rs"]
mod imp;
} else {
diff --git a/src/thread_parker/redox.rs b/src/thread_parker/redox.rs
index fdf6bd1..cac06bc 100644
--- a/src/thread_parker/redox.rs
+++ b/src/thread_parker/redox.rs
@@ -9,8 +9,8 @@ use core::{
ptr,
sync::atomic::{AtomicI32, Ordering},
};
+use instant::Instant;
use std::thread;
-use std::time::Instant;
use syscall::{
call::futex,
data::TimeSpec,
diff --git a/src/thread_parker/sgx.rs b/src/thread_parker/sgx.rs
index bc76fe7..341efe2 100644
--- a/src/thread_parker/sgx.rs
+++ b/src/thread_parker/sgx.rs
@@ -6,7 +6,7 @@
// copied, modified, or distributed except according to those terms.
use core::sync::atomic::{AtomicBool, Ordering};
-use std::time::Instant;
+use instant::Instant;
use std::{
io,
os::fortanix_sgx::{
diff --git a/src/thread_parker/unix.rs b/src/thread_parker/unix.rs
index c52ead9..c2381e6 100644
--- a/src/thread_parker/unix.rs
+++ b/src/thread_parker/unix.rs
@@ -11,8 +11,8 @@ use core::{
cell::{Cell, UnsafeCell},
mem::MaybeUninit,
};
+use instant::Instant;
use libc;
-use std::time::Instant;
use std::{thread, time::Duration};
// x32 Linux uses a non-standard type for tv_nsec in timespec.
diff --git a/src/thread_parker/wasm.rs b/src/thread_parker/wasm.rs
index 657425f..ba4118c 100644
--- a/src/thread_parker/wasm.rs
+++ b/src/thread_parker/wasm.rs
@@ -8,8 +8,8 @@
//! The wasm platform can't park when atomic support is not available.
//! So this ThreadParker just panics on any attempt to park.
+use instant::Instant;
use std::thread;
-use std::time::Instant;
pub struct ThreadParker(());
diff --git a/src/thread_parker/wasm_atomic.rs b/src/thread_parker/wasm_atomic.rs
index f332aff..2128e93 100644
--- a/src/thread_parker/wasm_atomic.rs
+++ b/src/thread_parker/wasm_atomic.rs
@@ -5,13 +5,41 @@
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
+use cfg_if::cfg_if;
use core::{
arch::wasm32,
sync::atomic::{AtomicI32, Ordering},
};
-use std::time::{Duration, Instant};
+use instant::Instant;
+use std::time::Duration;
use std::{convert::TryFrom, thread};
+cfg_if! {
+ if #[cfg(all(
+ target_arch = "wasm32",
+ target_os = "unknown",
+ target_vendor = "unknown"
+ ))] {
+ // This function serves as a polyfill for `Instant::checked_duration_since`, which is
+ // currently not implemented for wasm32-unknown-unknown.
+ // TODO: Remove this shim once it
+ fn checked_duration_since_now(other: Instant) -> Option<Duration> {
+ let now = Instant::now();
+
+ if other < now {
+ None
+ } else {
+ Some(other.duration_since(now))
+ }
+ }
+ } else {
+ // If we are not targeting wasm32, we can use the native `checked_duration_since`.
+ fn checked_duration_since_now(timeout: Instant) -> Option<Duration> {
+ timeout.checked_duration_since(Instant::now())
+ }
+ }
+}
+
// Helper type for putting a thread to sleep until some other thread wakes it up
pub struct ThreadParker {
parked: AtomicI32,
@@ -55,7 +83,7 @@ impl super::ThreadParkerT for ThreadParker {
#[inline]
unsafe fn park_until(&self, timeout: Instant) -> bool {
while self.parked.load(Ordering::Acquire) == PARKED {
- if let Some(left) = timeout.checked_duration_since(Instant::now()) {
+ if let Some(left) = checked_duration_since_now(timeout) {
let nanos_left = i64::try_from(left.as_nanos()).unwrap_or(i64::max_value());
let r = wasm32::memory_atomic_wait32(self.ptr(), PARKED, nanos_left);
debug_assert!(r == 0 || r == 1 || r == 2);
diff --git a/src/thread_parker/windows/keyed_event.rs b/src/thread_parker/windows/keyed_event.rs
index bbe45a4..7c37153 100644
--- a/src/thread_parker/windows/keyed_event.rs
+++ b/src/thread_parker/windows/keyed_event.rs
@@ -6,18 +6,24 @@
// copied, modified, or distributed except according to those terms.
use core::{
- ffi,
mem::{self, MaybeUninit},
ptr,
};
+use instant::Instant;
use std::sync::atomic::{AtomicUsize, Ordering};
-use std::time::Instant;
-
-use windows_sys::Win32::{
- Foundation::{CloseHandle, BOOLEAN, HANDLE, NTSTATUS, STATUS_SUCCESS, STATUS_TIMEOUT},
- System::{
- LibraryLoader::{GetModuleHandleA, GetProcAddress},
- SystemServices::{GENERIC_READ, GENERIC_WRITE},
+use winapi::{
+ shared::{
+ minwindef::{TRUE, ULONG},
+ ntdef::NTSTATUS,
+ ntstatus::{STATUS_SUCCESS, STATUS_TIMEOUT},
+ },
+ um::{
+ handleapi::CloseHandle,
+ libloaderapi::{GetModuleHandleA, GetProcAddress},
+ winnt::{
+ ACCESS_MASK, BOOLEAN, GENERIC_READ, GENERIC_WRITE, HANDLE, LARGE_INTEGER, LPCSTR,
+ PHANDLE, PLARGE_INTEGER, PVOID,
+ },
},
};
@@ -30,49 +36,58 @@ pub struct KeyedEvent {
handle: HANDLE,
NtReleaseKeyedEvent: extern "system" fn(
EventHandle: HANDLE,
- Key: *mut ffi::c_void,
+ Key: PVOID,
Alertable: BOOLEAN,
- Timeout: *mut i64,
+ Timeout: PLARGE_INTEGER,
) -> NTSTATUS,
NtWaitForKeyedEvent: extern "system" fn(
EventHandle: HANDLE,
- Key: *mut ffi::c_void,
+ Key: PVOID,
Alertable: BOOLEAN,
- Timeout: *mut i64,
+ Timeout: PLARGE_INTEGER,
) -> NTSTATUS,
}
impl KeyedEvent {
#[inline]
- unsafe fn wait_for(&self, key: *mut ffi::c_void, timeout: *mut i64) -> NTSTATUS {
- (self.NtWaitForKeyedEvent)(self.handle, key, false.into(), timeout)
+ unsafe fn wait_for(&self, key: PVOID, timeout: PLARGE_INTEGER) -> NTSTATUS {
+ (self.NtWaitForKeyedEvent)(self.handle, key, 0, timeout)
}
#[inline]
- unsafe fn release(&self, key: *mut ffi::c_void) -> NTSTATUS {
- (self.NtReleaseKeyedEvent)(self.handle, key, false.into(), ptr::null_mut())
+ unsafe fn release(&self, key: PVOID) -> NTSTATUS {
+ (self.NtReleaseKeyedEvent)(self.handle, key, 0, ptr::null_mut())
}
#[allow(non_snake_case)]
pub fn create() -> Option<KeyedEvent> {
unsafe {
- let ntdll = GetModuleHandleA(b"ntdll.dll\0".as_ptr());
- if ntdll == 0 {
+ let ntdll = GetModuleHandleA(b"ntdll.dll\0".as_ptr() as LPCSTR);
+ if ntdll.is_null() {
return None;
}
let NtCreateKeyedEvent =
- GetProcAddress(ntdll, b"NtCreateKeyedEvent\0".as_ptr())?;
+ GetProcAddress(ntdll, b"NtCreateKeyedEvent\0".as_ptr() as LPCSTR);
+ if NtCreateKeyedEvent.is_null() {
+ return None;
+ }
let NtReleaseKeyedEvent =
- GetProcAddress(ntdll, b"NtReleaseKeyedEvent\0".as_ptr())?;
+ GetProcAddress(ntdll, b"NtReleaseKeyedEvent\0".as_ptr() as LPCSTR);
+ if NtReleaseKeyedEvent.is_null() {
+ return None;
+ }
let NtWaitForKeyedEvent =
- GetProcAddress(ntdll, b"NtWaitForKeyedEvent\0".as_ptr())?;
+ GetProcAddress(ntdll, b"NtWaitForKeyedEvent\0".as_ptr() as LPCSTR);
+ if NtWaitForKeyedEvent.is_null() {
+ return None;
+ }
let NtCreateKeyedEvent: extern "system" fn(
- KeyedEventHandle: *mut HANDLE,
- DesiredAccess: u32,
- ObjectAttributes: *mut ffi::c_void,
- Flags: u32,
+ KeyedEventHandle: PHANDLE,
+ DesiredAccess: ACCESS_MASK,
+ ObjectAttributes: PVOID,
+ Flags: ULONG,
) -> NTSTATUS = mem::transmute(NtCreateKeyedEvent);
let mut handle = MaybeUninit::uninit();
let status = NtCreateKeyedEvent(
@@ -105,7 +120,7 @@ impl KeyedEvent {
#[inline]
pub unsafe fn park(&'static self, key: &AtomicUsize) {
- let status = self.wait_for(key as *const _ as *mut ffi::c_void, ptr::null_mut());
+ let status = self.wait_for(key as *const _ as PVOID, ptr::null_mut());
debug_assert_eq!(status, STATUS_SUCCESS);
}
@@ -125,13 +140,14 @@ impl KeyedEvent {
// NT uses a timeout in units of 100ns. We use a negative value to
// indicate a relative timeout based on a monotonic clock.
+ let mut nt_timeout: LARGE_INTEGER = mem::zeroed();
let diff = timeout - now;
let value = (diff.as_secs() as i64)
.checked_mul(-10000000)
.and_then(|x| x.checked_sub((diff.subsec_nanos() as i64 + 99) / 100));
- let mut nt_timeout = match value {
- Some(x) => x,
+ match value {
+ Some(x) => *nt_timeout.QuadPart_mut() = x,
None => {
// Timeout overflowed, just sleep indefinitely
self.park(key);
@@ -139,7 +155,7 @@ impl KeyedEvent {
}
};
- let status = self.wait_for(key as *const _ as *mut ffi::c_void, &mut nt_timeout);
+ let status = self.wait_for(key as *const _ as PVOID, &mut nt_timeout);
if status == STATUS_SUCCESS {
return true;
}
@@ -176,7 +192,7 @@ impl Drop for KeyedEvent {
fn drop(&mut self) {
unsafe {
let ok = CloseHandle(self.handle);
- debug_assert_eq!(ok, true.into());
+ debug_assert_eq!(ok, TRUE);
}
}
}
@@ -195,7 +211,7 @@ impl UnparkHandle {
#[inline]
pub unsafe fn unpark(self) {
if !self.key.is_null() {
- let status = self.keyed_event.release(self.key as *mut ffi::c_void);
+ let status = self.keyed_event.release(self.key as PVOID);
debug_assert_eq!(status, STATUS_SUCCESS);
}
}
diff --git a/src/thread_parker/windows/mod.rs b/src/thread_parker/windows/mod.rs
index 1f5ed23..76dbb5d 100644
--- a/src/thread_parker/windows/mod.rs
+++ b/src/thread_parker/windows/mod.rs
@@ -9,7 +9,7 @@ use core::{
ptr,
sync::atomic::{AtomicPtr, AtomicUsize, Ordering},
};
-use std::time::Instant;
+use instant::Instant;
mod keyed_event;
mod waitaddress;
@@ -177,7 +177,7 @@ pub fn thread_yield() {
// libraries, but that'll probably take a lot longer than patching this here
// and avoiding the `synchapi` feature entirely.
extern "system" {
- fn Sleep(a: u32);
+ fn Sleep(a: winapi::shared::minwindef::DWORD);
}
unsafe {
// We don't use SwitchToThread here because it doesn't consider all
diff --git a/src/thread_parker/windows/waitaddress.rs b/src/thread_parker/windows/waitaddress.rs
index dde0db7..862c5c6 100644
--- a/src/thread_parker/windows/waitaddress.rs
+++ b/src/thread_parker/windows/waitaddress.rs
@@ -9,24 +9,30 @@ use core::{
mem,
sync::atomic::{AtomicUsize, Ordering},
};
-use std::{ffi, time::Instant};
-use windows_sys::Win32::{
- Foundation::{GetLastError, BOOL, ERROR_TIMEOUT},
- System::{
- LibraryLoader::{GetModuleHandleA, GetProcAddress},
- WindowsProgramming::INFINITE,
+use instant::Instant;
+use winapi::{
+ shared::{
+ basetsd::SIZE_T,
+ minwindef::{BOOL, DWORD, FALSE, TRUE},
+ winerror::ERROR_TIMEOUT,
+ },
+ um::{
+ errhandlingapi::GetLastError,
+ libloaderapi::{GetModuleHandleA, GetProcAddress},
+ winbase::INFINITE,
+ winnt::{LPCSTR, PVOID},
},
};
#[allow(non_snake_case)]
pub struct WaitAddress {
WaitOnAddress: extern "system" fn(
- Address: *mut ffi::c_void,
- CompareAddress: *mut ffi::c_void,
- AddressSize: usize,
- dwMilliseconds: u32,
+ Address: PVOID,
+ CompareAddress: PVOID,
+ AddressSize: SIZE_T,
+ dwMilliseconds: DWORD,
) -> BOOL,
- WakeByAddressSingle: extern "system" fn(Address: *mut ffi::c_void),
+ WakeByAddressSingle: extern "system" fn(Address: PVOID),
}
impl WaitAddress {
@@ -36,15 +42,20 @@ impl WaitAddress {
// MSDN claims that that WaitOnAddress and WakeByAddressSingle are
// located in kernel32.dll, but they are lying...
let synch_dll =
- GetModuleHandleA(b"api-ms-win-core-synch-l1-2-0.dll\0".as_ptr());
- if synch_dll == 0 {
+ GetModuleHandleA(b"api-ms-win-core-synch-l1-2-0.dll\0".as_ptr() as LPCSTR);
+ if synch_dll.is_null() {
return None;
}
- let WaitOnAddress = GetProcAddress(synch_dll, b"WaitOnAddress\0".as_ptr())?;
+ let WaitOnAddress = GetProcAddress(synch_dll, b"WaitOnAddress\0".as_ptr() as LPCSTR);
+ if WaitOnAddress.is_null() {
+ return None;
+ }
let WakeByAddressSingle =
- GetProcAddress(synch_dll, b"WakeByAddressSingle\0".as_ptr())?;
-
+ GetProcAddress(synch_dll, b"WakeByAddressSingle\0".as_ptr() as LPCSTR);
+ if WakeByAddressSingle.is_null() {
+ return None;
+ }
Some(WaitAddress {
WaitOnAddress: mem::transmute(WaitOnAddress),
WakeByAddressSingle: mem::transmute(WakeByAddressSingle),
@@ -66,7 +77,7 @@ impl WaitAddress {
pub fn park(&'static self, key: &AtomicUsize) {
while key.load(Ordering::Acquire) != 0 {
let r = self.wait_on_address(key, INFINITE);
- debug_assert!(r == true.into());
+ debug_assert!(r == TRUE);
}
}
@@ -83,14 +94,14 @@ impl WaitAddress {
.checked_mul(1000)
.and_then(|x| x.checked_add((diff.subsec_nanos() as u64 + 999999) / 1000000))
.map(|ms| {
- if ms > std::u32::MAX as u64 {
+ if ms > <DWORD>::max_value() as u64 {
INFINITE
} else {
- ms as u32
+ ms as DWORD
}
})
.unwrap_or(INFINITE);
- if self.wait_on_address(key, timeout) == false.into() {
+ if self.wait_on_address(key, timeout) == FALSE {
debug_assert_eq!(unsafe { GetLastError() }, ERROR_TIMEOUT);
}
}
@@ -109,12 +120,12 @@ impl WaitAddress {
}
#[inline]
- fn wait_on_address(&'static self, key: &AtomicUsize, timeout: u32) -> BOOL {
+ fn wait_on_address(&'static self, key: &AtomicUsize, timeout: DWORD) -> BOOL {
let cmp = 1usize;
(self.WaitOnAddress)(
- key as *const _ as *mut ffi::c_void,
- &cmp as *const _ as *mut ffi::c_void,
- mem::size_of::<usize>(),
+ key as *const _ as PVOID,
+ &cmp as *const _ as PVOID,
+ mem::size_of::<usize>() as SIZE_T,
timeout,
)
}
@@ -133,6 +144,6 @@ impl UnparkHandle {
// released to avoid blocking the queue for too long.
#[inline]
pub fn unpark(self) {
- (self.waitaddress.WakeByAddressSingle)(self.key as *mut ffi::c_void);
+ (self.waitaddress.WakeByAddressSingle)(self.key as PVOID);
}
}
diff --git a/src/word_lock.rs b/src/word_lock.rs
index 1109401..450e985 100644
--- a/src/word_lock.rs
+++ b/src/word_lock.rs
@@ -154,7 +154,7 @@ impl WordLock {
if let Err(x) = self.state.compare_exchange_weak(
state,
state.with_queue_head(thread_data),
- Ordering::AcqRel,
+ Ordering::Release,
Ordering::Relaxed,
) {
return x;
@@ -238,7 +238,7 @@ impl WordLock {
}
// Need an acquire fence before reading the new queue
- fence_acquire(&self.state);
+ fence(Ordering::Acquire);
continue;
}
@@ -263,7 +263,7 @@ impl WordLock {
continue;
} else {
// Need an acquire fence before reading the new queue
- fence_acquire(&self.state);
+ fence(Ordering::Acquire);
continue 'outer;
}
}
@@ -286,17 +286,6 @@ impl WordLock {
}
}
-// Thread-Sanitizer only has partial fence support, so when running under it, we
-// try and avoid false positives by using a discarded acquire load instead.
-#[inline]
-fn fence_acquire(a: &AtomicUsize) {
- if cfg!(tsan_enabled) {
- let _ = a.load(Ordering::Acquire);
- } else {
- fence(Ordering::Acquire);
- }
-}
-
trait LockState {
fn is_locked(self) -> bool;
fn is_queue_locked(self) -> bool;