1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! This is an implementation of a global allocator on the wasm32 platform when
12 //! emscripten is not in use. In that situation there's no actual runtime for us
13 //! to lean on for allocation, so instead we provide our own!
15 //! The wasm32 instruction set has two instructions for getting the current
16 //! amount of memory and growing the amount of memory. These instructions are the
17 //! foundation on which we're able to build an allocator, so we do so! Note that
18 //! the instructions are also pretty "global" and this is the "global" allocator
21 //! The current allocator here is the `dlmalloc` crate which we've got included
22 //! in the rust-lang/rust repository as a submodule. The crate is a port of
23 //! dlmalloc.c from C to Rust and is basically just so we can have "pure Rust"
24 //! for now which is currently technically required (can't link with C yet).
26 //! The crate itself provides a global allocator which on wasm has no
27 //! synchronization as there are no threads!
29 extern crate dlmalloc;
31 use alloc::{GlobalAlloc, Layout, System};
33 static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT;
35 #[stable(feature = "alloc_system_type", since = "1.28.0")]
36 unsafe impl GlobalAlloc for System {
38 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
39 let _lock = lock::lock();
40 DLMALLOC.malloc(layout.size(), layout.align())
44 unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
45 let _lock = lock::lock();
46 DLMALLOC.calloc(layout.size(), layout.align())
50 unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
51 let _lock = lock::lock();
52 DLMALLOC.free(ptr, layout.size(), layout.align())
56 unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
57 let _lock = lock::lock();
58 DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size)
62 #[cfg(target_feature = "atomics")]
65 use sync::atomic::{AtomicI32, Ordering::SeqCst};
67 static LOCKED: AtomicI32 = AtomicI32::new(0);
71 pub fn lock() -> DropLock {
73 if LOCKED.swap(1, SeqCst) == 0 {
77 let r = wasm32::i32_atomic_wait(
78 &LOCKED as *const AtomicI32 as *mut i32,
82 debug_assert!(r == 0 || r == 1);
87 impl Drop for DropLock {
89 let r = LOCKED.swap(0, SeqCst);
90 debug_assert_eq!(r, 1);
92 wasm32::atomic_notify(
93 &LOCKED as *const AtomicI32 as *mut i32,
101 #[cfg(not(target_feature = "atomics"))]
104 pub fn lock() {} // no atomics, no threads, that's easy!