about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authoroliver-giersch <oliver.giersch@googlemail.com>2018-10-15 14:37:54 +0200
committerGitHub <noreply@github.com>2018-10-15 14:37:54 +0200
commit5891a64165ea4819ca331f5a35f5318a91e1be3f (patch)
treee2da4d1f0bf89c9bce5c29783744f12039b3dd33 /src/libstd
parentfa76d42b3e547bd3a0e049cc2c1e00f6b9560d6c (diff)
parent42f401dd02fd418e038d9b2829d60d69407e9aab (diff)
downloadrust-5891a64165ea4819ca331f5a35f5318a91e1be3f.tar.gz
rust-5891a64165ea4819ca331f5a35f5318a91e1be3f.zip
Merge pull request #4 from rust-lang/master
sync with upstream
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/Cargo.toml9
-rw-r--r--src/libstd/sys/wasm/mutex_atomics.rs23
-rw-r--r--src/libstd/sys/wasm/thread.rs46
-rw-r--r--src/libstd/sys/wasm/thread_local_atomics.rs53
-rw-r--r--src/libstd/thread/local.rs14
-rw-r--r--src/libstd/thread/mod.rs2
6 files changed, 122 insertions, 25 deletions
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index bcdd1b4b088..cd1e3438fc3 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -48,4 +48,13 @@ jemalloc = ["alloc_jemalloc"]
 force_alloc_system = []
 panic-unwind = ["panic_unwind"]
 profiler = ["profiler_builtins"]
+
+# An off-by-default feature which enables a linux-syscall-like ABI for libstd to
+# interoperate with the host environment. Currently not well documented and
+# requires rebuilding the standard library to use it.
 wasm_syscall = []
+
+# An off-by-default features to enable libstd to assume that wasm-bindgen is in
+# the environment for hooking up some thread-related information like the
+# current thread id and accessing/getting the current thread's TCB
+wasm-bindgen-threads = []
diff --git a/src/libstd/sys/wasm/mutex_atomics.rs b/src/libstd/sys/wasm/mutex_atomics.rs
index ced6c17ef96..762e807096f 100644
--- a/src/libstd/sys/wasm/mutex_atomics.rs
+++ b/src/libstd/sys/wasm/mutex_atomics.rs
@@ -11,7 +11,8 @@
 use arch::wasm32::atomic;
 use cell::UnsafeCell;
 use mem;
-use sync::atomic::{AtomicUsize, AtomicU64, Ordering::SeqCst};
+use sync::atomic::{AtomicUsize, AtomicU32, Ordering::SeqCst};
+use sys::thread;
 
 pub struct Mutex {
     locked: AtomicUsize,
@@ -70,7 +71,7 @@ impl Mutex {
 }
 
 pub struct ReentrantMutex {
-    owner: AtomicU64,
+    owner: AtomicU32,
     recursions: UnsafeCell<u32>,
 }
 
@@ -91,7 +92,7 @@ unsafe impl Sync for ReentrantMutex {}
 impl ReentrantMutex {
     pub unsafe fn uninitialized() -> ReentrantMutex {
         ReentrantMutex {
-            owner: AtomicU64::new(0),
+            owner: AtomicU32::new(0),
             recursions: UnsafeCell::new(0),
         }
     }
@@ -101,20 +102,20 @@ impl ReentrantMutex {
     }
 
     pub unsafe fn lock(&self) {
-        let me = thread_id();
+        let me = thread::my_id();
         while let Err(owner) = self._try_lock(me) {
-            let val = atomic::wait_i64(self.ptr(), owner as i64, -1);
+            let val = atomic::wait_i32(self.ptr(), owner as i32, -1);
             debug_assert!(val == 0 || val == 1);
         }
     }
 
     #[inline]
     pub unsafe fn try_lock(&self) -> bool {
-        self._try_lock(thread_id()).is_ok()
+        self._try_lock(thread::my_id()).is_ok()
     }
 
     #[inline]
-    unsafe fn _try_lock(&self, id: u64) -> Result<(), u64> {
+    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
@@ -153,11 +154,7 @@ impl ReentrantMutex {
     }
 
     #[inline]
-    fn ptr(&self) -> *mut i64 {
-        &self.owner as *const AtomicU64 as *mut i64
+    fn ptr(&self) -> *mut i32 {
+        &self.owner as *const AtomicU32 as *mut i32
     }
 }
-
-fn thread_id() -> u64 {
-    panic!("thread ids not implemented on wasm with atomics yet")
-}
diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs
index bef6c1f3490..4ad89c42b92 100644
--- a/src/libstd/sys/wasm/thread.rs
+++ b/src/libstd/sys/wasm/thread.rs
@@ -69,3 +69,49 @@ pub mod guard {
     pub unsafe fn init() -> Option<Guard> { None }
     pub unsafe fn deinit() {}
 }
+
+cfg_if! {
+    if #[cfg(all(target_feature = "atomics", feature = "wasm-bindgen-threads"))] {
+        #[link(wasm_import_module = "__wbindgen_thread_xform__")]
+        extern {
+            fn __wbindgen_current_id() -> u32;
+            fn __wbindgen_tcb_get() -> u32;
+            fn __wbindgen_tcb_set(ptr: u32);
+        }
+        pub fn my_id() -> u32 {
+            unsafe { __wbindgen_current_id() }
+        }
+
+        // These are currently only ever used in `thread_local_atomics.rs`, if
+        // you'd like to use them be sure to update that and make sure everyone
+        // agrees what's what.
+        pub fn tcb_get() -> *mut u8 {
+            use mem;
+            assert_eq!(mem::size_of::<*mut u8>(), mem::size_of::<u32>());
+            unsafe { __wbindgen_tcb_get() as *mut u8 }
+        }
+
+        pub fn tcb_set(ptr: *mut u8) {
+            unsafe { __wbindgen_tcb_set(ptr as u32); }
+        }
+
+        // FIXME: still need something for hooking exiting a thread to free
+        // data...
+
+    } else if #[cfg(target_feature = "atomics")] {
+        pub fn my_id() -> u32 {
+            panic!("thread ids not implemented on wasm with atomics yet")
+        }
+
+        pub fn tcb_get() -> *mut u8 {
+            panic!("thread local data not implemented on wasm with atomics yet")
+        }
+
+        pub fn tcb_set(ptr: *mut u8) {
+            panic!("thread local data not implemented on wasm with atomics yet")
+        }
+    } else {
+        // stubbed out because no functions actually access these intrinsics
+        // unless atomics are enabled
+    }
+}
diff --git a/src/libstd/sys/wasm/thread_local_atomics.rs b/src/libstd/sys/wasm/thread_local_atomics.rs
index 1394013b4a3..acfe60719f2 100644
--- a/src/libstd/sys/wasm/thread_local_atomics.rs
+++ b/src/libstd/sys/wasm/thread_local_atomics.rs
@@ -8,22 +8,61 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use sys::thread;
+use sync::atomic::{AtomicUsize, Ordering::SeqCst};
+
+const MAX_KEYS: usize = 128;
+static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);
+
+struct ThreadControlBlock {
+    keys: [*mut u8; MAX_KEYS],
+}
+
+impl ThreadControlBlock {
+    fn new() -> ThreadControlBlock {
+        ThreadControlBlock {
+            keys: [0 as *mut u8; MAX_KEYS],
+        }
+    }
+
+    fn get() -> *mut ThreadControlBlock {
+        let ptr = thread::tcb_get();
+        if !ptr.is_null() {
+            return ptr as *mut ThreadControlBlock
+        }
+        let tcb = Box::into_raw(Box::new(ThreadControlBlock::new()));
+        thread::tcb_set(tcb as *mut u8);
+        tcb
+    }
+}
+
 pub type Key = usize;
 
