2017-06-03 16:54:08 -05:00
|
|
|
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2018-05-31 11:23:42 -05:00
|
|
|
//! Memory allocation APIs
|
2018-05-31 13:22:59 -05:00
|
|
|
//!
|
|
|
|
//! In a given program, the standard library has one “global” memory allocator
|
|
|
|
//! that is used for example by `Box<T>` and `Vec<T>`.
|
|
|
|
//!
|
|
|
|
//! Currently the default global allocator is unspecified.
|
|
|
|
//! The compiler may link to a version of [jemalloc] on some platforms,
|
|
|
|
//! but this is not guaranteed.
|
|
|
|
//! Libraries, however, like `cdylib`s and `staticlib`s are guaranteed
|
|
|
|
//! to use the [`System`] by default.
|
|
|
|
//!
|
|
|
|
//! [jemalloc]: https://github.com/jemalloc/jemalloc
|
|
|
|
//! [`System`]: struct.System.html
|
|
|
|
//!
|
|
|
|
//! # The `#[global_allocator]` attribute
|
|
|
|
//!
|
|
|
|
//! This attribute allows configuring the choice of global allocator.
|
|
|
|
//! You can use this to implement a completely custom global allocator
|
|
|
|
//! to route all default allocation requests to a custom object.
|
|
|
|
//!
|
|
|
|
//! ```rust
|
|
|
|
//! use std::alloc::{GlobalAlloc, System, Layout};
|
|
|
|
//!
|
|
|
|
//! struct MyAllocator;
|
|
|
|
//!
|
|
|
|
//! unsafe impl GlobalAlloc for MyAllocator {
|
|
|
|
//! unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
|
|
|
//! System.alloc(layout)
|
|
|
|
//! }
|
|
|
|
//!
|
|
|
|
//! unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
|
|
|
//! System.dealloc(ptr, layout)
|
|
|
|
//! }
|
|
|
|
//! }
|
|
|
|
//!
|
|
|
|
//! #[global_allocator]
|
|
|
|
//! static GLOBAL: MyAllocator = MyAllocator;
|
|
|
|
//!
|
|
|
|
//! fn main() {
|
|
|
|
//! // This `Vec` will allocate memory through `GLOBAL` above
|
|
|
|
//! let mut v = Vec::new();
|
|
|
|
//! v.push(1);
|
|
|
|
//! }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! The attribute is used on a `static` item whose type implements the
|
|
|
|
//! [`GlobalAlloc`] trait. This type can be provided by an external library:
|
|
|
|
//!
|
|
|
|
//! [`GlobalAlloc`]: ../../core/alloc/trait.GlobalAlloc.html
|
|
|
|
//!
|
|
|
|
//! ```rust,ignore (demonstrates crates.io usage)
|
|
|
|
//! extern crate jemallocator;
|
|
|
|
//!
|
2018-06-28 21:12:02 -05:00
|
|
|
//! use jemallocator::Jemalloc;
|
2018-05-31 13:22:59 -05:00
|
|
|
//!
|
|
|
|
//! #[global_allocator]
|
|
|
|
//! static GLOBAL: Jemalloc = Jemalloc;
|
|
|
|
//!
|
|
|
|
//! fn main() {}
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! The `#[global_allocator]` can only be used once in a crate
|
|
|
|
//! or its recursive dependencies.
|
2017-06-03 16:54:08 -05:00
|
|
|
|
2018-05-31 11:36:51 -05:00
|
|
|
#![stable(feature = "alloc_module", since = "1.28.0")]
|
2017-06-03 16:54:08 -05:00
|
|
|
|
2018-05-15 19:16:37 -05:00
|
|
|
use core::sync::atomic::{AtomicPtr, Ordering};
|
|
|
|
use core::{mem, ptr};
|
2018-05-31 18:50:07 -05:00
|
|
|
use sys_common::util::dumb_print;
|
2018-05-15 19:16:37 -05:00
|
|
|
|
2018-05-31 11:36:51 -05:00
|
|
|
#[stable(feature = "alloc_module", since = "1.28.0")]
|
|
|
|
#[doc(inline)]
|
|
|
|
pub use alloc_crate::alloc::*;
|
|
|
|
|
2018-05-31 12:16:24 -05:00
|
|
|
#[stable(feature = "alloc_system_type", since = "1.28.0")]
|
2018-05-31 11:36:51 -05:00
|
|
|
#[doc(inline)]
|
|
|
|
pub use alloc_system::System;
|
|
|
|
|
2018-05-15 19:16:37 -05:00
|
|
|
static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
|
|
|
|
|
2018-06-13 17:32:30 -05:00
|
|
|
/// Registers a custom allocation error hook, replacing any that was previously registered.
|
2018-05-15 19:16:37 -05:00
|
|
|
///
|
2018-06-13 17:32:30 -05:00
|
|
|
/// The allocation error hook is invoked when an infallible memory allocation fails, before
|
2018-05-31 18:50:07 -05:00
|
|
|
/// the runtime aborts. The default hook prints a message to standard error,
|
2018-06-13 17:32:30 -05:00
|
|
|
/// but this behavior can be customized with the [`set_alloc_error_hook`] and
|
|
|
|
/// [`take_alloc_error_hook`] functions.
|
2018-05-15 19:16:37 -05:00
|
|
|
///
|
|
|
|
/// The hook is provided with a `Layout` struct which contains information
|
|
|
|
/// about the allocation that failed.
|
|
|
|
///
|
2018-06-13 17:32:30 -05:00
|
|
|
/// The allocation error hook is a global resource.
|
|
|
|
#[unstable(feature = "alloc_error_hook", issue = "51245")]
|
|
|
|
pub fn set_alloc_error_hook(hook: fn(Layout)) {
|
2018-05-15 19:16:37 -05:00
|
|
|
HOOK.store(hook as *mut (), Ordering::SeqCst);
|
|
|
|
}
|
|
|
|
|
2018-06-13 17:32:30 -05:00
|
|
|
/// Unregisters the current allocation error hook, returning it.
|
2018-05-15 19:16:37 -05:00
|
|
|
///
|
2018-06-13 17:32:30 -05:00
|
|
|
/// *See also the function [`set_alloc_error_hook`].*
|
2018-05-15 19:16:37 -05:00
|
|
|
///
|
|
|
|
/// If no custom hook is registered, the default hook will be returned.
|
2018-06-13 17:32:30 -05:00
|
|
|
#[unstable(feature = "alloc_error_hook", issue = "51245")]
|
|
|
|
pub fn take_alloc_error_hook() -> fn(Layout) {
|
2018-05-15 19:16:37 -05:00
|
|
|
let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst);
|
|
|
|
if hook.is_null() {
|
2018-06-13 17:32:30 -05:00
|
|
|
default_alloc_error_hook
|
2018-05-15 19:16:37 -05:00
|
|
|
} else {
|
|
|
|
unsafe { mem::transmute(hook) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-13 17:32:30 -05:00
|
|
|
fn default_alloc_error_hook(layout: Layout) {
|
2018-05-31 18:50:07 -05:00
|
|
|
dumb_print(format_args!("memory allocation of {} bytes failed", layout.size()));
|
2018-05-15 19:16:37 -05:00
|
|
|
}
|
|
|
|
|
2018-04-20 23:05:13 -05:00
|
|
|
#[cfg(not(test))]
|
|
|
|
#[doc(hidden)]
|
|
|
|
#[lang = "oom"]
|
2018-05-31 11:38:39 -05:00
|
|
|
#[unstable(feature = "alloc_internals", issue = "0")]
|
2018-05-15 19:16:37 -05:00
|
|
|
pub extern fn rust_oom(layout: Layout) -> ! {
|
|
|
|
let hook = HOOK.load(Ordering::SeqCst);
|
2018-05-31 18:50:07 -05:00
|
|
|
let hook: fn(Layout) = if hook.is_null() {
|
2018-06-13 17:32:30 -05:00
|
|
|
default_alloc_error_hook
|
2018-05-15 19:16:37 -05:00
|
|
|
} else {
|
|
|
|
unsafe { mem::transmute(hook) }
|
|
|
|
};
|
2018-05-31 18:50:07 -05:00
|
|
|
hook(layout);
|
|
|
|
unsafe { ::sys::abort_internal(); }
|
2018-04-20 23:05:13 -05:00
|
|
|
}
|
|
|
|
|
2017-07-17 11:32:08 -05:00
|
|
|
#[cfg(not(test))]
|
2017-06-03 16:54:08 -05:00
|
|
|
#[doc(hidden)]
|
2017-11-01 15:16:36 -05:00
|
|
|
#[allow(unused_attributes)]
|
2018-05-31 11:38:39 -05:00
|
|
|
#[unstable(feature = "alloc_internals", issue = "0")]
|
2017-06-03 16:54:08 -05:00
|
|
|
pub mod __default_lib_allocator {
|
2018-05-31 01:57:43 -05:00
|
|
|
use super::{System, Layout, GlobalAlloc};
|
2017-06-03 16:54:08 -05:00
|
|
|
// for symbol names src/librustc/middle/allocator.rs
|
|
|
|
// for signatures src/librustc_allocator/lib.rs
|
|
|
|
|
|
|
|
// linkage directives are provided as part of the current compiler allocator
|
|
|
|
// ABI
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-11-01 15:16:36 -05:00
|
|
|
#[rustc_std_internal_symbol]
|
2018-04-03 10:12:57 -05:00
|
|
|
pub unsafe extern fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
|
2017-06-03 16:54:08 -05:00
|
|
|
let layout = Layout::from_size_align_unchecked(size, align);
|
2018-05-31 01:57:43 -05:00
|
|
|
System.alloc(layout)
|
2017-06-03 16:54:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-11-01 15:16:36 -05:00
|
|
|
#[rustc_std_internal_symbol]
|
2017-06-03 16:54:08 -05:00
|
|
|
pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
|
|
|
|
size: usize,
|
|
|
|
align: usize) {
|
2018-05-31 01:57:43 -05:00
|
|
|
System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
|
2017-06-03 16:54:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-11-01 15:16:36 -05:00
|
|
|
#[rustc_std_internal_symbol]
|
2017-06-03 16:54:08 -05:00
|
|
|
pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
|
|
|
|
old_size: usize,
|
2018-04-03 10:12:57 -05:00
|
|
|
align: usize,
|
|
|
|
new_size: usize) -> *mut u8 {
|
|
|
|
let old_layout = Layout::from_size_align_unchecked(old_size, align);
|
2018-05-31 01:57:43 -05:00
|
|
|
System.realloc(ptr, old_layout, new_size)
|
2017-06-03 16:54:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-11-01 15:16:36 -05:00
|
|
|
#[rustc_std_internal_symbol]
|
2018-04-03 10:12:57 -05:00
|
|
|
pub unsafe extern fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
|
2017-06-03 16:54:08 -05:00
|
|
|
let layout = Layout::from_size_align_unchecked(size, align);
|
2018-05-31 01:57:43 -05:00
|
|
|
System.alloc_zeroed(layout)
|
2017-06-03 16:54:08 -05:00
|
|
|
}
|
|
|
|
}
|