diff --git a/library/core/src/alloc/global.rs b/library/core/src/alloc/global.rs
index e97398aa5dc4a..44a8ab6e54196 100644
--- a/library/core/src/alloc/global.rs
+++ b/library/core/src/alloc/global.rs
@@ -1,4 +1,7 @@
+use super::{AllocError, GlobalAllocator};
use crate::alloc::Layout;
+use crate::hint::assert_unchecked;
+use crate::ptr::NonNull;
use crate::{cmp, ptr};
/// A memory allocator that can be registered as the standard library’s default
@@ -301,3 +304,72 @@ pub unsafe trait GlobalAlloc {
new_ptr
}
}
+
+/// Allows all [`GlobalAllocator`]s to be used with the legacy [`GlobalAlloc`] interface.
+#[stable(feature = "global_alloc", since = "1.28.0")]
+unsafe impl GlobalAlloc for A
+where
+ A: GlobalAllocator + ?Sized,
+{
+ unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+ // SAFETY: guaranteed by the caller.
+ // This might lead to the removal of zero-size checks inside the
+ // `Allocator` implementation.
+ unsafe { assert_unchecked(layout.size() != 0) };
+ match self.allocate(layout) {
+ Ok(ptr) => ptr.cast().as_ptr(),
+ Err(AllocError) => ptr::null_mut(),
+ }
+ }
+
+ unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+ // SAFETY: guaranteed by the caller.
+ unsafe { assert_unchecked(layout.size() != 0) };
+ // SAFETY: only non-null pointers can be currently allocated.
+ let ptr = unsafe { NonNull::new_unchecked(ptr) };
+ // SAFETY: guaranteed by caller.
+ unsafe { self.deallocate(ptr, layout) };
+ }
+
+ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
+ // SAFETY: guaranteed by the caller.
+ unsafe { assert_unchecked(layout.size() != 0) };
+ match self.allocate_zeroed(layout) {
+ Ok(ptr) => ptr.cast().as_ptr(),
+ Err(AllocError) => ptr::null_mut(),
+ }
+ }
+
+ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+ // SAFETY: guaranteed by the caller.
+ unsafe { assert_unchecked(layout.size() != 0) };
+ // SAFETY: guaranteed by the caller.
+ unsafe { assert_unchecked(new_size != 0) };
+
+ // SAFETY: only non-null pointers can be currently allocated.
+ let ptr = unsafe { NonNull::new_unchecked(ptr) };
+ let alignment = layout.alignment();
+ // SAFETY: the caller must ensure that the `new_size` does not overflow
+ // when rounded up to the next multiple of `alignment`.
+ let new_layout = unsafe { Layout::from_size_alignment_unchecked(new_size, alignment) };
+
+ // SAFETY:
+ // Two preconditions are guaranteed by the caller:
+ // * `ptr` is currently allocated with this allocator.
+ // * `layout` fits the block of memory.
+ // The size precondition is upheld by selecting between `grow` and `shrink`
+ // based on the size.
+ let ptr = unsafe {
+ if new_size >= layout.size() {
+ self.grow(ptr, layout, new_layout)
+ } else {
+ self.shrink(ptr, layout, new_layout)
+ }
+ };
+
+ match ptr {
+ Ok(ptr) => ptr.cast().as_ptr(),
+ Err(AllocError) => ptr::null_mut(),
+ }
+ }
+}
diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs
index 102fb19efc8ea..b70fd827990a0 100644
--- a/library/core/src/alloc/mod.rs
+++ b/library/core/src/alloc/mod.rs
@@ -375,6 +375,96 @@ pub const unsafe trait Allocator {
}
}
+/// An [`Allocator`] that can be registered as the standard library’s default
+/// through the `#[global_allocator]` attribute.
+///
+/// Types implementing this trait can be used as the default allocator for
+/// memory allocations through `Box`, `Vec` and the collection types. For
+/// instance, the `System` allocator implements this trait, and thus can be
+/// explicitly set as the default like so:
+/// ```
+/// use std::alloc::System;
+///
+/// #[global_allocator]
+/// static ALLOCATOR: System = System;
+/// ```
+///
+/// The `Global` allocator forwards all memory allocation requests to the
+/// `static` annotated with `#[global_allocator]`. Hence, `Global` does not
+/// implement `GlobalAllocator` itself, as that would lead to infinite recursion.
+///
+/// # Note to implementors
+///
+/// This trait is used to prevent the infinite recursion that would occur if the
+/// default allocator were to attempt to allocate memory through `Global` (and
+/// thus from itself).
+///
+/// When to implement this trait:
+/// * for custom global allocators that only use system memory allocation
+/// services.
+/// * for allocators that wrap another allocator that implements `GlobalAllocator`.
+///
+/// When **not** to implement this trait:
+/// * for wrappers of arbitrary allocators (which might end up being `Global`,
+/// leading to infinite recursion).
+///
+/// # Safety
+///
+/// In addition to the safety requirements of `Allocator`, global allocators are
+/// subject to some additional constraints:
+///
+/// * It's undefined behavior if global allocators unwind. This restriction may
+/// be lifted in the future, but currently a panic from any of these
+/// functions may lead to memory unsafety.
+///
+/// * You must not rely on allocations actually happening, even if there are explicit
+/// heap allocations in the source. The optimizer may detect unused allocations that it can either
+/// eliminate entirely or move to the stack and thus never invoke the allocator. The
+/// optimizer may further assume that allocation is infallible, so code that used to fail due
+/// to allocator failures may now suddenly work because the optimizer worked around the
+/// need for an allocation. More concretely, the following code example is unsound, irrespective
+/// of whether your custom allocator allows counting how many allocations have happened.
+///
+/// ```rust,ignore (unsound and has placeholders)
+/// drop(Box::new(42));
+/// let number_of_heap_allocs = /* call private allocator API */;
+/// unsafe { std::hint::assert_unchecked(number_of_heap_allocs > 0); }
+/// ```
+///
+/// Note that the optimizations mentioned above are not the only
+/// optimization that can be applied. You may generally not rely on heap allocations
+/// happening if they can be removed without changing program behavior.
+/// Whether allocations happen or not is not part of the program behavior, even if it
+/// could be detected via an allocator that tracks allocations by printing or otherwise
+/// having side effects.
+///
+/// # Re-entrance
+///
+/// When implementing a global allocator, one has to be careful not to create an infinitely recursive
+/// implementation by accident, as many constructs in the Rust standard library may allocate in
+/// their implementation. For example, on some platforms, [`std::sync::Mutex`] may allocate, so using
+/// it is highly problematic in a global allocator.
+///
+/// For this reason, one should generally stick to library features available through
+/// [`core`], and avoid using [`std`] in a global allocator. A few features from [`std`] are
+/// guaranteed to not use `#[global_allocator]` to allocate:
+///
+/// - [`std::thread_local`],
+/// - [`std::thread::current`],
+/// - [`std::thread::park`] and [`std::thread::Thread`]'s [`unpark`] method and
+/// [`Clone`] implementation.
+///
+/// [`std`]: ../../std/index.html
+/// [`std::sync::Mutex`]: ../../std/sync/struct.Mutex.html
+/// [`std::thread_local`]: ../../std/macro.thread_local.html
+/// [`std::thread::current`]: ../../std/thread/fn.current.html
+/// [`std::thread::park`]: ../../std/thread/fn.park.html
+/// [`std::thread::Thread`]: ../../std/thread/struct.Thread.html
+/// [`unpark`]: ../../std/thread/struct.Thread.html#method.unpark
+#[unstable(feature = "allocator_api", issue = "32838")]
+#[expect(multiple_supertrait_upcastable)]
+pub unsafe trait GlobalAllocator: Allocator + Sync + 'static {}
+
#[unstable(feature = "allocator_api", issue = "32838")]
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
const unsafe impl Allocator for &A
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index 7a576e083df7c..753ca5aba561c 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -63,14 +63,15 @@
#![deny(unsafe_op_in_unsafe_fn)]
#![stable(feature = "alloc_module", since = "1.28.0")]
-use core::ptr::NonNull;
-use core::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
-use core::{hint, mem, ptr};
-
#[stable(feature = "alloc_module", since = "1.28.0")]
#[doc(inline)]
pub use alloc_crate::alloc::*;
+use crate::ptr::NonNull;
+use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
+use crate::sys::alloc as imp;
+use crate::{hint, mem, ptr};
+
/// The default memory allocator provided by the operating system.
///
/// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows,
@@ -145,11 +146,7 @@ impl System {
0 => Ok(layout.dangling_ptr().cast_slice(0)),
// SAFETY: `layout` is non-zero in size,
size => unsafe {
- let raw_ptr = if zeroed {
- GlobalAlloc::alloc_zeroed(self, layout)
- } else {
- GlobalAlloc::alloc(self, layout)
- };
+ let raw_ptr = if zeroed { imp::alloc_zeroed(layout) } else { imp::alloc(layout) };
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
Ok(ptr.cast_slice(size))
},
@@ -182,7 +179,7 @@ impl System {
// `realloc` probably checks for `new_size >= old_layout.size()` or something similar.
hint::assert_unchecked(new_size >= old_layout.size());
- let raw_ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), old_layout, new_size);
+ let raw_ptr = imp::realloc(ptr.as_ptr(), old_layout, new_size);
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
if zeroed {
raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
@@ -205,8 +202,8 @@ impl System {
}
}
-// The Allocator impl checks the layout size to be non-zero and forwards to the GlobalAlloc impl,
-// which is in `std::sys::*::alloc`.
+// The Allocator impl checks the layout size to be non-zero and forwards to the
+// platform functions in `std::sys::*::alloc`.
#[unstable(feature = "allocator_api", issue = "32838")]
unsafe impl Allocator for System {
#[inline]
@@ -224,7 +221,7 @@ unsafe impl Allocator for System {
if layout.size() != 0 {
// SAFETY: `layout` is non-zero in size,
// other conditions must be upheld by the caller
- unsafe { GlobalAlloc::dealloc(self, ptr.as_ptr(), layout) }
+ unsafe { imp::dealloc(ptr.as_ptr(), layout) }
}
}
@@ -274,7 +271,7 @@ unsafe impl Allocator for System {
// `realloc` probably checks for `new_size <= old_layout.size()` or something similar.
hint::assert_unchecked(new_size <= old_layout.size());
- let raw_ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), old_layout, new_size);
+ let raw_ptr = imp::realloc(ptr.as_ptr(), old_layout, new_size);
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
Ok(ptr.cast_slice(new_size))
},
@@ -294,6 +291,9 @@ unsafe impl Allocator for System {
}
}
+#[unstable(feature = "allocator_api", issue = "32838")]
+unsafe impl GlobalAllocator for System {}
+
static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
/// Registers a custom allocation error hook, replacing any that was previously registered.
@@ -435,7 +435,12 @@ pub fn rust_oom(layout: Layout) -> ! {
#[allow(unused_attributes)]
#[unstable(feature = "alloc_internals", issue = "none")]
pub mod __default_lib_allocator {
- use super::{GlobalAlloc, Layout, System};
+ use super::Layout;
+ // We call the system functions directly to avoid any overheads introduced
+ // by the roundtrip through `impl Allocator for System` and
+ // `impl GlobalAlloc for A`.
+ use crate::sys::alloc as imp;
+
// These magic symbol names are used as a fallback for implementing the
// `__rust_alloc` etc symbols (see `src/liballoc/alloc.rs`) when there is
// no `#[global_allocator]` attribute.
@@ -452,7 +457,7 @@ pub mod __default_lib_allocator {
// `GlobalAlloc::alloc`.
unsafe {
let layout = Layout::from_size_align_unchecked(size, align);
- System.alloc(layout)
+ imp::alloc(layout)
}
}
@@ -460,7 +465,7 @@ pub mod __default_lib_allocator {
pub unsafe extern "C" fn __rdl_dealloc(ptr: *mut u8, size: usize, align: usize) {
// SAFETY: see the guarantees expected by `Layout::from_size_align` and
// `GlobalAlloc::dealloc`.
- unsafe { System.dealloc(ptr, Layout::from_size_align_unchecked(size, align)) }
+ unsafe { imp::dealloc(ptr, Layout::from_size_align_unchecked(size, align)) }
}
#[rustc_std_internal_symbol]
@@ -474,7 +479,7 @@ pub mod __default_lib_allocator {
// `GlobalAlloc::realloc`.
unsafe {
let old_layout = Layout::from_size_align_unchecked(old_size, align);
- System.realloc(ptr, old_layout, new_size)
+ imp::realloc(ptr, old_layout, new_size)
}
}
@@ -484,7 +489,7 @@ pub mod __default_lib_allocator {
// `GlobalAlloc::alloc_zeroed`.
unsafe {
let layout = Layout::from_size_align_unchecked(size, align);
- System.alloc_zeroed(layout)
+ imp::alloc_zeroed(layout)
}
}
}
diff --git a/library/std/src/sys/alloc/hermit.rs b/library/std/src/sys/alloc/hermit.rs
index 77f8200a70a64..9afcb315f4ab5 100644
--- a/library/std/src/sys/alloc/hermit.rs
+++ b/library/std/src/sys/alloc/hermit.rs
@@ -1,27 +1,24 @@
-use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::alloc::Layout;
-#[stable(feature = "alloc_system_type", since = "1.28.0")]
-unsafe impl GlobalAlloc for System {
- #[inline]
- unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- let size = layout.size();
- let align = layout.align();
- unsafe { hermit_abi::malloc(size, align) }
- }
+#[inline]
+pub unsafe fn alloc(layout: Layout) -> *mut u8 {
+ let size = layout.size();
+ let align = layout.align();
+ unsafe { hermit_abi::malloc(size, align) }
+}
- #[inline]
- unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
- let size = layout.size();
- let align = layout.align();
- unsafe {
- hermit_abi::free(ptr, size, align);
- }
+#[inline]
+pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
+ let size = layout.size();
+ let align = layout.align();
+ unsafe {
+ hermit_abi::free(ptr, size, align);
}
+}
- #[inline]
- unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
- let size = layout.size();
- let align = layout.align();
- unsafe { hermit_abi::realloc(ptr, size, align, new_size) }
- }
+#[inline]
+pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+ let size = layout.size();
+ let align = layout.align();
+ unsafe { hermit_abi::realloc(ptr, size, align, new_size) }
}
diff --git a/library/std/src/sys/alloc/mod.rs b/library/std/src/sys/alloc/mod.rs
index f2f1d1c7feceb..73d35781f09bf 100644
--- a/library/std/src/sys/alloc/mod.rs
+++ b/library/std/src/sys/alloc/mod.rs
@@ -1,6 +1,6 @@
#![forbid(unsafe_op_in_unsafe_fn)]
-use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::alloc::Layout;
use crate::ptr;
// The minimum alignment guaranteed by the architecture. This value is used to
@@ -47,21 +47,16 @@ const MIN_ALIGN: usize = if cfg!(any(
};
#[allow(dead_code)]
-unsafe fn realloc_fallback(
- alloc: &System,
- ptr: *mut u8,
- old_layout: Layout,
- new_size: usize,
-) -> *mut u8 {
+unsafe fn realloc_fallback(ptr: *mut u8, old_layout: Layout, new_size: usize) -> *mut u8 {
// SAFETY: Docs for GlobalAlloc::realloc require this to be valid
unsafe {
let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align());
- let new_ptr = GlobalAlloc::alloc(alloc, new_layout);
+ let new_ptr = alloc(new_layout);
if !new_ptr.is_null() {
let size = usize::min(old_layout.size(), new_size);
ptr::copy_nonoverlapping(ptr, new_ptr, size);
- GlobalAlloc::dealloc(alloc, ptr, old_layout);
+ dealloc(ptr, old_layout);
}
new_ptr
@@ -76,35 +71,69 @@ cfg_select! {
target_os = "trusty",
) => {
mod unix;
+ use unix as imp;
}
target_os = "windows" => {
mod windows;
+ use windows as imp;
}
target_os = "hermit" => {
mod hermit;
+ use hermit as imp;
}
target_os = "motor" => {
mod motor;
+ use motor as imp;
}
all(target_vendor = "fortanix", target_env = "sgx") => {
mod sgx;
+ use sgx as imp;
}
target_os = "solid_asp3" => {
mod solid;
+ use solid as imp;
}
target_os = "uefi" => {
mod uefi;
+ use uefi as imp;
}
target_os = "vexos" => {
mod vexos;
+ use vexos as imp;
}
target_family = "wasm" => {
mod wasm;
+ use wasm as imp;
}
target_os = "xous" => {
mod xous;
+ use xous as imp;
}
target_os = "zkvm" => {
mod zkvm;
+ use zkvm as imp;
+ }
+}
+
+pub use imp::{alloc, dealloc, realloc};
+
+cfg_select! {
+ any(
+ target_os = "hermit",
+ target_os = "solid_asp3",
+ target_os = "uefi",
+ target_os = "zkvm",
+ ) => {
+ #[inline]
+ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
+ let ptr = unsafe { alloc(layout) };
+ if !ptr.is_null() {
+ unsafe { ptr.write_bytes(0, layout.size()) };
+ }
+ ptr
+ }
+ }
+ _ => {
+ pub use imp::alloc_zeroed;
}
}
diff --git a/library/std/src/sys/alloc/motor.rs b/library/std/src/sys/alloc/motor.rs
index 271e3c40c26ae..090dc198bb500 100644
--- a/library/std/src/sys/alloc/motor.rs
+++ b/library/std/src/sys/alloc/motor.rs
@@ -1,28 +1,13 @@
-use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::alloc::Layout;
-#[stable(feature = "alloc_system_type", since = "1.28.0")]
-unsafe impl GlobalAlloc for System {
- #[inline]
- unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- // SAFETY: same requirements as in GlobalAlloc::alloc.
- moto_rt::alloc::alloc(layout)
- }
-
- #[inline]
- unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
- // SAFETY: same requirements as in GlobalAlloc::alloc_zeroed.
- moto_rt::alloc::alloc_zeroed(layout)
- }
-
- #[inline]
- unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
- // SAFETY: same requirements as in GlobalAlloc::dealloc.
- unsafe { moto_rt::alloc::dealloc(ptr, layout) }
- }
+#[inline]
+pub unsafe fn alloc(layout: Layout) -> *mut u8 {
+ moto_rt::alloc::alloc(layout)
+}
- #[inline]
- unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
- // SAFETY: same requirements as in GlobalAlloc::realloc.
- unsafe { moto_rt::alloc::realloc(ptr, layout, new_size) }
- }
+#[inline]
+pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
+ moto_rt::alloc::alloc_zeroed(layout)
}
+
+pub use moto_rt::alloc::{dealloc, realloc};
diff --git a/library/std/src/sys/alloc/sgx.rs b/library/std/src/sys/alloc/sgx.rs
index afdef7a5cb647..c20761259048e 100644
--- a/library/std/src/sys/alloc/sgx.rs
+++ b/library/std/src/sys/alloc/sgx.rs
@@ -1,4 +1,4 @@
-use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::alloc::Layout;
use crate::ptr;
use crate::sync::atomic::{Atomic, AtomicBool, Ordering};
use crate::sys::pal::abi::mem as sgx_mem;
@@ -57,31 +57,28 @@ unsafe impl dlmalloc::Allocator for Sgx {
}
}
-#[stable(feature = "alloc_system_type", since = "1.28.0")]
-unsafe impl GlobalAlloc for System {
- #[inline]
- unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- // SAFETY: the caller must uphold the safety contract for `malloc`
- unsafe { DLMALLOC.lock().malloc(layout.size(), layout.align()) }
- }
+#[inline]
+pub unsafe fn alloc(layout: Layout) -> *mut u8 {
+ // SAFETY: the caller must uphold the safety contract for `malloc`
+ unsafe { DLMALLOC.lock().malloc(layout.size(), layout.align()) }
+}
- #[inline]
- unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
- // SAFETY: the caller must uphold the safety contract for `malloc`
- unsafe { DLMALLOC.lock().calloc(layout.size(), layout.align()) }
- }
+#[inline]
+pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
+ // SAFETY: the caller must uphold the safety contract for `malloc`
+ unsafe { DLMALLOC.lock().calloc(layout.size(), layout.align()) }
+}
- #[inline]
- unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
- // SAFETY: the caller must uphold the safety contract for `malloc`
- unsafe { DLMALLOC.lock().free(ptr, layout.size(), layout.align()) }
- }
+#[inline]
+pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
+ // SAFETY: the caller must uphold the safety contract for `malloc`
+ unsafe { DLMALLOC.lock().free(ptr, layout.size(), layout.align()) }
+}
- #[inline]
- unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
- // SAFETY: the caller must uphold the safety contract for `malloc`
- unsafe { DLMALLOC.lock().realloc(ptr, layout.size(), layout.align(), new_size) }
- }
+#[inline]
+pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+ // SAFETY: the caller must uphold the safety contract for `malloc`
+ unsafe { DLMALLOC.lock().realloc(ptr, layout.size(), layout.align(), new_size) }
}
// The following functions are needed by libunwind. These symbols are named
diff --git a/library/std/src/sys/alloc/solid.rs b/library/std/src/sys/alloc/solid.rs
index 47cfa2eb1162b..5d3f396f0dd11 100644
--- a/library/std/src/sys/alloc/solid.rs
+++ b/library/std/src/sys/alloc/solid.rs
@@ -1,30 +1,27 @@
use super::{MIN_ALIGN, realloc_fallback};
-use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::alloc::Layout;
-#[stable(feature = "alloc_system_type", since = "1.28.0")]
-unsafe impl GlobalAlloc for System {
- #[inline]
- unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
- unsafe { libc::malloc(layout.size()) as *mut u8 }
- } else {
- unsafe { libc::memalign(layout.align(), layout.size()) as *mut u8 }
- }
+#[inline]
+pub unsafe fn alloc(layout: Layout) -> *mut u8 {
+ if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
+ unsafe { libc::malloc(layout.size()) as *mut u8 }
+ } else {
+ unsafe { libc::memalign(layout.align(), layout.size()) as *mut u8 }
}
+}
- #[inline]
- unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
- unsafe { libc::free(ptr as *mut libc::c_void) }
- }
+#[inline]
+pub unsafe fn dealloc(ptr: *mut u8, _layout: Layout) {
+ unsafe { libc::free(ptr as *mut libc::c_void) }
+}
- #[inline]
- unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
- unsafe {
- if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
- libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8
- } else {
- realloc_fallback(self, ptr, layout, new_size)
- }
+#[inline]
+pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+ unsafe {
+ if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
+ libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8
+ } else {
+ realloc_fallback(ptr, layout, new_size)
}
}
}
diff --git a/library/std/src/sys/alloc/uefi.rs b/library/std/src/sys/alloc/uefi.rs
index 5221876e90866..aa7fcc9fe110c 100644
--- a/library/std/src/sys/alloc/uefi.rs
+++ b/library/std/src/sys/alloc/uefi.rs
@@ -3,47 +3,48 @@
use r_efi::protocols::loaded_image;
-use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::alloc::Layout;
use crate::sync::OnceLock;
use crate::sys::pal::helpers;
-#[stable(feature = "alloc_system_type", since = "1.28.0")]
-unsafe impl GlobalAlloc for System {
- unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- static EFI_MEMORY_TYPE: OnceLock = OnceLock::new();
-
- // Return null pointer if boot services are not available
- if crate::os::uefi::env::boot_services().is_none() {
- return crate::ptr::null_mut();
- }
-
- // If boot services is valid then SystemTable is not null.
- let system_table = crate::os::uefi::env::system_table().as_ptr().cast();
-
- // Each loaded image has an image handle that supports `EFI_LOADED_IMAGE_PROTOCOL`. Thus, this
- // will never fail.
- let mem_type = EFI_MEMORY_TYPE.get_or_init(|| {
- let protocol = helpers::image_handle_protocol::(
- loaded_image::PROTOCOL_GUID,
- )
- .unwrap();
- // Gives allocations the memory type that the data sections were loaded as.
- unsafe { (*protocol.as_ptr()).image_data_type }
- });
-
- // The caller must ensure non-0 layout
- unsafe { r_efi_alloc::raw::alloc(system_table, layout, *mem_type) }
+pub unsafe fn alloc(layout: Layout) -> *mut u8 {
+ static EFI_MEMORY_TYPE: OnceLock = OnceLock::new();
+
+ // Return null pointer if boot services are not available
+ if crate::os::uefi::env::boot_services().is_none() {
+ return crate::ptr::null_mut();
}
- unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
- // Do nothing if boot services are not available
- if crate::os::uefi::env::boot_services().is_none() {
- return;
- }
+ // If boot services is valid then SystemTable is not null.
+ let system_table = crate::os::uefi::env::system_table().as_ptr().cast();
+
+ // Each loaded image has an image handle that supports `EFI_LOADED_IMAGE_PROTOCOL`. Thus, this
+ // will never fail.
+ let mem_type = EFI_MEMORY_TYPE.get_or_init(|| {
+ let protocol =
+ helpers::image_handle_protocol::(loaded_image::PROTOCOL_GUID)
+ .unwrap();
+ // Gives allocations the memory type that the data sections were loaded as.
+ unsafe { (*protocol.as_ptr()).image_data_type }
+ });
+
+ // The caller must ensure non-0 layout
+ unsafe { r_efi_alloc::raw::alloc(system_table, layout, *mem_type) }
+}
- // If boot services is valid then SystemTable is not null.
- let system_table = crate::os::uefi::env::system_table().as_ptr().cast();
- // The caller must ensure non-0 layout
- unsafe { r_efi_alloc::raw::dealloc(system_table, ptr, layout) }
+pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
+ // Do nothing if boot services are not available
+ if crate::os::uefi::env::boot_services().is_none() {
+ return;
}
+
+ // If boot services is valid then SystemTable is not null.
+ let system_table = crate::os::uefi::env::system_table().as_ptr().cast();
+ // The caller must ensure non-0 layout
+ unsafe { r_efi_alloc::raw::dealloc(system_table, ptr, layout) }
+}
+
+pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+ // SAFETY: this is just a `pub` wrapper.
+ unsafe { super::realloc_fallback(ptr, layout, new_size) }
}
diff --git a/library/std/src/sys/alloc/unix.rs b/library/std/src/sys/alloc/unix.rs
index 3d369b08abc77..d6de8bf28c44c 100644
--- a/library/std/src/sys/alloc/unix.rs
+++ b/library/std/src/sys/alloc/unix.rs
@@ -1,60 +1,57 @@
use super::{MIN_ALIGN, realloc_fallback};
-use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::alloc::Layout;
use crate::ptr;
-#[stable(feature = "alloc_system_type", since = "1.28.0")]
-unsafe impl GlobalAlloc for System {
- #[inline]
- unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- // jemalloc provides alignment less than MIN_ALIGN for small allocations.
- // So only rely on MIN_ALIGN if size >= align.
- // Also see and
- // .
- if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
- unsafe { libc::malloc(layout.size()) as *mut u8 }
- } else {
- // `posix_memalign` returns a non-aligned value if supplied a very
- // large alignment on older versions of Apple's platforms (unknown
- // exactly which version range, but the issue is definitely
- // present in macOS 10.14 and iOS 13.3).
- //
- //
- #[cfg(target_vendor = "apple")]
- {
- if layout.align() > (1 << 31) {
- return ptr::null_mut();
- }
+#[inline]
+pub unsafe fn alloc(layout: Layout) -> *mut u8 {
+ // jemalloc provides alignment less than MIN_ALIGN for small allocations.
+ // So only rely on MIN_ALIGN if size >= align.
+ // Also see and
+ // .
+ if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
+ unsafe { libc::malloc(layout.size()) as *mut u8 }
+ } else {
+ // `posix_memalign` returns a non-aligned value if supplied a very
+ // large alignment on older versions of Apple's platforms (unknown
+ // exactly which version range, but the issue is definitely
+ // present in macOS 10.14 and iOS 13.3).
+ //
+ //
+ #[cfg(target_vendor = "apple")]
+ {
+ if layout.align() > (1 << 31) {
+ return ptr::null_mut();
}
- unsafe { aligned_malloc(&layout) }
}
+ unsafe { aligned_malloc(&layout) }
}
+}
- #[inline]
- unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
- // See the comment above in `alloc` for why this check looks the way it does.
- if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
- unsafe { libc::calloc(layout.size(), 1) as *mut u8 }
- } else {
- let ptr = unsafe { self.alloc(layout) };
- if !ptr.is_null() {
- unsafe { ptr::write_bytes(ptr, 0, layout.size()) };
- }
- ptr
+#[inline]
+pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
+ // See the comment above in `alloc` for why this check looks the way it does.
+ if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
+ unsafe { libc::calloc(layout.size(), 1) as *mut u8 }
+ } else {
+ let ptr = unsafe { alloc(layout) };
+ if !ptr.is_null() {
+ unsafe { ptr::write_bytes(ptr, 0, layout.size()) };
}
+ ptr
}
+}
- #[inline]
- unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
- unsafe { libc::free(ptr as *mut libc::c_void) }
- }
+#[inline]
+pub unsafe fn dealloc(ptr: *mut u8, _layout: Layout) {
+ unsafe { libc::free(ptr as *mut libc::c_void) }
+}
- #[inline]
- unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
- if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
- unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 }
- } else {
- unsafe { realloc_fallback(self, ptr, layout, new_size) }
- }
+#[inline]
+pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+ if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
+ unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 }
+ } else {
+ unsafe { realloc_fallback(ptr, layout, new_size) }
}
}
diff --git a/library/std/src/sys/alloc/vexos.rs b/library/std/src/sys/alloc/vexos.rs
index c1fb6896a89ae..481462296f8af 100644
--- a/library/std/src/sys/alloc/vexos.rs
+++ b/library/std/src/sys/alloc/vexos.rs
@@ -1,7 +1,7 @@
// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
#![allow(static_mut_refs)]
-use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::alloc::Layout;
use crate::ptr;
use crate::sync::atomic::{AtomicBool, Ordering};
@@ -60,37 +60,34 @@ unsafe impl dlmalloc::Allocator for Vexos {
}
}
-#[stable(feature = "alloc_system_type", since = "1.28.0")]
-unsafe impl GlobalAlloc for System {
- #[inline]
- unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which
- // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used.
- // Calling malloc() is safe because preconditions on this function match the trait method preconditions.
- unsafe { DLMALLOC.malloc(layout.size(), layout.align()) }
- }
+#[inline]
+pub unsafe fn alloc(layout: Layout) -> *mut u8 {
+ // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which
+ // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used.
+ // Calling malloc() is safe because preconditions on this function match the trait method preconditions.
+ unsafe { DLMALLOC.malloc(layout.size(), layout.align()) }
+}
- #[inline]
- unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
- // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which
- // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used.
- // Calling calloc() is safe because preconditions on this function match the trait method preconditions.
- unsafe { DLMALLOC.calloc(layout.size(), layout.align()) }
- }
+#[inline]
+pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
+ // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which
+ // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used.
+ // Calling calloc() is safe because preconditions on this function match the trait method preconditions.
+ unsafe { DLMALLOC.calloc(layout.size(), layout.align()) }
+}
- #[inline]
- unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
- // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which
- // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used.
- // Calling free() is safe because preconditions on this function match the trait method preconditions.
- unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) }
- }
+#[inline]
+pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
+ // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which
+ // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used.
+ // Calling free() is safe because preconditions on this function match the trait method preconditions.
+ unsafe { DLMALLOC.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 we are a single-threaded target, which
- // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used.
- // Calling realloc() is safe because preconditions on this function match the trait method preconditions.
- unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) }
- }
+#[inline]
+pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+ // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which
+ // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used.
+ // Calling realloc() is safe because preconditions on this function match the trait method preconditions.
+ unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) }
}
diff --git a/library/std/src/sys/alloc/wasm.rs b/library/std/src/sys/alloc/wasm.rs
index 48e2fdd4eccec..995230aebaa01 100644
--- a/library/std/src/sys/alloc/wasm.rs
+++ b/library/std/src/sys/alloc/wasm.rs
@@ -18,7 +18,7 @@
use core::cell::SyncUnsafeCell;
-use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::alloc::Layout;
struct SyncDlmalloc(dlmalloc::Dlmalloc);
unsafe impl Sync for SyncDlmalloc {}
@@ -26,39 +26,36 @@ unsafe impl Sync for SyncDlmalloc {}
static DLMALLOC: SyncUnsafeCell =
SyncUnsafeCell::new(SyncDlmalloc(dlmalloc::Dlmalloc::new()));
-#[stable(feature = "alloc_system_type", since = "1.28.0")]
-unsafe impl GlobalAlloc for System {
- #[inline]
- unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- // 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.get()).0.malloc(layout.size(), layout.align()) }
- }
+#[inline]
+pub unsafe fn alloc(layout: Layout) -> *mut u8 {
+ // 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.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.get()).0.calloc(layout.size(), layout.align()) }
- }
+#[inline]
+pub unsafe fn alloc_zeroed(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.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.get()).0.free(ptr, layout.size(), layout.align()) }
- }
+#[inline]
+pub unsafe fn dealloc(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.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.get()).0.realloc(ptr, layout.size(), layout.align(), new_size) }
- }
+#[inline]
+pub unsafe fn realloc(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.get()).0.realloc(ptr, layout.size(), layout.align(), new_size) }
}
#[cfg(target_feature = "atomics")]
diff --git a/library/std/src/sys/alloc/windows.rs b/library/std/src/sys/alloc/windows.rs
index 9336a6ec085aa..1d75cbd9d54f1 100644
--- a/library/std/src/sys/alloc/windows.rs
+++ b/library/std/src/sys/alloc/windows.rs
@@ -1,5 +1,18 @@
+//! Implements `System` on Windows.
+//!
+//! All pointers returned by this allocator have, in addition to the guarantees of `GlobalAlloc`, the
+//! following properties:
+//!
+//! If the pointer was allocated or reallocated with a `layout` specifying an alignment <= `MIN_ALIGN`
+//! the pointer will be aligned to at least `MIN_ALIGN` and point to the start of the allocated block.
+//!
+//! If the pointer was allocated or reallocated with a `layout` specifying an alignment > `MIN_ALIGN`
+//! the pointer will be aligned to the specified alignment and not point to the start of the allocated block.
+//! Instead there will be a header readable directly before the returned pointer, containing the actual
+//! location of the start of the block.
+
use super::{MIN_ALIGN, realloc_fallback};
-use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::alloc::Layout;
use crate::ffi::c_void;
use crate::mem::MaybeUninit;
use crate::ptr;
@@ -150,70 +163,56 @@ unsafe fn allocate(layout: Layout, zeroed: bool) -> *mut u8 {
}
}
-// All pointers returned by this allocator have, in addition to the guarantees of `GlobalAlloc`, the
-// following properties:
-//
-// If the pointer was allocated or reallocated with a `layout` specifying an alignment <= `MIN_ALIGN`
-// the pointer will be aligned to at least `MIN_ALIGN` and point to the start of the allocated block.
-//
-// If the pointer was allocated or reallocated with a `layout` specifying an alignment > `MIN_ALIGN`
-// the pointer will be aligned to the specified alignment and not point to the start of the allocated block.
-// Instead there will be a header readable directly before the returned pointer, containing the actual
-// location of the start of the block.
-#[stable(feature = "alloc_system_type", since = "1.28.0")]
-unsafe impl GlobalAlloc for System {
- #[inline]
- unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- // SAFETY: Pointers returned by `allocate` satisfy the guarantees of `System`
- let zeroed = false;
- unsafe { allocate(layout, zeroed) }
- }
+pub unsafe fn alloc(layout: Layout) -> *mut u8 {
+ // SAFETY: Pointers returned by `allocate` satisfy the guarantees of `System`
+ let zeroed = false;
+ unsafe { allocate(layout, zeroed) }
+}
- #[inline]
- unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
- // SAFETY: Pointers returned by `allocate` satisfy the guarantees of `System`
- let zeroed = true;
- unsafe { allocate(layout, zeroed) }
- }
+#[inline]
+pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
+ // SAFETY: Pointers returned by `allocate` satisfy the guarantees of `System`
+ let zeroed = true;
+ unsafe { allocate(layout, zeroed) }
+}
- #[inline]
- unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
- let block = {
- if layout.align() <= MIN_ALIGN {
- ptr
- } else {
- // The location of the start of the block is stored in the padding before `ptr`.
+#[inline]
+pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
+ let block = {
+ if layout.align() <= MIN_ALIGN {
+ ptr
+ } else {
+ // The location of the start of the block is stored in the padding before `ptr`.
- // SAFETY: Because of the contract of `System`, `ptr` is guaranteed to be non-null
- // and have a header readable directly before it.
- unsafe { ptr::read((ptr as *mut Header).sub(1)).0 }
- }
- };
+ // SAFETY: Because of the contract of `System`, `ptr` is guaranteed to be non-null
+ // and have a header readable directly before it.
+ unsafe { ptr::read((ptr as *mut Header).sub(1)).0 }
+ }
+ };
+ // because `ptr` has been successfully allocated with this allocator,
+ // there must be a valid process heap.
+ let heap = get_process_heap();
+
+ // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`,
+ // `block` is a pointer to the start of an allocated block.
+ unsafe { HeapFree(heap, 0, block.cast::()) };
+}
+
+#[inline]
+pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+ if layout.align() <= MIN_ALIGN {
// because `ptr` has been successfully allocated with this allocator,
// there must be a valid process heap.
let heap = get_process_heap();
// SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`,
- // `block` is a pointer to the start of an allocated block.
- unsafe { HeapFree(heap, 0, block.cast::()) };
- }
-
- #[inline]
- unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
- if layout.align() <= MIN_ALIGN {
- // because `ptr` has been successfully allocated with this allocator,
- // there must be a valid process heap.
- let heap = get_process_heap();
-
- // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`,
- // `ptr` is a pointer to the start of an allocated block.
- // The returned pointer points to the start of an allocated block.
- unsafe { HeapReAlloc(heap, 0, ptr.cast::(), new_size).cast::() }
- } else {
- // SAFETY: `realloc_fallback` is implemented using `dealloc` and `alloc`, which will
- // correctly handle `ptr` and return a pointer satisfying the guarantees of `System`
- unsafe { realloc_fallback(self, ptr, layout, new_size) }
- }
+ // `ptr` is a pointer to the start of an allocated block.
+ // The returned pointer points to the start of an allocated block.
+ unsafe { HeapReAlloc(heap, 0, ptr.cast::(), new_size).cast::() }
+ } else {
+ // SAFETY: `realloc_fallback` is implemented using `dealloc` and `alloc`, which will
+ // correctly handle `ptr` and return a pointer satisfying the guarantees of `System`
+ unsafe { realloc_fallback(ptr, layout, new_size) }
}
}
diff --git a/library/std/src/sys/alloc/xous.rs b/library/std/src/sys/alloc/xous.rs
index c7f973b802791..7a4fc5e9a873f 100644
--- a/library/std/src/sys/alloc/xous.rs
+++ b/library/std/src/sys/alloc/xous.rs
@@ -1,7 +1,7 @@
// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
#![allow(static_mut_refs)]
-use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::alloc::Layout;
#[cfg(not(test))]
#[unsafe(export_name = "_ZN16__rust_internals3std3sys4xous5alloc8DLMALLOCE")]
@@ -13,39 +13,36 @@ unsafe extern "Rust" {
static mut DLMALLOC: dlmalloc::Dlmalloc;
}
-#[stable(feature = "alloc_system_type", since = "1.28.0")]
-unsafe impl GlobalAlloc for System {
- #[inline]
- unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- // 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()) }
- }
+#[inline]
+pub unsafe fn alloc(layout: Layout) -> *mut u8 {
+ // 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()) }
+}
- #[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()) }
- }
+#[inline]
+pub unsafe fn alloc_zeroed(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()) }
+}
- #[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()) }
- }
+#[inline]
+pub unsafe fn dealloc(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()) }
+}
- #[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) }
- }
+#[inline]
+pub unsafe fn realloc(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) }
}
mod lock {
diff --git a/library/std/src/sys/alloc/zkvm.rs b/library/std/src/sys/alloc/zkvm.rs
index a600cfa2220dd..7f39d7fed777e 100644
--- a/library/std/src/sys/alloc/zkvm.rs
+++ b/library/std/src/sys/alloc/zkvm.rs
@@ -1,15 +1,18 @@
-use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::alloc::Layout;
use crate::sys::pal::abi;
-#[stable(feature = "alloc_system_type", since = "1.28.0")]
-unsafe impl GlobalAlloc for System {
- #[inline]
- unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- unsafe { abi::sys_alloc_aligned(layout.size(), layout.align()) }
- }
+#[inline]
+pub unsafe fn alloc(layout: Layout) -> *mut u8 {
+ unsafe { abi::sys_alloc_aligned(layout.size(), layout.align()) }
+}
+
+#[inline]
+pub unsafe fn dealloc(_ptr: *mut u8, _layout: Layout) {
+ // this allocator never deallocates memory
+}
- #[inline]
- unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
- // this allocator never deallocates memory
- }
+#[inline]
+pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+ // SAFETY: this is just a `pub` wrapper.
+ unsafe { super::realloc_fallback(ptr, layout, new_size) }
}
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index fe0c103952414..58c8dc43e12ae 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -1,11 +1,11 @@
#![allow(unsafe_op_in_unsafe_fn)]
-mod alloc;
mod configure_builtins;
mod helpers;
mod pal;
mod personality;
+pub mod alloc;
pub mod args;
pub mod backtrace;
pub mod cmath;
diff --git a/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr b/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr
index 1e9d859b5cf81..1853ecbf43c70 100644
--- a/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr
+++ b/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr
@@ -1,13 +1,13 @@
error: Undefined Behavior: deallocating ALLOC, which is Rust heap memory, using PLATFORM heap deallocation operation
--> RUSTLIB/std/src/sys/alloc/PLATFORM.rs:LL:CC
|
-LL | FREE();
+LL | FREE();
| ^ Undefined Behavior occurred here
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: stack backtrace:
- 0: std::sys::alloc::PLATFORM::::dealloc
+ 0: std::sys::alloc::PLATFORM::dealloc
at RUSTLIB/std/src/sys/alloc/PLATFORM.rs:LL:CC
1: ::deallocate
at RUSTLIB/std/src/alloc.rs:LL:CC
diff --git a/tests/ui/allocator/not-an-allocator.u.stderr b/tests/ui/allocator/not-an-allocator.u.stderr
index f7400d16b1fd1..9be5dd495db02 100644
--- a/tests/ui/allocator/not-an-allocator.u.stderr
+++ b/tests/ui/allocator/not-an-allocator.u.stderr
@@ -4,10 +4,11 @@ error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
LL | #[global_allocator]
| ------------------- in this attribute macro expansion
LL | static A: usize = 0;
- | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
+ | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize`
|
-help: the trait `GlobalAlloc` is implemented for `System`
- --> $SRC_DIR/std/src/sys/alloc/unix.rs:LL:COL
+help: the trait `GlobalAllocator` is implemented for `System`
+ --> $SRC_DIR/std/src/alloc.rs:LL:COL
+ = note: required for `usize` to implement `GlobalAlloc`
error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
--> $DIR/not-an-allocator.rs:5:11
@@ -15,10 +16,11 @@ error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
LL | #[global_allocator]
| ------------------- in this attribute macro expansion
LL | static A: usize = 0;
- | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
+ | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize`
|
-help: the trait `GlobalAlloc` is implemented for `System`
- --> $SRC_DIR/std/src/sys/alloc/unix.rs:LL:COL
+help: the trait `GlobalAllocator` is implemented for `System`
+ --> $SRC_DIR/std/src/alloc.rs:LL:COL
+ = note: required for `usize` to implement `GlobalAlloc`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
@@ -27,10 +29,11 @@ error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
LL | #[global_allocator]
| ------------------- in this attribute macro expansion
LL | static A: usize = 0;
- | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
+ | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize`
|
-help: the trait `GlobalAlloc` is implemented for `System`
- --> $SRC_DIR/std/src/sys/alloc/unix.rs:LL:COL
+help: the trait `GlobalAllocator` is implemented for `System`
+ --> $SRC_DIR/std/src/alloc.rs:LL:COL
+ = note: required for `usize` to implement `GlobalAlloc`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
@@ -39,10 +42,11 @@ error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
LL | #[global_allocator]
| ------------------- in this attribute macro expansion
LL | static A: usize = 0;
- | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
+ | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize`
|
-help: the trait `GlobalAlloc` is implemented for `System`
- --> $SRC_DIR/std/src/sys/alloc/unix.rs:LL:COL
+help: the trait `GlobalAllocator` is implemented for `System`
+ --> $SRC_DIR/std/src/alloc.rs:LL:COL
+ = note: required for `usize` to implement `GlobalAlloc`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 4 previous errors