Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions library/std/src/sys/alloc/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@
//! The crate itself provides a global allocator which on wasm has no
//! synchronization as there are no threads!

// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
#![allow(static_mut_refs)]
use core::cell::SyncUnsafeCell;

use crate::alloc::{GlobalAlloc, Layout, System};

static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::Dlmalloc::new();
struct SyncDlmalloc(dlmalloc::Dlmalloc);
unsafe impl Sync for SyncDlmalloc {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only safe if we're in WASM without threads, is this file already gated for that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same file also contains a Lock impl for the case there are threads, which is used to guard the Allocator impl against unsynchronized accesses.


static DLMALLOC: SyncUnsafeCell<SyncDlmalloc> =
SyncUnsafeCell::new(SyncDlmalloc(dlmalloc::Dlmalloc::new()));

#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
Expand All @@ -30,31 +33,31 @@ unsafe impl GlobalAlloc for System {
// SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access.
// Calling malloc() is safe because preconditions on this function match the trait method preconditions.
let _lock = lock::lock();
unsafe { DLMALLOC.malloc(layout.size(), layout.align()) }
unsafe { (*DLMALLOC.get()).0.malloc(layout.size(), layout.align()) }
}

#[inline]
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
// SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access.
// Calling calloc() is safe because preconditions on this function match the trait method preconditions.
let _lock = lock::lock();
unsafe { DLMALLOC.calloc(layout.size(), layout.align()) }
unsafe { (*DLMALLOC.get()).0.calloc(layout.size(), layout.align()) }
}

#[inline]
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
// SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access.
// Calling free() is safe because preconditions on this function match the trait method preconditions.
let _lock = lock::lock();
unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) }
unsafe { (*DLMALLOC.get()).0.free(ptr, layout.size(), layout.align()) }
}

#[inline]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
// SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access.
// Calling realloc() is safe because preconditions on this function match the trait method preconditions.
let _lock = lock::lock();
unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) }
unsafe { (*DLMALLOC.get()).0.realloc(ptr, layout.size(), layout.align(), new_size) }
}
}

Expand Down
Loading