summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-10 06:57:41 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-10 06:57:41 +0000
commit978c8c40cb8f7fb2cf4d2adf1ad56d3743ec66cf (patch)
tree849d5ded097a262df9792e1bf91ccda3dd0567e0
parentcaa2c63fcf783cfb68c5c7d03ed08bd15d8b278c (diff)
parent6d6dff10c2010df2767139895bd6eedef76ceb48 (diff)
downloadparking_lot_core-android13-mainline-cellbroadcast-release.tar.gz
Change-Id: I941c94c2d3dbe792859d4721d297a53cad880a5e
-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, 203 insertions, 197 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index b278af6..ec3f28f 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
{
"git": {
- "sha1": "f3ea9e2082735525e84b30acd39c3f1d9d845c9a"
- }
-}
+ "sha1": "847b5cab64fe3a87f853de0cac479d78e5a7ee77"
+ },
+ "path_in_vcs": "core"
+} \ No newline at end of file
diff --git a/Android.bp b/Android.bp
index dee3192..8ae1551 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,5 @@
-// This file is generated by cargo2android.py --run --device --dependencies --tests.
+// This file is generated by cargo2android.py --config cargo2android.json.
+// Do not modify this file as changes will be overridden on upgrade.
package {
default_applicable_licenses: [
@@ -42,46 +43,39 @@ 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_defaults {
- name: "parking_lot_core_defaults",
+rust_test {
+ name: "parking_lot_core_test_src_lib",
+ host_supported: true,
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 a9184c2..2fdf5e8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,17 +3,16 @@
# 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 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)
+# 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.
[package]
edition = "2018"
name = "parking_lot_core"
-version = "0.8.3"
+version = "0.9.1"
authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
description = "An advanced API for creating custom synchronization primitives."
keywords = ["mutex", "condvar", "rwlock", "once", "thread"]
@@ -21,15 +20,12 @@ categories = ["concurrency"]
license = "Apache-2.0/MIT"
repository = "https://github.com/Amanieu/parking_lot"
[dependencies.backtrace]
-version = "0.3.49"
+version = "0.3.60"
optional = true
[dependencies.cfg-if]
version = "1.0.0"
-[dependencies.instant]
-version = "0.1.4"
-
[dependencies.petgraph]
version = "0.5.1"
optional = true
@@ -38,16 +34,16 @@ optional = true
version = "1.6.1"
[dependencies.thread-id]
-version = "3.3.0"
+version = "4.0.0"
optional = true
[features]
deadlock_detection = ["petgraph", "thread-id", "backtrace"]
nightly = []
[target."cfg(target_os = \"redox\")".dependencies.redox_syscall]
-version = "0.2.4"
+version = "0.2.8"
[target."cfg(unix)".dependencies.libc]
-version = "0.2.71"
-[target."cfg(windows)".dependencies.winapi]
-version = "0.3.8"
-features = ["winnt", "ntstatus", "minwindef", "winerror", "winbase", "errhandlingapi", "handleapi"]
+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"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index e4af2fc..f053e45 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "parking_lot_core"
-version = "0.8.3"
+version = "0.9.1"
authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
description = "An advanced API for creating custom synchronization primitives."
license = "Apache-2.0/MIT"
@@ -13,19 +13,22 @@ edition = "2018"
cfg-if = "1.0.0"
smallvec = "1.6.1"
petgraph = { version = "0.5.1", optional = true }
-thread-id = { version = "3.3.0", optional = true }
-backtrace = { version = "0.3.49", optional = true }
-instant = "0.1.4"
+thread-id = { version = "4.0.0", optional = true }
+backtrace = { version = "0.3.60", optional = true }
[target.'cfg(unix)'.dependencies]
-libc = "0.2.71"
+libc = "0.2.95"
[target.'cfg(target_os = "redox")'.dependencies]
-redox_syscall = "0.2.4"
+redox_syscall = "0.2.8"
[target.'cfg(windows)'.dependencies]
-winapi = { version = "0.3.8", features = ["winnt", "ntstatus", "minwindef",
- "winerror", "winbase", "errhandlingapi", "handleapi"] }
+windows-sys = { version = "0.32", features = [
+ "Win32_Foundation",
+ "Win32_System_LibraryLoader",
+ "Win32_System_SystemServices",
+ "Win32_System_WindowsProgramming",
+] }
[features]
nightly = []
diff --git a/METADATA b/METADATA
index a3eea08..138cd87 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.8.3.crate"
+ value: "https://static.crates.io/crates/parking_lot_core/parking_lot_core-0.9.1.crate"
}
- version: "0.8.3"
+ version: "0.9.1"
license_type: NOTICE
last_upgrade_date {
- year: 2021
- month: 2
- day: 12
+ year: 2022
+ month: 3
+ day: 1
}
}
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 98e9fcf..9284a57 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,8 +1,18 @@
// Generated by update_crate_tests.py for tests that depend on this crate.
{
+ "imports": [
+ {
+ "path": "external/rust/crates/vulkano"
+ }
+ ],
"presubmit": [
{
- "name": "parking_lot_core_device_test_src_lib"
+ "name": "parking_lot_core_test_src_lib"
+ }
+ ],
+ "presubmit-rust": [
+ {
+ "name": "parking_lot_core_test_src_lib"
}
]
}
diff --git a/build.rs b/build.rs
new file mode 100644
index 0000000..d29c769
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,10 @@
+// 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
new file mode 100644
index 0000000..22531ba
--- /dev/null
+++ b/cargo2android.json
@@ -0,0 +1,11 @@
+{
+ "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 27087f4..4845356 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -46,7 +46,7 @@
#![cfg_attr(
all(
feature = "nightly",
- target_arch = "wasm32",
+ target_family = "wasm",
target_feature = "atomics"
),
feature(stdsimd)
diff --git a/src/parking_lot.rs b/src/parking_lot.rs
index 519ce9e..9b84525 100644
--- a/src/parking_lot.rs
+++ b/src/parking_lot.rs
@@ -12,9 +12,33 @@ use core::{
ptr,
sync::atomic::{AtomicPtr, AtomicUsize, Ordering},
};
-use instant::Instant;
use smallvec::SmallVec;
-use std::time::Duration;
+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;
+ }
+}
static NUM_THREADS: AtomicUsize = AtomicUsize::new(0);
@@ -47,7 +71,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 = Instant::now();
+ let now = TimeoutInstant::now();
let mut entries = Vec::with_capacity(new_size);
for i in 0..new_size {
// We must ensure the seed is not zero
@@ -77,7 +101,7 @@ struct Bucket {
impl Bucket {
#[inline]
- pub fn new(timeout: Instant, seed: u32) -> Self {
+ pub fn new(timeout: TimeoutInstant, seed: u32) -> Self {
Self {
mutex: WordLock::new(),
queue_head: Cell::new(ptr::null()),
@@ -89,7 +113,7 @@ impl Bucket {
struct FairTimeout {
// Next time at which point be_fair should be set
- timeout: Instant,
+ timeout: TimeoutInstant,
// the PRNG state for calculating the next timeout
seed: u32,
@@ -97,14 +121,14 @@ struct FairTimeout {
impl FairTimeout {
#[inline]
- fn new(timeout: Instant, seed: u32) -> FairTimeout {
+ fn new(timeout: TimeoutInstant, 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 = Instant::now();
+ let now = TimeoutInstant::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 ad0327a..a57f4c1 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 std::sync::atomic::spin_loop_hint;
+use core::hint::spin_loop;
// 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_hint()
+ spin_loop()
}
}
diff --git a/src/thread_parker/generic.rs b/src/thread_parker/generic.rs
index 5236e14..990bcb7 100644
--- a/src/thread_parker/generic.rs
+++ b/src/thread_parker/generic.rs
@@ -8,9 +8,10 @@
//! A simple spin lock based thread parker. Used on platforms without better
//! parking facilities available.
-use core::sync::atomic::{spin_loop_hint, AtomicBool, Ordering};
-use instant::Instant;
+use core::sync::atomic::{AtomicBool, Ordering};
+use core::hint::spin_loop;
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 {
@@ -42,7 +43,7 @@ impl super::ThreadParkerT for ThreadParker {
#[inline]
unsafe fn park(&self) {
while self.parked.load(Ordering::Acquire) != false {
- spin_loop_hint();
+ spin_loop();
}
}
@@ -52,7 +53,7 @@ impl super::ThreadParkerT for ThreadParker {
if Instant::now() >= timeout {
return false;
}
- spin_loop_hint();
+ spin_loop();
}
true
}
diff --git a/src/thread_parker/linux.rs b/src/thread_parker/linux.rs
index 766e63b..5d4e229 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 a7e4bb6..fc162f4 100644
--- a/src/thread_parker/mod.rs
+++ b/src/thread_parker/mod.rs
@@ -1,5 +1,5 @@
use cfg_if::cfg_if;
-use instant::Instant;
+use std::time::Instant;
/// Trait for the platform thread parker implementation.
///
@@ -68,12 +68,12 @@ cfg_if! {
mod imp;
} else if #[cfg(all(
feature = "nightly",
- target_arch = "wasm32",
+ target_family = "wasm",
target_feature = "atomics"
))] {
#[path = "wasm_atomic.rs"]
mod imp;
- } else if #[cfg(target_arch = "wasm32")] {
+ } else if #[cfg(target_family = "wasm")] {
#[path = "wasm.rs"]
mod imp;
} else {
diff --git a/src/thread_parker/redox.rs b/src/thread_parker/redox.rs
index cac06bc..fdf6bd1 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 341efe2..bc76fe7 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 instant::Instant;
+use std::time::Instant;
use std::{
io,
os::fortanix_sgx::{
diff --git a/src/thread_parker/unix.rs b/src/thread_parker/unix.rs
index c2381e6..c52ead9 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 ba4118c..657425f 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 2128e93..f332aff 100644
--- a/src/thread_parker/wasm_atomic.rs
+++ b/src/thread_parker/wasm_atomic.rs
@@ -5,41 +5,13 @@
// 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 instant::Instant;
-use std::time::Duration;
+use std::time::{Duration, Instant};
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,
@@ -83,7 +55,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) = checked_duration_since_now(timeout) {
+ if let Some(left) = timeout.checked_duration_since(Instant::now()) {
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 7c37153..bbe45a4 100644
--- a/src/thread_parker/windows/keyed_event.rs
+++ b/src/thread_parker/windows/keyed_event.rs
@@ -6,24 +6,18 @@
// 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 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,
- },
+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},
},
};
@@ -36,58 +30,49 @@ pub struct KeyedEvent {
handle: HANDLE,
NtReleaseKeyedEvent: extern "system" fn(
EventHandle: HANDLE,
- Key: PVOID,
+ Key: *mut ffi::c_void,
Alertable: BOOLEAN,
- Timeout: PLARGE_INTEGER,
+ Timeout: *mut i64,
) -> NTSTATUS,
NtWaitForKeyedEvent: extern "system" fn(
EventHandle: HANDLE,
- Key: PVOID,
+ Key: *mut ffi::c_void,
Alertable: BOOLEAN,
- Timeout: PLARGE_INTEGER,
+ Timeout: *mut i64,
) -> NTSTATUS,
}
impl KeyedEvent {
#[inline]
- unsafe fn wait_for(&self, key: PVOID, timeout: PLARGE_INTEGER) -> NTSTATUS {
- (self.NtWaitForKeyedEvent)(self.handle, key, 0, timeout)
+ unsafe fn wait_for(&self, key: *mut ffi::c_void, timeout: *mut i64) -> NTSTATUS {
+ (self.NtWaitForKeyedEvent)(self.handle, key, false.into(), timeout)
}
#[inline]
- unsafe fn release(&self, key: PVOID) -> NTSTATUS {
- (self.NtReleaseKeyedEvent)(self.handle, key, 0, ptr::null_mut())
+ unsafe fn release(&self, key: *mut ffi::c_void) -> NTSTATUS {
+ (self.NtReleaseKeyedEvent)(self.handle, key, false.into(), ptr::null_mut())
}
#[allow(non_snake_case)]
pub fn create() -> Option<KeyedEvent> {
unsafe {
- let ntdll = GetModuleHandleA(b"ntdll.dll\0".as_ptr() as LPCSTR);
- if ntdll.is_null() {
+ let ntdll = GetModuleHandleA(b"ntdll.dll\0".as_ptr());
+ if ntdll == 0 {
return None;
}
let NtCreateKeyedEvent =
- GetProcAddress(ntdll, b"NtCreateKeyedEvent\0".as_ptr() as LPCSTR);
- if NtCreateKeyedEvent.is_null() {
- return None;
- }
+ GetProcAddress(ntdll, b"NtCreateKeyedEvent\0".as_ptr())?;
let NtReleaseKeyedEvent =
- GetProcAddress(ntdll, b"NtReleaseKeyedEvent\0".as_ptr() as LPCSTR);
- if NtReleaseKeyedEvent.is_null() {
- return None;
- }
+ GetProcAddress(ntdll, b"NtReleaseKeyedEvent\0".as_ptr())?;
let NtWaitForKeyedEvent =
- GetProcAddress(ntdll, b"NtWaitForKeyedEvent\0".as_ptr() as LPCSTR);
- if NtWaitForKeyedEvent.is_null() {
- return None;
- }
+ GetProcAddress(ntdll, b"NtWaitForKeyedEvent\0".as_ptr())?;
let NtCreateKeyedEvent: extern "system" fn(
- KeyedEventHandle: PHANDLE,
- DesiredAccess: ACCESS_MASK,
- ObjectAttributes: PVOID,
- Flags: ULONG,
+ KeyedEventHandle: *mut HANDLE,
+ DesiredAccess: u32,
+ ObjectAttributes: *mut ffi::c_void,
+ Flags: u32,
) -> NTSTATUS = mem::transmute(NtCreateKeyedEvent);
let mut handle = MaybeUninit::uninit();
let status = NtCreateKeyedEvent(
@@ -120,7 +105,7 @@ impl KeyedEvent {
#[inline]
pub unsafe fn park(&'static self, key: &AtomicUsize) {
- let status = self.wait_for(key as *const _ as PVOID, ptr::null_mut());
+ let status = self.wait_for(key as *const _ as *mut ffi::c_void, ptr::null_mut());
debug_assert_eq!(status, STATUS_SUCCESS);
}
@@ -140,14 +125,13 @@ 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));
- match value {
- Some(x) => *nt_timeout.QuadPart_mut() = x,
+ let mut nt_timeout = match value {
+ Some(x) => x,
None => {
// Timeout overflowed, just sleep indefinitely
self.park(key);
@@ -155,7 +139,7 @@ impl KeyedEvent {
}
};
- let status = self.wait_for(key as *const _ as PVOID, &mut nt_timeout);
+ let status = self.wait_for(key as *const _ as *mut ffi::c_void, &mut nt_timeout);
if status == STATUS_SUCCESS {
return true;
}
@@ -192,7 +176,7 @@ impl Drop for KeyedEvent {
fn drop(&mut self) {
unsafe {
let ok = CloseHandle(self.handle);
- debug_assert_eq!(ok, TRUE);
+ debug_assert_eq!(ok, true.into());
}
}
}
@@ -211,7 +195,7 @@ impl UnparkHandle {
#[inline]
pub unsafe fn unpark(self) {
if !self.key.is_null() {
- let status = self.keyed_event.release(self.key as PVOID);
+ let status = self.keyed_event.release(self.key as *mut ffi::c_void);
debug_assert_eq!(status, STATUS_SUCCESS);
}
}
diff --git a/src/thread_parker/windows/mod.rs b/src/thread_parker/windows/mod.rs
index 76dbb5d..1f5ed23 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 instant::Instant;
+use std::time::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: winapi::shared::minwindef::DWORD);
+ fn Sleep(a: u32);
}
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 862c5c6..dde0db7 100644
--- a/src/thread_parker/windows/waitaddress.rs
+++ b/src/thread_parker/windows/waitaddress.rs
@@ -9,30 +9,24 @@ use core::{
mem,
sync::atomic::{AtomicUsize, Ordering},
};
-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},
+use std::{ffi, time::Instant};
+use windows_sys::Win32::{
+ Foundation::{GetLastError, BOOL, ERROR_TIMEOUT},
+ System::{
+ LibraryLoader::{GetModuleHandleA, GetProcAddress},
+ WindowsProgramming::INFINITE,
},
};
#[allow(non_snake_case)]
pub struct WaitAddress {
WaitOnAddress: extern "system" fn(
- Address: PVOID,
- CompareAddress: PVOID,
- AddressSize: SIZE_T,
- dwMilliseconds: DWORD,
+ Address: *mut ffi::c_void,
+ CompareAddress: *mut ffi::c_void,
+ AddressSize: usize,
+ dwMilliseconds: u32,
) -> BOOL,
- WakeByAddressSingle: extern "system" fn(Address: PVOID),
+ WakeByAddressSingle: extern "system" fn(Address: *mut ffi::c_void),
}
impl WaitAddress {
@@ -42,20 +36,15 @@ 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() as LPCSTR);
- if synch_dll.is_null() {
+ GetModuleHandleA(b"api-ms-win-core-synch-l1-2-0.dll\0".as_ptr());
+ if synch_dll == 0 {
return None;
}
- let WaitOnAddress = GetProcAddress(synch_dll, b"WaitOnAddress\0".as_ptr() as LPCSTR);
- if WaitOnAddress.is_null() {
- return None;
- }
+ let WaitOnAddress = GetProcAddress(synch_dll, b"WaitOnAddress\0".as_ptr())?;
let WakeByAddressSingle =
- GetProcAddress(synch_dll, b"WakeByAddressSingle\0".as_ptr() as LPCSTR);
- if WakeByAddressSingle.is_null() {
- return None;
- }
+ GetProcAddress(synch_dll, b"WakeByAddressSingle\0".as_ptr())?;
+
Some(WaitAddress {
WaitOnAddress: mem::transmute(WaitOnAddress),
WakeByAddressSingle: mem::transmute(WakeByAddressSingle),
@@ -77,7 +66,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);
+ debug_assert!(r == true.into());
}
}
@@ -94,14 +83,14 @@ impl WaitAddress {
.checked_mul(1000)
.and_then(|x| x.checked_add((diff.subsec_nanos() as u64 + 999999) / 1000000))
.map(|ms| {
- if ms > <DWORD>::max_value() as u64 {
+ if ms > std::u32::MAX as u64 {
INFINITE
} else {
- ms as DWORD
+ ms as u32
}
})
.unwrap_or(INFINITE);
- if self.wait_on_address(key, timeout) == FALSE {
+ if self.wait_on_address(key, timeout) == false.into() {
debug_assert_eq!(unsafe { GetLastError() }, ERROR_TIMEOUT);
}
}
@@ -120,12 +109,12 @@ impl WaitAddress {
}
#[inline]
- fn wait_on_address(&'static self, key: &AtomicUsize, timeout: DWORD) -> BOOL {
+ fn wait_on_address(&'static self, key: &AtomicUsize, timeout: u32) -> BOOL {
let cmp = 1usize;
(self.WaitOnAddress)(
- key as *const _ as PVOID,
- &cmp as *const _ as PVOID,
- mem::size_of::<usize>() as SIZE_T,
+ key as *const _ as *mut ffi::c_void,
+ &cmp as *const _ as *mut ffi::c_void,
+ mem::size_of::<usize>(),
timeout,
)
}
@@ -144,6 +133,6 @@ impl UnparkHandle {
// released to avoid blocking the queue for too long.
#[inline]
pub fn unpark(self) {
- (self.waitaddress.WakeByAddressSingle)(self.key as PVOID);
+ (self.waitaddress.WakeByAddressSingle)(self.key as *mut ffi::c_void);
}
}
diff --git a/src/word_lock.rs b/src/word_lock.rs
index 450e985..1109401 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::Release,
+ Ordering::AcqRel,
Ordering::Relaxed,
) {
return x;
@@ -238,7 +238,7 @@ impl WordLock {
}
// Need an acquire fence before reading the new queue
- fence(Ordering::Acquire);
+ fence_acquire(&self.state);
continue;
}
@@ -263,7 +263,7 @@ impl WordLock {
continue;
} else {
// Need an acquire fence before reading the new queue
- fence(Ordering::Acquire);
+ fence_acquire(&self.state);
continue 'outer;
}
}
@@ -286,6 +286,17 @@ 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;