]> git.proxmox.com Git - rustc.git/blob - src/libcore/alloc/global.rs
New upstream version 1.44.1+dfsg1
[rustc.git] / src / libcore / alloc / global.rs
1 use crate::alloc::Layout;
2 use crate::cmp;
3 use crate::ptr;
4
5 /// A memory allocator that can be registered as the standard library’s default
6 /// through the `#[global_allocator]` attribute.
7 ///
8 /// Some of the methods require that a memory block be *currently
9 /// allocated* via an allocator. This means that:
10 ///
11 /// * the starting address for that memory block was previously
12 /// returned by a previous call to an allocation method
13 /// such as `alloc`, and
14 ///
15 /// * the memory block has not been subsequently deallocated, where
16 /// blocks are deallocated either by being passed to a deallocation
17 /// method such as `dealloc` or by being
18 /// passed to a reallocation method that returns a non-null pointer.
19 ///
20 ///
21 /// # Example
22 ///
23 /// ```no_run
24 /// use std::alloc::{GlobalAlloc, Layout, alloc};
25 /// use std::ptr::null_mut;
26 ///
27 /// struct MyAllocator;
28 ///
29 /// unsafe impl GlobalAlloc for MyAllocator {
30 /// unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { null_mut() }
31 /// unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
32 /// }
33 ///
34 /// #[global_allocator]
35 /// static A: MyAllocator = MyAllocator;
36 ///
37 /// fn main() {
38 /// unsafe {
39 /// assert!(alloc(Layout::new::<u32>()).is_null())
40 /// }
41 /// }
42 /// ```
43 ///
44 /// # Safety
45 ///
46 /// The `GlobalAlloc` trait is an `unsafe` trait for a number of reasons, and
47 /// implementors must ensure that they adhere to these contracts:
48 ///
49 /// * It's undefined behavior if global allocators unwind. This restriction may
50 /// be lifted in the future, but currently a panic from any of these
51 /// functions may lead to memory unsafety.
52 ///
53 /// * `Layout` queries and calculations in general must be correct. Callers of
54 /// this trait are allowed to rely on the contracts defined on each method,
55 /// and implementors must ensure such contracts remain true.
56 #[stable(feature = "global_alloc", since = "1.28.0")]
57 pub unsafe trait GlobalAlloc {
58 /// Allocate memory as described by the given `layout`.
59 ///
60 /// Returns a pointer to newly-allocated memory,
61 /// or null to indicate allocation failure.
62 ///
63 /// # Safety
64 ///
65 /// This function is unsafe because undefined behavior can result
66 /// if the caller does not ensure that `layout` has non-zero size.
67 ///
68 /// (Extension subtraits might provide more specific bounds on
69 /// behavior, e.g., guarantee a sentinel address or a null pointer
70 /// in response to a zero-size allocation request.)
71 ///
72 /// The allocated block of memory may or may not be initialized.
73 ///
74 /// # Errors
75 ///
76 /// Returning a null pointer indicates that either memory is exhausted
77 /// or `layout` does not meet this allocator's size or alignment constraints.
78 ///
79 /// Implementations are encouraged to return null on memory
80 /// exhaustion rather than aborting, but this is not
81 /// a strict requirement. (Specifically: it is *legal* to
82 /// implement this trait atop an underlying native allocation
83 /// library that aborts on memory exhaustion.)
84 ///
85 /// Clients wishing to abort computation in response to an
86 /// allocation error are encouraged to call the [`handle_alloc_error`] function,
87 /// rather than directly invoking `panic!` or similar.
88 ///
89 /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
90 #[stable(feature = "global_alloc", since = "1.28.0")]
91 unsafe fn alloc(&self, layout: Layout) -> *mut u8;
92
93 /// Deallocate the block of memory at the given `ptr` pointer with the given `layout`.
94 ///
95 /// # Safety
96 ///
97 /// This function is unsafe because undefined behavior can result
98 /// if the caller does not ensure all of the following:
99 ///
100 /// * `ptr` must denote a block of memory currently allocated via
101 /// this allocator,
102 ///
103 /// * `layout` must be the same layout that was used
104 /// to allocate that block of memory,
105 #[stable(feature = "global_alloc", since = "1.28.0")]
106 unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout);
107
108 /// Behaves like `alloc`, but also ensures that the contents
109 /// are set to zero before being returned.
110 ///
111 /// # Safety
112 ///
113 /// This function is unsafe for the same reasons that `alloc` is.
114 /// However the allocated block of memory is guaranteed to be initialized.
115 ///
116 /// # Errors
117 ///
118 /// Returning a null pointer indicates that either memory is exhausted
119 /// or `layout` does not meet allocator's size or alignment constraints,
120 /// just as in `alloc`.
121 ///
122 /// Clients wishing to abort computation in response to an
123 /// allocation error are encouraged to call the [`handle_alloc_error`] function,
124 /// rather than directly invoking `panic!` or similar.
125 ///
126 /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
127 #[stable(feature = "global_alloc", since = "1.28.0")]
128 unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
129 let size = layout.size();
130 let ptr = self.alloc(layout);
131 if !ptr.is_null() {
132 ptr::write_bytes(ptr, 0, size);
133 }
134 ptr
135 }
136
137 /// Shrink or grow a block of memory to the given `new_size`.
138 /// The block is described by the given `ptr` pointer and `layout`.
139 ///
140 /// If this returns a non-null pointer, then ownership of the memory block
141 /// referenced by `ptr` has been transferred to this allocator.
142 /// The memory may or may not have been deallocated,
143 /// and should be considered unusable (unless of course it was
144 /// transferred back to the caller again via the return value of
145 /// this method). The new memory block is allocated with `layout`, but
146 /// with the `size` updated to `new_size`.
147 ///
148 /// If this method returns null, then ownership of the memory
149 /// block has not been transferred to this allocator, and the
150 /// contents of the memory block are unaltered.
151 ///
152 /// # Safety
153 ///
154 /// This function is unsafe because undefined behavior can result
155 /// if the caller does not ensure all of the following:
156 ///
157 /// * `ptr` must be currently allocated via this allocator,
158 ///
159 /// * `layout` must be the same layout that was used
160 /// to allocate that block of memory,
161 ///
162 /// * `new_size` must be greater than zero.
163 ///
164 /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
165 /// must not overflow (i.e., the rounded value must be less than `usize::MAX`).
166 ///
167 /// (Extension subtraits might provide more specific bounds on
168 /// behavior, e.g., guarantee a sentinel address or a null pointer
169 /// in response to a zero-size allocation request.)
170 ///
171 /// # Errors
172 ///
173 /// Returns null if the new layout does not meet the size
174 /// and alignment constraints of the allocator, or if reallocation
175 /// otherwise fails.
176 ///
177 /// Implementations are encouraged to return null on memory
178 /// exhaustion rather than panicking or aborting, but this is not
179 /// a strict requirement. (Specifically: it is *legal* to
180 /// implement this trait atop an underlying native allocation
181 /// library that aborts on memory exhaustion.)
182 ///
183 /// Clients wishing to abort computation in response to a
184 /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
185 /// rather than directly invoking `panic!` or similar.
186 ///
187 /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
188 #[stable(feature = "global_alloc", since = "1.28.0")]
189 unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
190 let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
191 let new_ptr = self.alloc(new_layout);
192 if !new_ptr.is_null() {
193 ptr::copy_nonoverlapping(ptr, new_ptr, cmp::min(layout.size(), new_size));
194 self.dealloc(ptr, layout);
195 }
196 new_ptr
197 }
198 }