summaryrefslogtreecommitdiff
path: root/src/libstd/sys/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/sys/wasm')
-rw-r--r--src/libstd/sys/wasm/alloc.rs158
-rw-r--r--src/libstd/sys/wasm/args.rs46
-rw-r--r--src/libstd/sys/wasm/condvar_atomics.rs94
-rw-r--r--src/libstd/sys/wasm/env.rs9
-rw-r--r--src/libstd/sys/wasm/mod.rs70
-rw-r--r--src/libstd/sys/wasm/mutex_atomics.rs147
-rw-r--r--src/libstd/sys/wasm/rwlock_atomics.rs144
-rw-r--r--src/libstd/sys/wasm/thread.rs98
8 files changed, 0 insertions, 766 deletions
diff --git a/src/libstd/sys/wasm/alloc.rs b/src/libstd/sys/wasm/alloc.rs
deleted file mode 100644
index 32b8b5bdaea..00000000000
--- a/src/libstd/sys/wasm/alloc.rs
+++ /dev/null
@@ -1,158 +0,0 @@
-//! This is an implementation of a global allocator on the wasm32 platform when
-//! emscripten is not in use. In that situation there's no actual runtime for us
-//! to lean on for allocation, so instead we provide our own!
-//!
-//! The wasm32 instruction set has two instructions for getting the current
-//! amount of memory and growing the amount of memory. These instructions are the
-//! foundation on which we're able to build an allocator, so we do so! Note that
-//! the instructions are also pretty "global" and this is the "global" allocator
-//! after all!
-//!
-//! The current allocator here is the `dlmalloc` crate which we've got included
-//! in the rust-lang/rust repository as a submodule. The crate is a port of
-//! dlmalloc.c from C to Rust and is basically just so we can have "pure Rust"
-//! for now which is currently technically required (can't link with C yet).
-//!
-//! The crate itself provides a global allocator which on wasm has no
-//! synchronization as there are no threads!
-
-use crate::alloc::{GlobalAlloc, Layout, System};
-
-static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT;
-
-#[stable(feature = "alloc_system_type", since = "1.28.0")]
-unsafe impl GlobalAlloc for System {
- #[inline]
- unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- let _lock = lock::lock();
- DLMALLOC.malloc(layout.size(), layout.align())
- }
-
- #[inline]
- unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
- let _lock = lock::lock();
- DLMALLOC.calloc(layout.size(), layout.align())
- }
-
- #[inline]
- unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
- let _lock = lock::lock();
- DLMALLOC.free(ptr, layout.size(), layout.align())
- }
-
- #[inline]
- unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
- let _lock = lock::lock();
- DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size)
- }
-}
-
-#[cfg(target_feature = "atomics")]
-mod lock {
- use crate::sync::atomic::{AtomicI32, Ordering::SeqCst};
-
- static LOCKED: AtomicI32 = AtomicI32::new(0);
-
- pub struct DropLock;
-
- pub fn lock() -> DropLock {
- loop {
- if LOCKED.swap(1, SeqCst) == 0 {
- return DropLock;
- }
- // Ok so here's where things get a little depressing. At this point
- // in time we need to synchronously acquire a lock, but we're
- // contending with some other thread. Typically we'd execute some
- // form of `i32.atomic.wait` like so:
- //
- // unsafe {
- // let r = core::arch::wasm32::i32_atomic_wait(
- // LOCKED.as_mut_ptr(),
- // 1, // expected value
- // -1, // timeout
- // );
- // debug_assert!(r == 0 || r == 1);
- // }
- //
- // Unfortunately though in doing so we would cause issues for the
- // main thread. The main thread in a web browser *cannot ever
- // block*, no exceptions. This means that the main thread can't
- // actually execute the `i32.atomic.wait` instruction.
- //
- // As a result if we want to work within the context of browsers we
- // need to figure out some sort of allocation scheme for the main
- // thread where when there's contention on the global malloc lock we
- // do... something.
- //
- // Possible ideas include:
- //
- // 1. Attempt to acquire the global lock. If it fails, fall back to
- // memory allocation via `memory.grow`. Later just ... somehow
- // ... inject this raw page back into the main allocator as it
- // gets sliced up over time. This strategy has the downside of
- // forcing allocation of a page to happen whenever the main
- // thread contents with other threads, which is unfortunate.
- //
- // 2. Maintain a form of "two level" allocator scheme where the main
- // thread has its own allocator. Somehow this allocator would
- // also be balanced with a global allocator, not only to have
- // allocations cross between threads but also to ensure that the
- // two allocators stay "balanced" in terms of free'd memory and
- // such. This, however, seems significantly complicated.
- //
- // Out of a lack of other ideas, the current strategy implemented
- // here is to simply spin. Typical spin loop algorithms have some
- // form of "hint" here to the CPU that it's what we're doing to
- // ensure that the CPU doesn't get too hot, but wasm doesn't have
- // such an instruction.
- //
- // To be clear, spinning here is not a great solution.
- // Another thread with the lock may take quite a long time to wake
- // up. For example it could be in `memory.grow` or it could be
- // evicted from the CPU for a timeslice like 10ms. For these periods
- // of time our thread will "helpfully" sit here and eat CPU time
- // until it itself is evicted or the lock holder finishes. This
- // means we're just burning and wasting CPU time to no one's
- // benefit.
- //
- // Spinning does have the nice properties, though, of being
- // semantically correct, being fair to all threads for memory
- // allocation, and being simple enough to implement.
- //
- // This will surely (hopefully) be replaced in the future with a
- // real memory allocator that can handle the restriction of the main
- // thread.
- //
- //
- // FIXME: We can also possibly add an optimization here to detect
- // when a thread is the main thread or not and block on all
- // non-main-thread threads. Currently, however, we have no way
- // of knowing which wasm thread is on the browser main thread, but
- // if we could figure out we could at least somewhat mitigate the
- // cost of this spinning.
- }
- }
-
- impl Drop for DropLock {
- fn drop(&mut self) {
- let r = LOCKED.swap(0, SeqCst);
- debug_assert_eq!(r, 1);
-
- // Note that due to the above logic we don't actually need to wake
- // anyone up, but if we did it'd likely look something like this:
- //
- // unsafe {
- // core::arch::wasm32::atomic_notify(
- // LOCKED.as_mut_ptr(),
- // 1, // only one thread
- // );
- // }
- }
- }
-}
-
-#[cfg(not(target_feature = "atomics"))]
-mod lock {
- #[inline]
- pub fn lock() {} // no atomics, no threads, that's easy!
-}
diff --git a/src/libstd/sys/wasm/args.rs b/src/libstd/sys/wasm/args.rs
deleted file mode 100644
index 3b6557ae325..00000000000
--- a/src/libstd/sys/wasm/args.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-use crate::ffi::OsString;
-use crate::marker::PhantomData;
-use crate::vec;
-
-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
- // On wasm these should always be null, so there's nothing for us to do here
-}
-
-pub unsafe fn cleanup() {}
-
-pub fn args() -> Args {
- Args { iter: Vec::new().into_iter(), _dont_send_or_sync_me: PhantomData }
-}
-
-pub struct Args {
- iter: vec::IntoIter<OsString>,
- _dont_send_or_sync_me: PhantomData<*mut ()>,
-}
-
-impl Args {
- pub fn inner_debug(&self) -> &[OsString] {
- self.iter.as_slice()
- }
-}
-
-impl Iterator for Args {
- type Item = OsString;
- fn next(&mut self) -> Option<OsString> {
- self.iter.next()
- }
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-}
-
-impl ExactSizeIterator for Args {
- fn len(&self) -> usize {
- self.iter.len()
- }
-}
-
-impl DoubleEndedIterator for Args {
- fn next_back(&mut self) -> Option<OsString> {
- self.iter.next_back()
- }
-}
diff --git a/src/libstd/sys/wasm/condvar_atomics.rs b/src/libstd/sys/wasm/condvar_atomics.rs
deleted file mode 100644
index 1859cdd5a0e..00000000000
--- a/src/libstd/sys/wasm/condvar_atomics.rs
+++ /dev/null
@@ -1,94 +0,0 @@
-use crate::arch::wasm32;
-use crate::cmp;
-use crate::mem;
-use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
-use crate::sys::mutex::Mutex;
-use crate::time::Duration;
-
-pub struct Condvar {
- cnt: AtomicUsize,
-}
-
-// Condition variables are implemented with a simple counter internally that is
-// likely to cause spurious wakeups. Blocking on a condition variable will first
-// read the value of the internal counter, unlock the given mutex, and then
-// block if and only if the counter's value is still the same. Notifying a
-// condition variable will modify the counter (add one for now) and then wake up
-// a thread waiting on the address of the counter.
-//
-// A thread waiting on the condition variable will as a result avoid going to
-// sleep if it's notified after the lock is unlocked but before it fully goes to
-// sleep. A sleeping thread is guaranteed to be woken up at some point as it can
-// only be woken up with a call to `wake`.
-//
-// Note that it's possible for 2 or more threads to be woken up by a call to
-// `notify_one` with this implementation. That can happen where the modification
-// of `cnt` causes any threads in the middle of `wait` to avoid going to sleep,
-// and the subsequent `wake` may wake up a thread that's actually blocking. We
-// consider this a spurious wakeup, though, which all users of condition
-// variables must already be prepared to handle. As a result, this source of
-// spurious wakeups is currently though to be ok, although it may be problematic
-// later on if it causes too many spurious wakeups.
-
-impl Condvar {
- pub const fn new() -> Condvar {
- Condvar { cnt: AtomicUsize::new(0) }
- }
-
- #[inline]
- pub unsafe fn init(&mut self) {
- // nothing to do
- }
-
- pub unsafe fn notify_one(&self) {
- self.cnt.fetch_add(1, SeqCst);
- wasm32::atomic_notify(self.ptr(), 1);
- }
-
- #[inline]
- pub unsafe fn notify_all(&self) {
- self.cnt.fetch_add(1, SeqCst);
- wasm32::atomic_notify(self.ptr(), u32::MAX); // -1 == "wake everyone"
- }
-
- pub unsafe fn wait(&self, mutex: &Mutex) {
- // "atomically block and unlock" implemented by loading our current
- // counter's value, unlocking the mutex, and blocking if the counter
- // still has the same value.
- //
- // Notifications happen by incrementing the counter and then waking a
- // thread. Incrementing the counter after we unlock the mutex will
- // prevent us from sleeping and otherwise the call to `wake` will
- // wake us up once we're asleep.
- let ticket = self.cnt.load(SeqCst) as i32;
- mutex.unlock();
- let val = wasm32::i32_atomic_wait(self.ptr(), ticket, -1);
- // 0 == woken, 1 == not equal to `ticket`, 2 == timeout (shouldn't happen)
- debug_assert!(val == 0 || val == 1);
- mutex.lock();
- }
-
- pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
- let ticket = self.cnt.load(SeqCst) as i32;
- mutex.unlock();
- let nanos = dur.as_nanos();
- let nanos = cmp::min(i64::MAX as u128, nanos);
-
- // If the return value is 2 then a timeout happened, so we return
- // `false` as we weren't actually notified.
- let ret = wasm32::i32_atomic_wait(self.ptr(), ticket, nanos as i64) != 2;
- mutex.lock();
- return ret;
- }
-
- #[inline]
- pub unsafe fn destroy(&self) {
- // nothing to do
- }
-
- #[inline]
- fn ptr(&self) -> *mut i32 {
- assert_eq!(mem::size_of::<usize>(), mem::size_of::<i32>());
- self.cnt.as_mut_ptr() as *mut i32
- }
-}
diff --git a/src/libstd/sys/wasm/env.rs b/src/libstd/sys/wasm/env.rs
deleted file mode 100644
index 730e356d7fe..00000000000
--- a/src/libstd/sys/wasm/env.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub mod os {
- pub const FAMILY: &str = "";
- pub const OS: &str = "";
- pub const DLL_PREFIX: &str = "";
- pub const DLL_SUFFIX: &str = ".wasm";
- pub const DLL_EXTENSION: &str = "wasm";
- pub const EXE_SUFFIX: &str = ".wasm";
- pub const EXE_EXTENSION: &str = "wasm";
-}
diff --git a/src/libstd/sys/wasm/mod.rs b/src/libstd/sys/wasm/mod.rs
deleted file mode 100644
index 3de58904043..00000000000
--- a/src/libstd/sys/wasm/mod.rs
+++ /dev/null
@@ -1,70 +0,0 @@
-//! System bindings for the wasm/web platform
-//!
-//! This module contains the facade (aka platform-specific) implementations of
-//! OS level functionality for wasm. Note that this wasm is *not* the emscripten
-//! wasm, so we have no runtime here.
-//!
-//! This is all super highly experimental and not actually intended for
-//! wide/production use yet, it's still all in the experimental category. This
-//! will likely change over time.
-//!
-//! Currently all functions here are basically stubs that immediately return
-//! errors. The hope is that with a portability lint we can turn actually just
-//! remove all this and just omit parts of the standard library if we're
-//! compiling for wasm. That way it's a compile time error for something that's
-//! guaranteed to be a runtime error!
-
-pub mod alloc;
-pub mod args;
-#[path = "../unsupported/cmath.rs"]
-pub mod cmath;
-pub mod env;
-#[path = "../unsupported/fs.rs"]
-pub mod fs;
-#[path = "../unsupported/io.rs"]
-pub mod io;
-#[path = "../unsupported/net.rs"]
-pub mod net;
-#[path = "../unsupported/os.rs"]
-pub mod os;
-#[path = "../unsupported/path.rs"]
-pub mod path;
-#[path = "../unsupported/pipe.rs"]
-pub mod pipe;
-#[path = "../unsupported/process.rs"]
-pub mod process;
-#[path = "../unsupported/stack_overflow.rs"]
-pub mod stack_overflow;
-#[path = "../unsupported/stdio.rs"]
-pub mod stdio;
-pub mod thread;
-#[path = "../unsupported/thread_local_dtor.rs"]
-pub mod thread_local_dtor;
-#[path = "../unsupported/thread_local_key.rs"]
-pub mod thread_local_key;
-#[path = "../unsupported/time.rs"]
-pub mod time;
-
-pub use crate::sys_common::os_str_bytes as os_str;
-
-cfg_if::cfg_if! {
- if #[cfg(target_feature = "atomics")] {
- #[path = "condvar_atomics.rs"]
- pub mod condvar;
- #[path = "mutex_atomics.rs"]
- pub mod mutex;
- #[path = "rwlock_atomics.rs"]
- pub mod rwlock;
- } else {
- #[path = "../unsupported/condvar.rs"]
- pub mod condvar;
- #[path = "../unsupported/mutex.rs"]
- pub mod mutex;
- #[path = "../unsupported/rwlock.rs"]
- pub mod rwlock;
- }
-}
-
-#[path = "../unsupported/common.rs"]
-mod common;
-pub use common::*;
diff --git a/src/libstd/sys/wasm/mutex_atomics.rs b/src/libstd/sys/wasm/mutex_atomics.rs
deleted file mode 100644
index 268a53bb564..00000000000
--- a/src/libstd/sys/wasm/mutex_atomics.rs
+++ /dev/null
@@ -1,147 +0,0 @@
-use crate::arch::wasm32;
-use crate::cell::UnsafeCell;
-use crate::mem;
-use crate::sync::atomic::{AtomicU32, AtomicUsize, Ordering::SeqCst};
-use crate::sys::thread;
-
-pub struct Mutex {
- locked: AtomicUsize,
-}
-
-// Mutexes have a pretty simple implementation where they contain an `i32`
-// internally that is 0 when unlocked and 1 when the mutex is locked.
-// Acquisition has a fast path where it attempts to cmpxchg the 0 to a 1, and
-// if it fails it then waits for a notification. Releasing a lock is then done
-// by swapping in 0 and then notifying any waiters, if present.
-
-impl Mutex {
- pub const fn new() -> Mutex {
- Mutex { locked: AtomicUsize::new(0) }
- }
-
- #[inline]
- pub unsafe fn init(&mut self) {
- // nothing to do
- }
-
- pub unsafe fn lock(&self) {
- while !self.try_lock() {
- let val = wasm32::i32_atomic_wait(
- self.ptr(),
- 1, // we expect our mutex is locked
- -1, // wait infinitely
- );
- // we should have either woke up (0) or got a not-equal due to a
- // race (1). We should never time out (2)
- debug_assert!(val == 0 || val == 1);
- }
- }
-
- pub unsafe fn unlock(&self) {
- let prev = self.locked.swap(0, SeqCst);
- debug_assert_eq!(prev, 1);
- wasm32::atomic_notify(self.ptr(), 1); // wake up one waiter, if any
- }
-
- #[inline]
- pub unsafe fn try_lock(&self) -> bool {
- self.locked.compare_exchange(0, 1, SeqCst, SeqCst).is_ok()
- }
-
- #[inline]
- pub unsafe fn destroy(&self) {
- // nothing to do
- }
-
- #[inline]
- fn ptr(&self) -> *mut i32 {
- assert_eq!(mem::size_of::<usize>(), mem::size_of::<i32>());
- self.locked.as_mut_ptr() as *mut i32
- }
-}
-
-pub struct ReentrantMutex {
- owner: AtomicU32,
- recursions: UnsafeCell<u32>,
-}
-
-unsafe impl Send for ReentrantMutex {}
-unsafe impl Sync for ReentrantMutex {}
-
-// Reentrant mutexes are similarly implemented to mutexs above except that
-// instead of "1" meaning unlocked we use the id of a thread to represent
-// whether it has locked a mutex. That way we have an atomic counter which
-// always holds the id of the thread that currently holds the lock (or 0 if the
-// lock is unlocked).
-//
-// Once a thread acquires a lock recursively, which it detects by looking at
-// the value that's already there, it will update a local `recursions` counter
-// in a nonatomic fashion (as we hold the lock). The lock is then fully
-// released when this recursion counter reaches 0.
-
-impl ReentrantMutex {
- pub const unsafe fn uninitialized() -> ReentrantMutex {
- ReentrantMutex { owner: AtomicU32::new(0), recursions: UnsafeCell::new(0) }
- }
-
- pub unsafe fn init(&self) {
- // nothing to do...
- }
-
- pub unsafe fn lock(&self) {
- let me = thread::my_id();
- while let Err(owner) = self._try_lock(me) {
- let val = wasm32::i32_atomic_wait(self.ptr(), owner as i32, -1);
- debug_assert!(val == 0 || val == 1);
- }
- }
-
- #[inline]
- pub unsafe fn try_lock(&self) -> bool {
- self._try_lock(thread::my_id()).is_ok()
- }
-
- #[inline]
- unsafe fn _try_lock(&self, id: u32) -> Result<(), u32> {
- let id = id.checked_add(1).unwrap(); // make sure `id` isn't 0
- match self.owner.compare_exchange(0, id, SeqCst, SeqCst) {
- // we transitioned from unlocked to locked
- Ok(_) => {
- debug_assert_eq!(*self.recursions.get(), 0);
- Ok(())
- }
-
- // we currently own this lock, so let's update our count and return
- // true.
- Err(n) if n == id => {
- *self.recursions.get() += 1;
- Ok(())
- }
-
- // Someone else owns the lock, let our caller take care of it
- Err(other) => Err(other),
- }
- }
-
- pub unsafe fn unlock(&self) {
- // If we didn't ever recursively lock the lock then we fully unlock the
- // mutex and wake up a waiter, if any. Otherwise we decrement our
- // recursive counter and let some one else take care of the zero.
- match *self.recursions.get() {
- 0 => {
- self.owner.swap(0, SeqCst);
- wasm32::atomic_notify(self.ptr() as *mut i32, 1); // wake up one waiter, if any
- }
- ref mut n => *n -= 1,
- }
- }
-
- pub unsafe fn destroy(&self) {
- // nothing to do...
- }
-
- #[inline]
- fn ptr(&self) -> *mut i32 {
- self.owner.as_mut_ptr() as *mut i32
- }
-}
diff --git a/src/libstd/sys/wasm/rwlock_atomics.rs b/src/libstd/sys/wasm/rwlock_atomics.rs
deleted file mode 100644
index 06442e925f4..00000000000
--- a/src/libstd/sys/wasm/rwlock_atomics.rs
+++ /dev/null
@@ -1,144 +0,0 @@
-use crate::cell::UnsafeCell;
-use crate::sys::condvar::Condvar;
-use crate::sys::mutex::Mutex;
-
-pub struct RWLock {
- lock: Mutex,
- cond: Condvar,
- state: UnsafeCell<State>,
-}
-
-enum State {
- Unlocked,
- Reading(usize),
- Writing,
-}
-
-unsafe impl Send for RWLock {}
-unsafe impl Sync for RWLock {}
-
-// This rwlock implementation is a relatively simple implementation which has a
-// condition variable for readers/writers as well as a mutex protecting the
-// internal state of the lock. A current downside of the implementation is that
-// unlocking the lock will notify *all* waiters rather than just readers or just
-// writers. This can cause lots of "thundering stampede" problems. While
-// hopefully correct this implementation is very likely to want to be changed in
-// the future.
-
-impl RWLock {
- pub const fn new() -> RWLock {
- RWLock { lock: Mutex::new(), cond: Condvar::new(), state: UnsafeCell::new(State::Unlocked) }
- }
-
- #[inline]
- pub unsafe fn read(&self) {
- self.lock.lock();
- while !(*self.state.get()).inc_readers() {
- self.cond.wait(&self.lock);
- }
- self.lock.unlock();
- }
-
- #[inline]
- pub unsafe fn try_read(&self) -> bool {
- self.lock.lock();
- let ok = (*self.state.get()).inc_readers();
- self.lock.unlock();
- return ok;
- }
-
- #[inline]
- pub unsafe fn write(&self) {
- self.lock.lock();
- while !(*self.state.get()).inc_writers() {
- self.cond.wait(&self.lock);
- }
- self.lock.unlock();
- }
-
- #[inline]
- pub unsafe fn try_write(&self) -> bool {
- self.lock.lock();
- let ok = (*self.state.get()).inc_writers();
- self.lock.unlock();
- return ok;
- }
-
- #[inline]
- pub unsafe fn read_unlock(&self) {
- self.lock.lock();
- let notify = (*self.state.get()).dec_readers();
- self.lock.unlock();
- if notify {
- // FIXME: should only wake up one of these some of the time
- self.cond.notify_all();
- }
- }
-
- #[inline]
- pub unsafe fn write_unlock(&self) {
- self.lock.lock();
- (*self.state.get()).dec_writers();
- self.lock.unlock();
- // FIXME: should only wake up one of these some of the time
- self.cond.notify_all();
- }
-
- #[inline]
- pub unsafe fn destroy(&self) {
- self.lock.destroy();
- self.cond.destroy();
- }
-}
-
-impl State {
- fn inc_readers(&mut self) -> bool {
- match *self {
- State::Unlocked => {
- *self = State::Reading(1);
- true
- }
- State::Reading(ref mut cnt) => {
- *cnt += 1;
- true
- }
- State::Writing => false,
- }
- }
-
- fn inc_writers(&mut self) -> bool {
- match *self {
- State::Unlocked => {
- *self = State::Writing;
- true
- }
- State::Reading(_) | State::Writing => false,
- }
- }
-
- fn dec_readers(&mut self) -> bool {
- let zero = match *self {
- State::Reading(ref mut cnt) => {
- *cnt -= 1;
- *cnt == 0
- }
- State::Unlocked | State::Writing => invalid(),
- };
- if zero {
- *self = State::Unlocked;
- }
- zero
- }
-
- fn dec_writers(&mut self) {
- match *self {
- State::Writing => {}
- State::Unlocked | State::Reading(_) => invalid(),
- }
- *self = State::Unlocked;
- }
-}
-
-fn invalid() -> ! {
- panic!("inconsistent rwlock");
-}
diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs
deleted file mode 100644
index 0a11896a004..00000000000
--- a/src/libstd/sys/wasm/thread.rs
+++ /dev/null
@@ -1,98 +0,0 @@
-use crate::ffi::CStr;
-use crate::io;
-use crate::sys::{unsupported, Void};
-use crate::time::Duration;
-
-pub struct Thread(Void);
-
-pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
-
-impl Thread {
- // unsafe: see thread::Builder::spawn_unchecked for safety requirements
- pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>) -> io::Result<Thread> {
- unsupported()
- }
-
- pub fn yield_now() {
- // do nothing
- }
-
- pub fn set_name(_name: &CStr) {
- // nope
- }
-
- #[cfg(not(target_feature = "atomics"))]
- pub fn sleep(_dur: Duration) {
- panic!("can't sleep");
- }
-
- #[cfg(target_feature = "atomics")]
- pub fn sleep(dur: Duration) {
- use crate::arch::wasm32;
- use crate::cmp;
-
- // Use an atomic wait to block the current thread artificially with a
- // timeout listed. Note that we should never be notified (return value
- // of 0) or our comparison should never fail (return value of 1) so we
- // should always only resume execution through a timeout (return value
- // 2).
- let mut nanos = dur.as_nanos();
- while nanos > 0 {
- let amt = cmp::min(i64::MAX as u128, nanos);
- let mut x = 0;
- let val = unsafe { wasm32::i32_atomic_wait(&mut x, 0, amt as i64) };
- debug_assert_eq!(val, 2);
- nanos -= amt;
- }
- }
-
- pub fn join(self) {
- match self.0 {}
- }
-}
-
-pub mod guard {
- pub type Guard = !;
- pub unsafe fn current() -> Option<Guard> {
- None
- }
- pub unsafe fn init() -> Option<Guard> {
- None
- }
-}
-
-// This is only used by atomics primitives when the `atomics` feature is
-// enabled. In that mode we currently just use our own thread-local to store our
-// current thread's ID, and then we lazily initialize it to something allocated
-// from a global counter.
-#[cfg(target_feature = "atomics")]
-pub fn my_id() -> u32 {
- use crate::sync::atomic::{AtomicU32, Ordering::SeqCst};
-
- static NEXT_ID: AtomicU32 = AtomicU32::new(0);
-
- #[thread_local]
- static mut MY_ID: u32 = 0;
-
- unsafe {
- // If our thread ID isn't set yet then we need to allocate one. Do so
- // with with a simple "atomically add to a global counter" strategy.
- // This strategy doesn't handled what happens when the counter
- // overflows, however, so just abort everything once the counter
- // overflows and eventually we could have some sort of recycling scheme
- // (or maybe this is all totally irrelevant by that point!). In any case
- // though we're using a CAS loop instead of a `fetch_add` to ensure that
- // the global counter never overflows.
- if MY_ID == 0 {
- let mut cur = NEXT_ID.load(SeqCst);
- MY_ID = loop {
- let next = cur.checked_add(1).unwrap_or_else(|| crate::arch::wasm32::unreachable());
- match NEXT_ID.compare_exchange(cur, next, SeqCst, SeqCst) {
- Ok(_) => break next,
- Err(i) => cur = i,
- }
- };
- }
- MY_ID
- }
-}