]> git.lizzy.rs Git - rust.git/blob - src/libstd/alloc.rs
std: Delete the `alloc_system` crate
[rust.git] / src / libstd / alloc.rs
1 // Copyright 2017 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.
4 //
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.
10
11 //! Memory allocation APIs
12 //!
13 //! In a given program, the standard library has one “global” memory allocator
14 //! that is used for example by `Box<T>` and `Vec<T>`.
15 //!
16 //! Currently the default global allocator is unspecified. Libraries, however,
17 //! like `cdylib`s and `staticlib`s are guaranteed to use the [`System`] by
18 //! default.
19 //!
20 //! [`System`]: struct.System.html
21 //!
22 //! # The `#[global_allocator]` attribute
23 //!
24 //! This attribute allows configuring the choice of global allocator.
25 //! You can use this to implement a completely custom global allocator
26 //! to route all default allocation requests to a custom object.
27 //!
28 //! ```rust
29 //! use std::alloc::{GlobalAlloc, System, Layout};
30 //!
31 //! struct MyAllocator;
32 //!
33 //! unsafe impl GlobalAlloc for MyAllocator {
34 //!     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
35 //!         System.alloc(layout)
36 //!     }
37 //!
38 //!     unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
39 //!         System.dealloc(ptr, layout)
40 //!     }
41 //! }
42 //!
43 //! #[global_allocator]
44 //! static GLOBAL: MyAllocator = MyAllocator;
45 //!
46 //! fn main() {
47 //!     // This `Vec` will allocate memory through `GLOBAL` above
48 //!     let mut v = Vec::new();
49 //!     v.push(1);
50 //! }
51 //! ```
52 //!
53 //! The attribute is used on a `static` item whose type implements the
54 //! [`GlobalAlloc`] trait. This type can be provided by an external library:
55 //!
56 //! [`GlobalAlloc`]: ../../core/alloc/trait.GlobalAlloc.html
57 //!
58 //! ```rust,ignore (demonstrates crates.io usage)
59 //! extern crate jemallocator;
60 //!
61 //! use jemallocator::Jemalloc;
62 //!
63 //! #[global_allocator]
64 //! static GLOBAL: Jemalloc = Jemalloc;
65 //!
66 //! fn main() {}
67 //! ```
68 //!
69 //! The `#[global_allocator]` can only be used once in a crate
70 //! or its recursive dependencies.
71
72 #![stable(feature = "alloc_module", since = "1.28.0")]
73
74 use core::sync::atomic::{AtomicPtr, Ordering};
75 use core::{mem, ptr};
76 use core::ptr::NonNull;
77 use sys_common::util::dumb_print;
78
79 #[stable(feature = "alloc_module", since = "1.28.0")]
80 #[doc(inline)]
81 pub use alloc_crate::alloc::*;
82
83 /// The default memory allocator provided by the operating system.
84 ///
85 /// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows,
86 /// plus related functions.
87 ///
88 /// This type implements the `GlobalAlloc` trait and Rust programs by deafult
89 /// work as if they had this definition:
90 ///
91 /// ```rust
92 /// use std::alloc::System;
93 ///
94 /// #[global_allocator]
95 /// static A: System = System;
96 ///
97 /// fn main() {
98 ///     let a = Box::new(4); // Allocates from the system allocator.
99 ///     println!("{}", a);
100 /// }
101 /// ```
102 ///
103 /// You can also define your own wrapper around `System` if you'd like, such as
104 /// keeping track of the number of all bytes allocated:
105 ///
106 /// ```rust
107 /// use std::alloc::{System, GlobalAlloc, Layout};
108 /// use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering::SeqCst};
109 ///
110 /// struct Counter;
111 ///
112 /// static ALLOCATED: AtomicUsize = ATOMIC_USIZE_INIT;
113 ///
114 /// unsafe impl GlobalAlloc for Counter {
115 ///     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
116 ///         let ret = System.alloc(layout);
117 ///         if !ret.is_null() {
118 ///             ALLOCATED.fetch_add(layout.size(), SeqCst);
119 ///         }
120 ///         return ret
121 ///     }
122 ///
123 ///     unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
124 ///         System.dealloc(ptr, layout);
125 ///         ALLOCATED.fetch_sub(layout.size(), SeqCst);
126 ///     }
127 /// }
128 ///
129 /// #[global_allocator]
130 /// static A: Counter = Counter;
131 ///
132 /// fn main() {
133 ///     println!("allocated bytes before main: {}", ALLOCATED.load(SeqCst));
134 /// }
135 /// ```
136 ///
137 /// It can also be used directly to allocate memory independently of whatever
138 /// global allocator has been selected for a Rust program. For example if a Rust
139 /// program opts in to using jemalloc as the global allocator, `System` will
140 /// still allocate memory using `malloc` and `HeapAlloc`.
141 #[stable(feature = "alloc_system_type", since = "1.28.0")]
142 #[derive(Debug, Copy, Clone)]
143 pub struct System;
144
145 #[unstable(feature = "allocator_api", issue = "32838")]
146 unsafe impl Alloc for System {
147     #[inline]
148     unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
149         NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr)
150     }
151
152     #[inline]
153     unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
154         NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr)
155     }
156
157     #[inline]
158     unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
159         GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
160     }
161
162     #[inline]
163     unsafe fn realloc(&mut self,
164                       ptr: NonNull<u8>,
165                       layout: Layout,
166                       new_size: usize) -> Result<NonNull<u8>, AllocErr> {
167         NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
168     }
169 }
170
171 static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
172
173 /// Registers a custom allocation error hook, replacing any that was previously registered.
174 ///
175 /// The allocation error hook is invoked when an infallible memory allocation fails, before
176 /// the runtime aborts. The default hook prints a message to standard error,
177 /// but this behavior can be customized with the [`set_alloc_error_hook`] and
178 /// [`take_alloc_error_hook`] functions.
179 ///
180 /// The hook is provided with a `Layout` struct which contains information
181 /// about the allocation that failed.
182 ///
183 /// The allocation error hook is a global resource.
184 #[unstable(feature = "alloc_error_hook", issue = "51245")]
185 pub fn set_alloc_error_hook(hook: fn(Layout)) {
186     HOOK.store(hook as *mut (), Ordering::SeqCst);
187 }
188
189 /// Unregisters the current allocation error hook, returning it.
190 ///
191 /// *See also the function [`set_alloc_error_hook`].*
192 ///
193 /// If no custom hook is registered, the default hook will be returned.
194 #[unstable(feature = "alloc_error_hook", issue = "51245")]
195 pub fn take_alloc_error_hook() -> fn(Layout) {
196     let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst);
197     if hook.is_null() {
198         default_alloc_error_hook
199     } else {
200         unsafe { mem::transmute(hook) }
201     }
202 }
203
204 fn default_alloc_error_hook(layout: Layout) {
205     dumb_print(format_args!("memory allocation of {} bytes failed", layout.size()));
206 }
207
208 #[cfg(not(test))]
209 #[doc(hidden)]
210 #[alloc_error_handler]
211 #[unstable(feature = "alloc_internals", issue = "0")]
212 pub fn rust_oom(layout: Layout) -> ! {
213     let hook = HOOK.load(Ordering::SeqCst);
214     let hook: fn(Layout) = if hook.is_null() {
215         default_alloc_error_hook
216     } else {
217         unsafe { mem::transmute(hook) }
218     };
219     hook(layout);
220     unsafe { ::sys::abort_internal(); }
221 }
222
223 #[cfg(not(test))]
224 #[doc(hidden)]
225 #[allow(unused_attributes)]
226 #[unstable(feature = "alloc_internals", issue = "0")]
227 pub mod __default_lib_allocator {
228     use super::{System, Layout, GlobalAlloc};
229     // for symbol names src/librustc/middle/allocator.rs
230     // for signatures src/librustc_allocator/lib.rs
231
232     // linkage directives are provided as part of the current compiler allocator
233     // ABI
234
235     #[rustc_std_internal_symbol]
236     pub unsafe extern fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
237         let layout = Layout::from_size_align_unchecked(size, align);
238         System.alloc(layout)
239     }
240
241     #[rustc_std_internal_symbol]
242     pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
243                                        size: usize,
244                                        align: usize) {
245         System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
246     }
247
248     #[rustc_std_internal_symbol]
249     pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
250                                        old_size: usize,
251                                        align: usize,
252                                        new_size: usize) -> *mut u8 {
253         let old_layout = Layout::from_size_align_unchecked(old_size, align);
254         System.realloc(ptr, old_layout, new_size)
255     }
256
257     #[rustc_std_internal_symbol]
258     pub unsafe extern fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
259         let layout = Layout::from_size_align_unchecked(size, align);
260         System.alloc_zeroed(layout)
261     }
262 }