Skip to content

Commit

Permalink
Merge pull request #265 from d3lm/fix/instant-and-smid
Browse files Browse the repository at this point in the history
Remove instant dummy and update to latest wasm32 simd intrinsics
  • Loading branch information
Amanieu committed Dec 4, 2020
2 parents 9b3ccbd + 4554376 commit 0f29ea8
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 50 deletions.
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

0 comments on commit 0f29ea8

Please sign in to comment.