2017-06-03 14:54:08 -07: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 18:23:42 +02:00
|
|
|
//! Memory allocation APIs
|
2017-06-03 14:54:08 -07:00
|
|
|
|
|
|
|
#![unstable(issue = "32838", feature = "allocator_api")]
|
|
|
|
|
2018-05-15 09:56:46 +09:00
|
|
|
#[doc(inline)] pub use alloc_crate::alloc::{Global, Layout, oom};
|
2018-05-31 16:10:01 +09:00
|
|
|
#[doc(inline)] pub use alloc_crate::alloc::{alloc, alloc_zeroed, dealloc, realloc};
|
2018-04-03 21:05:10 +02:00
|
|
|
#[doc(inline)] pub use alloc_system::System;
|
|
|
|
#[doc(inline)] pub use core::alloc::*;
|
2017-06-03 14:54:08 -07:00
|
|
|
|
2018-05-16 09:16:37 +09:00
|
|
|
use core::sync::atomic::{AtomicPtr, Ordering};
|
|
|
|
use core::{mem, ptr};
|
2018-06-01 08:50:07 +09:00
|
|
|
use sys_common::util::dumb_print;
|
2018-05-16 09:16:37 +09:00
|
|
|
|
|
|
|
static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
|
|
|
|
|
|
|
|
/// Registers a custom OOM hook, replacing any that was previously registered.
|
|
|
|
///
|
2018-06-01 08:50:07 +09:00
|
|
|
/// The OOM hook is invoked when an infallible memory allocation fails, before
|
|
|
|
/// the runtime aborts. The default hook prints a message to standard error,
|
|
|
|
/// but this behavior can be customized with the [`set_oom_hook`] and
|
|
|
|
/// [`take_oom_hook`] functions.
|
2018-05-16 09:16:37 +09:00
|
|
|
///
|
|
|
|
/// The hook is provided with a `Layout` struct which contains information
|
|
|
|
/// about the allocation that failed.
|
|
|
|
///
|
|
|
|
/// The OOM hook is a global resource.
|
2018-06-01 08:50:07 +09:00
|
|
|
pub fn set_oom_hook(hook: fn(Layout)) {
|
2018-05-16 09:16:37 +09:00
|
|
|
HOOK.store(hook as *mut (), Ordering::SeqCst);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Unregisters the current OOM hook, returning it.
|
|
|
|
///
|
|
|
|
/// *See also the function [`set_oom_hook`].*
|
|
|
|
///
|
|
|
|
/// If no custom hook is registered, the default hook will be returned.
|
2018-06-01 08:50:07 +09:00
|
|
|
pub fn take_oom_hook() -> fn(Layout) {
|
2018-05-16 09:16:37 +09:00
|
|
|
let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst);
|
|
|
|
if hook.is_null() {
|
|
|
|
default_oom_hook
|
|
|
|
} else {
|
|
|
|
unsafe { mem::transmute(hook) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-01 08:50:07 +09:00
|
|
|
fn default_oom_hook(layout: Layout) {
|
|
|
|
dumb_print(format_args!("memory allocation of {} bytes failed", layout.size()));
|
2018-05-16 09:16:37 +09:00
|
|
|
}
|
|
|
|
|
2018-04-20 21:05:13 -07:00
|
|
|
#[cfg(not(test))]
|
|
|
|
#[doc(hidden)]
|
|
|
|
#[lang = "oom"]
|
2018-05-16 09:16:37 +09:00
|
|
|
pub extern fn rust_oom(layout: Layout) -> ! {
|
|
|
|
let hook = HOOK.load(Ordering::SeqCst);
|
2018-06-01 08:50:07 +09:00
|
|
|
let hook: fn(Layout) = if hook.is_null() {
|
2018-05-16 09:16:37 +09:00
|
|
|
default_oom_hook
|
|
|
|
} else {
|
|
|
|
unsafe { mem::transmute(hook) }
|
|
|
|
};
|
2018-06-01 08:50:07 +09:00
|
|
|
hook(layout);
|
|
|
|
unsafe { ::sys::abort_internal(); }
|
2018-04-20 21:05:13 -07:00
|
|
|
}
|
|
|
|
|
2017-07-17 09:32:08 -07:00
|
|
|
#[cfg(not(test))]
|
2017-06-03 14:54:08 -07:00
|
|
|
#[doc(hidden)]
|
2017-11-01 13:16:36 -07:00
|
|
|
#[allow(unused_attributes)]
|
2017-06-03 14:54:08 -07:00
|
|
|
pub mod __default_lib_allocator {
|
2018-05-31 15:57:43 +09:00
|
|
|
use super::{System, Layout, GlobalAlloc};
|
2017-06-03 14:54:08 -07: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 13:16:36 -07:00
|
|
|
#[rustc_std_internal_symbol]
|
2018-04-03 17:12:57 +02:00
|
|
|
pub unsafe extern fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
|
2017-06-03 14:54:08 -07:00
|
|
|
let layout = Layout::from_size_align_unchecked(size, align);
|
2018-05-31 15:57:43 +09:00
|
|
|
System.alloc(layout)
|
2017-06-03 14:54:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-11-01 13:16:36 -07:00
|
|
|
#[rustc_std_internal_symbol]
|
2017-06-03 14:54:08 -07:00
|
|
|
pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
|
|
|
|
size: usize,
|
|
|
|
align: usize) {
|
2018-05-31 15:57:43 +09:00
|
|
|
System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
|
2017-06-03 14:54:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-11-01 13:16:36 -07:00
|
|
|
#[rustc_std_internal_symbol]
|
2017-06-03 14:54:08 -07:00
|
|
|
pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
|
|
|
|
old_size: usize,
|
2018-04-03 17:12:57 +02:00
|
|
|
align: usize,
|
|
|
|
new_size: usize) -> *mut u8 {
|
|
|
|
let old_layout = Layout::from_size_align_unchecked(old_size, align);
|
2018-05-31 15:57:43 +09:00
|
|
|
System.realloc(ptr, old_layout, new_size)
|
2017-06-03 14:54:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-11-01 13:16:36 -07:00
|
|
|
#[rustc_std_internal_symbol]
|
2018-04-03 17:12:57 +02:00
|
|
|
pub unsafe extern fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
|
2017-06-03 14:54:08 -07:00
|
|
|
let layout = Layout::from_size_align_unchecked(size, align);
|
2018-05-31 15:57:43 +09:00
|
|
|
System.alloc_zeroed(layout)
|
2017-06-03 14:54:08 -07:00
|
|
|
}
|
|
|
|
}
|