-pub unsafe fn create(_dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
-    panic!("TLS on wasm with atomics not implemented yet");
+pub unsafe fn create(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
+    drop(dtor); // FIXME: need to figure out how to hook thread exit to run this
+    let key = NEXT_KEY.fetch_add(1, SeqCst);
+    if key >= MAX_KEYS {
+        NEXT_KEY.store(MAX_KEYS, SeqCst);
+        panic!("cannot allocate space for more TLS keys");
+    }
+    // offset by 1 so we never hand out 0. This is currently required by
+    // `sys_common/thread_local.rs` where it can't cope with keys of value 0
+    // because it messes up the atomic management.
+    return key + 1
 }
 
-pub unsafe fn set(_key: Key, _value: *mut u8) {
-    panic!("TLS on wasm with atomics not implemented yet");
+pub unsafe fn set(key: Key, value: *mut u8) {
+    (*ThreadControlBlock::get()).keys[key - 1] = value;
 }
 
-pub unsafe fn get(_key: Key) -> *mut u8 {
-    panic!("TLS on wasm with atomics not implemented yet");
+pub unsafe fn get(key: Key) -> *mut u8 {
+    (*ThreadControlBlock::get()).keys[key - 1]
 }
 
 pub unsafe fn destroy(_key: Key) {
-    panic!("TLS on wasm with atomics not implemented yet");
+    // FIXME: should implement this somehow, this isn't typically called but it
+    // can be called if two threads race to initialize a TLS slot and one ends
+    // up not being needed.
 }
 
 #[inline]
diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs
index a170abb2628..59f100fad1b 100644
--- a/src/libstd/thread/local.rs
+++ b/src/libstd/thread/local.rs
@@ -172,16 +172,22 @@ macro_rules! __thread_local_inner {
                 &'static $crate::cell::UnsafeCell<
                     $crate::option::Option<$t>>>
             {
-                #[cfg(target_arch = "wasm32")]
+                #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
                 static __KEY: $crate::thread::__StaticLocalKeyInner<$t> =
                     $crate::thread::__StaticLocalKeyInner::new();
 
                 #[thread_local]
-                #[cfg(all(target_thread_local, not(target_arch = "wasm32")))]
+                #[cfg(all(
+                    target_thread_local,
+                    not(all(target_arch = "wasm32", not(target_feature = "atomics"))),
+                ))]
                 static __KEY: $crate::thread::__FastLocalKeyInner<$t> =
                     $crate::thread::__FastLocalKeyInner::new();
 
-                #[cfg(all(not(target_thread_local), not(target_arch = "wasm32")))]
+                #[cfg(all(
+                    not(target_thread_local),
+                    not(all(target_arch = "wasm32", not(target_feature = "atomics"))),
+                ))]
                 static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
                     $crate::thread::__OsLocalKeyInner::new();
 
@@ -302,7 +308,7 @@ impl<T: 'static> LocalKey<T> {
 /// On some platforms like wasm32 there's no threads, so no need to generate
 /// thread locals and we can instead just use plain statics!
 #[doc(hidden)]
-#[cfg(target_arch = "wasm32")]
+#[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
 pub mod statik {
     use cell::UnsafeCell;
     use fmt;
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index c8d54a63946..796b2bd3eed 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -203,7 +203,7 @@ pub use self::local::{LocalKey, AccessError};
 // where available, but both are needed.
 
 #[unstable(feature = "libstd_thread_internals", issue = "0")]
-#[cfg(target_arch = "wasm32")]
+#[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
 #[doc(hidden)] pub use self::local::statik::Key as __StaticLocalKeyInner;
 #[unstable(feature = "libstd_thread_internals", issue = "0")]
 #[cfg(target_thread_local)]