Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove instant dummy and update to latest wasm32 simd intrinsics #265

Merged
merged 1 commit into from Dec 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 5 additions & 46 deletions core/src/parking_lot.rs
Expand Up @@ -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,
Expand All @@ -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`.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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()),
Expand All @@ -130,22 +89,22 @@ 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,
}

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;
Expand Down
36 changes: 32 additions & 4 deletions core/src/thread_parker/wasm_atomic.rs
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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);
}
}
Expand Down