about summary refs log tree commit diff
path: root/src/liballoc_system
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-10-12 15:00:24 +0000
committerbors <bors@rust-lang.org>2018-10-12 15:00:24 +0000
commit945372d26818f93d6f5cded7b751749e280b67bf (patch)
tree434e524cba2dee5a76b2aca15ef28c1f3229ff8e /src/liballoc_system
parente9e27e6a6258b3adf00a5dd35d2676656224880d (diff)
parentd64c77a671390a7ce9072e550ffa57837892a4fe (diff)
downloadrust-945372d26818f93d6f5cded7b751749e280b67bf.tar.gz
rust-945372d26818f93d6f5cded7b751749e280b67bf.zip
Auto merge of #55012 - kennytm:rollup, r=kennytm
Rollup of 16 pull requests

Successful merges:

 - #54755 (Documents reference equality by address (#54197))
 - #54811 (During rustc bootstrap, make default for `optimize` independent of `debug`)
 - #54825 (NLL says "borrowed content" instead of more precise "dereference of raw pointer")
 - #54860 (Add doc comments about safest way to initialize a vector of zeros)
 - #54869 (Fix mobile docs)
 - #54891 (Fix tracking issue for Once::is_completed)
 - #54913 (doc fix: it's auto traits that make for automatic implementations)
 - #54920 (Fix handling of #[must_use] on unit and uninhabited types)
 - #54932 (A handful of random string-related improvements)
 - #54936 (impl Eq+Hash for TyLayout)
 - #54950 (std: Synchronize global allocator on wasm32)
 - #54956 ("(using ..." doesn't have the matching ")")
 - #54958 (add a macro for static (compile-time) assertions)
 - #54967 (Remove incorrect span for second label inner macro invocation)
 - #54983 (Fix slice's benchmarks)
 - #54989 (Fix spelling in the documentation to htmldocck.py)

Failed merges:

r? @ghost
Diffstat (limited to 'src/liballoc_system')
-rw-r--r--src/liballoc_system/lib.rs53
1 files changed, 52 insertions, 1 deletions
diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs
index 3ef03ec6d58..15283036bb4 100644
--- a/src/liballoc_system/lib.rs
+++ b/src/liballoc_system/lib.rs
@@ -20,6 +20,10 @@
 #![feature(nll)]
 #![feature(staged_api)]
 #![feature(rustc_attrs)]
+#![cfg_attr(
+    all(target_arch = "wasm32", not(target_os = "emscripten")),
+    feature(integer_atomics, stdsimd)
+)]
 #![cfg_attr(any(unix, target_os = "cloudabi", target_os = "redox"), feature(libc))]
 #![rustc_alloc_kind = "lib"]
 
@@ -331,29 +335,76 @@ mod platform {
     use core::alloc::{GlobalAlloc, Layout};
     use System;
 
-    // No need for synchronization here as wasm is currently single-threaded
     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 core::arch::wasm32;
+        use core::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
+                }
+                unsafe {
+                    let r = wasm32::atomic::wait_i32(
+                        &LOCKED as *const AtomicI32 as *mut i32,
+                        1,  // expected value
+                        -1, // timeout
+                    );
+                    debug_assert!(r == 0 || r == 1);
+                }
+            }
+        }
+
+        impl Drop for DropLock {
+            fn drop(&mut self) {
+                let r = LOCKED.swap(0, SeqCst);
+                debug_assert_eq!(r, 1);
+                unsafe {
+                    wasm32::atomic::wake(
+                        &LOCKED as *const AtomicI32 as *mut i32,
+                        1, // only one thread
+                    );
+                }
+            }
+        }
+    }
+
+    #[cfg(not(target_feature = "atomics"))]
+    mod lock {
+        pub fn lock() {} // no atomics, no threads, that's easy!
+    }
 }