]> git.proxmox.com Git - rustc.git/blob - vendor/dlmalloc/src/lib.rs
New upstream version 1.34.2+dfsg1
[rustc.git] / vendor / dlmalloc / src / lib.rs
1 //! A Rust port of the `dlmalloc` allocator.
2 //!
3 //! The `dlmalloc` allocator is described at
4 //! http://g.oswego.edu/dl/html/malloc.html and this Rust crate is a straight
5 //! port of the C code for the allocator into Rust. The implementation is
6 //! wrapped up in a `Dlmalloc` type and has support for Linux, OSX, and Wasm
7 //! currently.
8 //!
9 //! The primary purpose of this crate is that it serves as the default memory
10 //! allocator for the `wasm32-unknown-unknown` target in the standard library.
11 //! Support for other platforms is largely untested and unused, but is used when
12 //! testing this crate.
13
14 #![cfg_attr(feature = "allocator-api", feature(allocator_api))]
15 #![cfg_attr(target_env = "sgx", feature(asm))]
16 #![cfg_attr(not(feature = "allocator-api"), allow(dead_code))]
17 #![no_std]
18 #![deny(missing_docs)]
19
20 #[cfg(feature = "allocator-api")]
21 use core::alloc::{Alloc, Layout, AllocErr};
22 use core::cmp;
23 use core::ptr;
24
25 #[cfg(feature = "global")]
26 pub use self::global::GlobalDlmalloc;
27
28 #[cfg(feature = "global")]
29 mod global;
30 mod dlmalloc;
31
32 /// An allocator instance
33 ///
34 /// Instances of this type are used to allocate blocks of memory. For best
35 /// results only use one of these. Currently doesn't implement `Drop` to release
36 /// lingering memory back to the OS. That may happen eventually though!
37 pub struct Dlmalloc(dlmalloc::Dlmalloc);
38
39 /// Constant initializer for `Dlmalloc` structure.
40 pub const DLMALLOC_INIT: Dlmalloc = Dlmalloc(dlmalloc::DLMALLOC_INIT);
41
42 #[cfg(target_arch = "wasm32")]
43 #[path = "wasm.rs"]
44 mod sys;
45
46 #[cfg(target_os = "macos")]
47 #[path = "macos.rs"]
48 mod sys;
49
50 #[cfg(target_os = "linux")]
51 #[path = "linux.rs"]
52 mod sys;
53
54 #[cfg(target_env = "sgx")]
55 #[path = "sgx.rs"]
56 mod sys;
57
58 impl Dlmalloc {
59 /// Creates a new instance of an allocator, same as `DLMALLOC_INIT`.
60 pub fn new() -> Dlmalloc {
61 DLMALLOC_INIT
62 }
63
64 /// Allocates `size` bytes with `align` align.
65 ///
66 /// Returns a null pointer if allocation fails. Returns a valid pointer
67 /// otherwise.
68 ///
69 /// Safety and contracts are largely governed by the `GlobalAlloc::alloc`
70 /// method contracts.
71 #[inline]
72 pub unsafe fn malloc(&mut self, size: usize, align: usize) -> *mut u8 {
73 if align <= self.0.malloc_alignment() {
74 self.0.malloc(size)
75 } else {
76 self.0.memalign(align, size)
77 }
78 }
79
80 /// Same as `malloc`, except if the allocation succeeds it's guaranteed to
81 /// point to `size` bytes of zeros.
82 #[inline]
83 pub unsafe fn calloc(&mut self, size: usize, align: usize) -> *mut u8 {
84 let ptr = self.malloc(size, align);
85 if !ptr.is_null() && self.0.calloc_must_clear(ptr) {
86 ptr::write_bytes(ptr, 0, size);
87 }
88 ptr
89 }
90
91 /// Deallocates a `ptr` with `size` and `align` as the previous request used
92 /// to allocate it.
93 ///
94 /// Safety and contracts are largely governed by the `GlobalAlloc::dealloc`
95 /// method contracts.
96 #[inline]
97 pub unsafe fn free(&mut self, ptr: *mut u8, size: usize, align: usize) {
98 drop((size, align));
99 self.0.free(ptr)
100 }
101
102 /// Reallocates `ptr`, a previous allocation with `old_size` and
103 /// `old_align`, to have `new_size` and the same alignment as before.
104 ///
105 /// Returns a null pointer if the memory couldn't be reallocated, but `ptr`
106 /// is still valid. Returns a valid pointer and frees `ptr` if the request
107 /// is satisfied.
108 ///
109 /// Safety and contracts are largely governed by the `GlobalAlloc::realloc`
110 /// method contracts.
111 #[inline]
112 pub unsafe fn realloc(&mut self,
113 ptr: *mut u8,
114 old_size: usize,
115 old_align: usize,
116 new_size: usize) -> *mut u8 {
117 if old_align <= self.0.malloc_alignment() {
118 self.0.realloc(ptr, new_size)
119 } else {
120 let res = self.malloc(new_size, old_align);
121 if !res.is_null() {
122 let size = cmp::min(old_size, new_size);
123 ptr::copy_nonoverlapping(ptr, res, size);
124 self.free(ptr, old_size, old_align);
125 }
126 res
127 }
128 }
129 }
130
131 #[cfg(feature = "allocator-api")]
132 unsafe impl Alloc for Dlmalloc {
133 #[inline]
134 unsafe fn alloc(
135 &mut self,
136 layout: Layout
137 ) -> Result<ptr::NonNull<u8>, AllocErr> {
138 let ptr = <Dlmalloc>::malloc(self, layout.size(), layout.align());
139 ptr::NonNull::new(ptr).ok_or(AllocErr)
140 }
141
142 #[inline]
143 unsafe fn dealloc(&mut self, ptr: ptr::NonNull<u8>, layout: Layout) {
144 <Dlmalloc>::free(self, ptr.as_ptr(), layout.size(), layout.align())
145 }
146
147 #[inline]
148 unsafe fn realloc(
149 &mut self,
150 ptr: ptr::NonNull<u8>,
151 layout: Layout,
152 new_size: usize
153 ) -> Result<ptr::NonNull<u8>, AllocErr> {
154 let ptr = <Dlmalloc>::realloc(
155 self,
156 ptr.as_ptr(),
157 layout.size(),
158 layout.align(),
159 new_size,
160 );
161 ptr::NonNull::new(ptr).ok_or(AllocErr)
162 }
163
164 #[inline]
165 unsafe fn alloc_zeroed(
166 &mut self,
167 layout: Layout
168 ) -> Result<ptr::NonNull<u8>, AllocErr> {
169 let ptr = <Dlmalloc>::calloc(self, layout.size(), layout.align());
170 ptr::NonNull::new(ptr).ok_or(AllocErr)
171 }
172 }