diff options
author | Haibo Huang <hhb@google.com> | 2021-01-11 21:14:36 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-01-11 21:14:36 +0000 |
commit | 2519ff75acb811756b1ddb26e9dd2a7af27cc702 (patch) | |
tree | 95a37a553ed3c03c7c69ff37ed15a426ef3b31be | |
parent | d380675280fb8977f13756afbc895553ee0d174d (diff) | |
parent | 27f39984d83c152d879f48345ff181f7353a0ff1 (diff) | |
download | parking_lot_core-2519ff75acb811756b1ddb26e9dd2a7af27cc702.tar.gz |
Upgrade rust/crates/parking_lot_core to 0.8.2 am: 27f39984d8
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/parking_lot_core/+/1535511
MUST ONLY BE SUBMITTED BY AUTOMERGER
Change-Id: I0548d76b4b5822f690bb77a8ffe2ce012ee339d0
-rw-r--r-- | .cargo_vcs_info.json | 2 | ||||
-rw-r--r-- | Android.bp | 8 | ||||
-rw-r--r-- | Cargo.toml | 8 | ||||
-rw-r--r-- | Cargo.toml.orig | 9 | ||||
-rw-r--r-- | METADATA | 8 | ||||
-rw-r--r-- | src/lib.rs | 4 | ||||
-rw-r--r-- | src/parking_lot.rs | 51 | ||||
-rw-r--r-- | src/thread_parker/cloudabi.rs | 305 | ||||
-rw-r--r-- | src/thread_parker/mod.rs | 3 | ||||
-rw-r--r-- | src/thread_parker/unix.rs | 12 | ||||
-rw-r--r-- | src/thread_parker/wasm_atomic.rs | 36 |
11 files changed, 54 insertions, 392 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index ef88cf4..d08ddd4 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,5 +1,5 @@ { "git": { - "sha1": "8c154bedcb392b87feea9b29054f3f0cabcd6a28" + "sha1": "dac08482fec1297c15e67c2fe034a1a5c463915d" } } @@ -40,7 +40,7 @@ rust_test { } // dependent_library ["feature_list"] -// cfg-if-0.1.10 -// instant-0.1.7 -// libc-0.2.79 "default,std" -// smallvec-1.4.2 +// cfg-if-1.0.0 +// instant-0.1.9 +// libc-0.2.81 "default,std" +// smallvec-1.5.1 @@ -13,7 +13,7 @@ [package] edition = "2018" name = "parking_lot_core" -version = "0.8.0" +version = "0.8.2" authors = ["Amanieu d'Antras <amanieu@gmail.com>"] description = "An advanced API for creating custom synchronization primitives." keywords = ["mutex", "condvar", "rwlock", "once", "thread"] @@ -25,7 +25,7 @@ version = "0.3.49" optional = true [dependencies.cfg-if] -version = "0.1.10" +version = "1.0.0" [dependencies.instant] version = "0.1.4" @@ -35,7 +35,7 @@ version = "0.5.1" optional = true [dependencies.smallvec] -version = "1.4.0" +version = "1.0" [dependencies.thread-id] version = "3.3.0" @@ -44,8 +44,6 @@ optional = true [features] deadlock_detection = ["petgraph", "thread-id", "backtrace"] nightly = [] -[target."cfg(target_os = \"cloudabi\")".dependencies.cloudabi] -version = "0.1.0" [target."cfg(target_os = \"redox\")".dependencies.redox_syscall] version = "0.1.56" [target."cfg(unix)".dependencies.libc] diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 44903ca..db7830e 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "parking_lot_core" -version = "0.8.0" +version = "0.8.2" authors = ["Amanieu d'Antras <amanieu@gmail.com>"] description = "An advanced API for creating custom synchronization primitives." license = "Apache-2.0/MIT" @@ -10,8 +10,8 @@ categories = ["concurrency"] edition = "2018" [dependencies] -cfg-if = "0.1.10" -smallvec = "1.4.0" +cfg-if = "1.0.0" +smallvec = "1.0" petgraph = { version = "0.5.1", optional = true } thread-id = { version = "3.3.0", optional = true } backtrace = { version = "0.3.49", optional = true } @@ -23,9 +23,6 @@ libc = "0.2.71" [target.'cfg(target_os = "redox")'.dependencies] redox_syscall = "0.1.56" -[target.'cfg(target_os = "cloudabi")'.dependencies] -cloudabi = "0.1.0" - [target.'cfg(windows)'.dependencies] winapi = { version = "0.3.8", features = ["winnt", "ntstatus", "minwindef", "winerror", "winbase", "errhandlingapi", "handleapi"] } @@ -7,13 +7,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/parking_lot_core/parking_lot_core-0.8.0.crate" + value: "https://static.crates.io/crates/parking_lot_core/parking_lot_core-0.8.2.crate" } - version: "0.8.0" + version: "0.8.2" license_type: NOTICE last_upgrade_date { year: 2020 - month: 10 - day: 20 + month: 12 + day: 22 } } @@ -51,10 +51,6 @@ ), feature(stdsimd) )] -#![cfg_attr( - all(feature = "nightly", target_os = "cloudabi",), - feature(thread_local) -)] mod parking_lot; mod spinwait; diff --git a/src/parking_lot.rs b/src/parking_lot.rs index 1bd19eb..519ce9e 100644 --- a/src/parking_lot.rs +++ b/src/parking_lot.rs @@ -7,7 +7,6 @@ use crate::thread_parker::{ThreadParker, ThreadParkerT, UnparkHandleT}; use crate::util::UncheckedOptionExt; use crate::word_lock::WordLock; -use cfg_if::cfg_if; use core::{ cell::{Cell, UnsafeCell}, ptr, @@ -17,46 +16,6 @@ use instant::Instant; use smallvec::SmallVec; use std::time::Duration; -cfg_if! { - if #[cfg(all( - target_arch = "wasm32", - target_os = "unknown", - target_vendor = "unknown" - ))] { - use core::ops::Add; - - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] - struct DummyInstant(Duration); - - impl DummyInstant { - pub fn now() -> DummyInstant { - DummyInstant::zero() - } - - const fn zero() -> DummyInstant { - DummyInstant(Duration::from_secs(0)) - } - } - - impl Add<Duration> for DummyInstant { - type Output = DummyInstant; - - fn add(self, _rhs: Duration) -> DummyInstant { - DummyInstant::zero() - } - } - - // Use dummy implementation for `Instant` on `wasm32`. The reason for this is - // that `Instant::now()` will always panic because time is currently not implemented - // on wasm32-unknown-unknown. - // See https://github.com/rust-lang/rust/blob/master/src/libstd/sys/wasm/time.rs - type InstantType = DummyInstant; - } else { - // Otherwise use `instant::Instant` - type InstantType = Instant; - } -} - static NUM_THREADS: AtomicUsize = AtomicUsize::new(0); /// Holds the pointer to the currently active `HashTable`. @@ -88,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 = InstantType::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 @@ -118,7 +77,7 @@ struct Bucket { impl Bucket { #[inline] - pub fn new(timeout: InstantType, seed: u32) -> Self { + pub fn new(timeout: Instant, seed: u32) -> Self { Self { mutex: WordLock::new(), queue_head: Cell::new(ptr::null()), @@ -130,7 +89,7 @@ impl Bucket { struct FairTimeout { // Next time at which point be_fair should be set - timeout: InstantType, + timeout: Instant, // the PRNG state for calculating the next timeout seed: u32, @@ -138,14 +97,14 @@ struct FairTimeout { impl FairTimeout { #[inline] - fn new(timeout: InstantType, 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 = InstantType::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/thread_parker/cloudabi.rs b/src/thread_parker/cloudabi.rs deleted file mode 100644 index 2c5237f..0000000 --- a/src/thread_parker/cloudabi.rs +++ /dev/null @@ -1,305 +0,0 @@ -// Copyright 2016 Amanieu d'Antras -// -// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or -// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or -// http://opensource.org/licenses/MIT>, at your option. This file may not be -// copied, modified, or distributed except according to those terms. - -use cloudabi as abi; -use core::{ - cell::Cell, - mem::{self, MaybeUninit}, - sync::atomic::{AtomicU32, Ordering}, -}; -use instant::Instant; -use std::{convert::TryFrom, thread}; - -extern "C" { - #[thread_local] - static __pthread_thread_id: abi::tid; -} - -struct Lock { - lock: AtomicU32, -} - -impl Lock { - pub fn new() -> Self { - Lock { - lock: AtomicU32::new(abi::LOCK_UNLOCKED.0), - } - } - - /// # Safety - /// - /// See `Lock::lock`. - unsafe fn try_lock(&self) -> Option<LockGuard> { - // Attempt to acquire the lock. - if let Err(old) = self.lock.compare_exchange( - abi::LOCK_UNLOCKED.0, - __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0, - Ordering::Acquire, - Ordering::Relaxed, - ) { - // Failure. Crash upon recursive acquisition. - debug_assert_ne!( - old & !abi::LOCK_KERNEL_MANAGED.0, - __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0, - "Attempted to recursive write-lock a lock", - ); - None - } else { - Some(LockGuard { lock: &self.lock }) - } - } - - /// # Safety - /// - /// This method is unsafe because the `LockGuard` has a raw pointer into this `Lock` - /// that it will access on drop to unlock the lock. So make sure the `LockGuard` goes - /// out of scope before the `Lock` it came from moves or goes out of scope. - pub unsafe fn lock(&self) -> LockGuard { - self.try_lock().unwrap_or_else(|| { - // Call into the kernel to acquire a write lock. - let subscription = abi::subscription { - r#type: abi::eventtype::LOCK_WRLOCK, - union: abi::subscription_union { - lock: abi::subscription_lock { - lock: self.ptr(), - lock_scope: abi::scope::PRIVATE, - }, - }, - ..mem::zeroed() - }; - let mut event = MaybeUninit::<abi::event>::uninit(); - let mut nevents: usize = 0; - let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, &mut nevents); - debug_assert_eq!(ret, abi::errno::SUCCESS); - debug_assert_eq!(event.assume_init().error, abi::errno::SUCCESS); - - LockGuard { lock: &self.lock } - }) - } - - fn ptr(&self) -> *mut abi::lock { - &self.lock as *const AtomicU32 as *mut abi::lock - } -} - -struct LockGuard { - lock: *const AtomicU32, -} - -impl LockGuard { - fn ptr(&self) -> *mut abi::lock { - self.lock as *mut abi::lock - } -} - -impl Drop for LockGuard { - fn drop(&mut self) { - let lock = unsafe { &*self.lock }; - debug_assert_eq!( - lock.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0, - unsafe { __pthread_thread_id.0 } | abi::LOCK_WRLOCKED.0, - "This lock is not write-locked by this thread" - ); - - if !lock - .compare_exchange( - unsafe { __pthread_thread_id.0 } | abi::LOCK_WRLOCKED.0, - abi::LOCK_UNLOCKED.0, - Ordering::Release, - Ordering::Relaxed, - ) - .is_ok() - { - // Lock is managed by kernelspace. Call into the kernel - // to unblock waiting threads. - let ret = unsafe { abi::lock_unlock(self.lock as *mut abi::lock, abi::scope::PRIVATE) }; - debug_assert_eq!(ret, abi::errno::SUCCESS); - } - } -} - -struct Condvar { - condvar: AtomicU32, -} - -impl Condvar { - pub fn new() -> Self { - Condvar { - condvar: AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0), - } - } - - pub fn wait(&self, lock: &LockGuard) { - unsafe { - let subscription = abi::subscription { - r#type: abi::eventtype::CONDVAR, - union: abi::subscription_union { - condvar: abi::subscription_condvar { - condvar: self.ptr(), - condvar_scope: abi::scope::PRIVATE, - lock: lock.ptr(), - lock_scope: abi::scope::PRIVATE, - }, - }, - ..mem::zeroed() - }; - let mut event = MaybeUninit::<abi::event>::uninit(); - let mut nevents: usize = 0; - - let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, &mut nevents); - debug_assert_eq!(ret, abi::errno::SUCCESS); - debug_assert_eq!(event.assume_init().error, abi::errno::SUCCESS); - } - } - - /// Waits for a signal on the condvar. - /// Returns false if it times out before anyone notified us. - pub fn wait_timeout(&self, lock: &LockGuard, timeout: abi::timestamp) -> bool { - unsafe { - let subscriptions = [ - abi::subscription { - r#type: abi::eventtype::CONDVAR, - union: abi::subscription_union { - condvar: abi::subscription_condvar { - condvar: self.ptr(), - condvar_scope: abi::scope::PRIVATE, - lock: lock.ptr(), - lock_scope: abi::scope::PRIVATE, - }, - }, - ..mem::zeroed() - }, - abi::subscription { - r#type: abi::eventtype::CLOCK, - union: abi::subscription_union { - clock: abi::subscription_clock { - clock_id: abi::clockid::MONOTONIC, - timeout, - ..mem::zeroed() - }, - }, - ..mem::zeroed() - }, - ]; - let mut events = MaybeUninit::<[abi::event; 2]>::uninit(); - let mut nevents: usize = 0; - - let ret = abi::poll( - subscriptions.as_ptr(), - events.as_mut_ptr() as *mut _, - 2, - &mut nevents, - ); - debug_assert_eq!(ret, abi::errno::SUCCESS); - let events = events.assume_init(); - for i in 0..nevents { - debug_assert_eq!(events[i].error, abi::errno::SUCCESS); - if events[i].r#type == abi::eventtype::CONDVAR { - return true; - } - } - } - false - } - - pub fn notify(&self) { - let ret = unsafe { abi::condvar_signal(self.ptr(), abi::scope::PRIVATE, 1) }; - debug_assert_eq!(ret, abi::errno::SUCCESS); - } - - fn ptr(&self) -> *mut abi::condvar { - &self.condvar as *const AtomicU32 as *mut abi::condvar - } -} - -// Helper type for putting a thread to sleep until some other thread wakes it up -pub struct ThreadParker { - should_park: Cell<bool>, - lock: Lock, - condvar: Condvar, -} - -impl super::ThreadParkerT for ThreadParker { - type UnparkHandle = UnparkHandle; - - const IS_CHEAP_TO_CONSTRUCT: bool = true; - - fn new() -> ThreadParker { - ThreadParker { - should_park: Cell::new(false), - lock: Lock::new(), - condvar: Condvar::new(), - } - } - - unsafe fn prepare_park(&self) { - self.should_park.set(true); - } - - unsafe fn timed_out(&self) -> bool { - // We need to grab the lock here because another thread may be - // concurrently executing UnparkHandle::unpark, which is done without - // holding the queue lock. - let _guard = self.lock.lock(); - self.should_park.get() - } - - unsafe fn park(&self) { - let guard = self.lock.lock(); - while self.should_park.get() { - self.condvar.wait(&guard); - } - } - - unsafe fn park_until(&self, timeout: Instant) -> bool { - let guard = self.lock.lock(); - while self.should_park.get() { - if let Some(duration_left) = timeout.checked_duration_since(Instant::now()) { - if let Ok(nanos_left) = abi::timestamp::try_from(duration_left.as_nanos()) { - self.condvar.wait_timeout(&guard, nanos_left); - } else { - // remaining timeout overflows an abi::timestamp. Sleep indefinitely - self.condvar.wait(&guard); - } - } else { - // We timed out - return false; - } - } - true - } - - unsafe fn unpark_lock(&self) -> UnparkHandle { - let _lock_guard = self.lock.lock(); - - UnparkHandle { - thread_parker: self, - _lock_guard, - } - } -} - -pub struct UnparkHandle { - thread_parker: *const ThreadParker, - _lock_guard: LockGuard, -} - -impl super::UnparkHandleT for UnparkHandle { - unsafe fn unpark(self) { - (*self.thread_parker).should_park.set(false); - - // We notify while holding the lock here to avoid races with the target - // thread. In particular, the thread could exit after we unlock the - // mutex, which would make the condvar access invalid memory. - (*self.thread_parker).condvar.notify(); - } -} - -#[inline] -pub fn thread_yield() { - thread::yield_now(); -} diff --git a/src/thread_parker/mod.rs b/src/thread_parker/mod.rs index 3d00bfc..a7e4bb6 100644 --- a/src/thread_parker/mod.rs +++ b/src/thread_parker/mod.rs @@ -76,9 +76,6 @@ cfg_if! { } else if #[cfg(target_arch = "wasm32")] { #[path = "wasm.rs"] mod imp; - } else if #[cfg(all(feature = "nightly", target_os = "cloudabi"))] { - #[path = "cloudabi.rs"] - mod imp; } else { #[path = "generic.rs"] mod imp; diff --git a/src/thread_parker/unix.rs b/src/thread_parker/unix.rs index a58e6ff..c2381e6 100644 --- a/src/thread_parker/unix.rs +++ b/src/thread_parker/unix.rs @@ -156,17 +156,9 @@ impl Drop for ThreadParker { // this behaviour no longer occurs. The same applies to condvars. unsafe { let r = libc::pthread_mutex_destroy(self.mutex.get()); - if cfg!(target_os = "dragonfly") { - debug_assert!(r == 0 || r == libc::EINVAL); - } else { - debug_assert_eq!(r, 0); - } + debug_assert!(r == 0 || r == libc::EINVAL); let r = libc::pthread_cond_destroy(self.condvar.get()); - if cfg!(target_os = "dragonfly") { - debug_assert!(r == 0 || r == libc::EINVAL); - } else { - debug_assert_eq!(r, 0); - } + debug_assert!(r == 0 || r == libc::EINVAL); } } } diff --git a/src/thread_parker/wasm_atomic.rs b/src/thread_parker/wasm_atomic.rs index e482c6b..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 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, @@ -45,7 +73,7 @@ impl super::ThreadParkerT for ThreadParker { #[inline] unsafe fn park(&self) { while self.parked.load(Ordering::Acquire) == PARKED { - let r = unsafe { wasm32::i32_atomic_wait(self.ptr(), PARKED, -1) }; + let r = wasm32::memory_atomic_wait32(self.ptr(), PARKED, -1); // we should have either woken up (0) or got a not-equal due to a // race (1). We should never time out (2) debug_assert!(r == 0 || r == 1); @@ -55,9 +83,9 @@ 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 = unsafe { wasm32::i32_atomic_wait(self.ptr(), PARKED, nanos_left) }; + let r = wasm32::memory_atomic_wait32(self.ptr(), PARKED, nanos_left); debug_assert!(r == 0 || r == 1 || r == 2); } else { return false; @@ -86,7 +114,7 @@ pub struct UnparkHandle(*mut i32); impl super::UnparkHandleT for UnparkHandle { #[inline] unsafe fn unpark(self) { - let num_notified = unsafe { wasm32::atomic_notify(self.0 as *mut i32, 1) }; + let num_notified = wasm32::memory_atomic_notify(self.0 as *mut i32, 1); debug_assert!(num_notified == 0 || num_notified == 1); } } |