1 // Copyright 2014 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.
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.
11 // FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
13 /// Returns a pointer to `size` bytes of memory.
15 /// Behavior is undefined if the requested size is 0 or the alignment is not a
16 /// power of 2. The alignment must be no larger than the largest supported page
17 /// size on the platform.
19 pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
20 imp::allocate(size, align)
23 /// Extends or shrinks the allocation referenced by `ptr` to `size` bytes of
26 /// Behavior is undefined if the requested size is 0 or the alignment is not a
27 /// power of 2. The alignment must be no larger than the largest supported page
28 /// size on the platform.
30 /// The `old_size` and `align` parameters are the parameters that were used to
31 /// create the allocation referenced by `ptr`. The `old_size` parameter may also
32 /// be the value returned by `usable_size` for the requested size.
34 pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
35 old_size: uint) -> *mut u8 {
36 imp::reallocate(ptr, size, align, old_size)
39 /// Extends or shrinks the allocation referenced by `ptr` to `size` bytes of
42 /// Returns true if successful, otherwise false if the allocation was not
45 /// Behavior is undefined if the requested size is 0 or the alignment is not a
46 /// power of 2. The alignment must be no larger than the largest supported page
47 /// size on the platform.
49 /// The `old_size` and `align` parameters are the parameters that were used to
50 /// create the allocation referenced by `ptr`. The `old_size` parameter may be
51 /// any value in range_inclusive(requested_size, usable_size).
53 pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint,
54 old_size: uint) -> bool {
55 imp::reallocate_inplace(ptr, size, align, old_size)
58 /// Deallocates the memory referenced by `ptr`.
60 /// The `ptr` parameter must not be null.
62 /// The `size` and `align` parameters are the parameters that were used to
63 /// create the allocation referenced by `ptr`. The `size` parameter may also be
64 /// the value returned by `usable_size` for the requested size.
66 pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
67 imp::deallocate(ptr, size, align)
70 /// Returns the usable size of an allocation created with the specified the
71 /// `size` and `align`.
73 pub fn usable_size(size: uint, align: uint) -> uint {
74 imp::usable_size(size, align)
77 /// Prints implementation-defined allocator statistics.
79 /// These statistics may be inconsistent if other threads use the allocator
82 pub fn stats_print() {
86 /// An arbitrary non-null address to represent zero-size allocations.
88 /// This preserves the non-null invariant for types like `Box<T>`. The address may overlap with
89 /// non-zero-size memory allocations.
90 pub static EMPTY: *mut () = 0x1 as *mut ();
92 /// The allocator for unique pointers.
94 #[lang="exchange_malloc"]
96 unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 {
100 allocate(size, align)
105 #[lang="exchange_free"]
107 unsafe fn exchange_free(ptr: *mut u8, size: uint, align: uint) {
108 deallocate(ptr, size, align);
111 // The minimum alignment guaranteed by the architecture. This value is used to
112 // add fast paths for low alignment values. In practice, the alignment is a
113 // constant at the call site and the branch will be optimized out.
114 #[cfg(target_arch = "arm")]
115 #[cfg(target_arch = "mips")]
116 #[cfg(target_arch = "mipsel")]
117 static MIN_ALIGN: uint = 8;
118 #[cfg(target_arch = "x86")]
119 #[cfg(target_arch = "x86_64")]
120 static MIN_ALIGN: uint = 16;
124 use core::option::{None, Option};
125 use core::ptr::{RawPtr, null_mut, null};
127 use libc::{c_char, c_int, c_void, size_t};
128 use super::MIN_ALIGN;
130 #[link(name = "jemalloc", kind = "static")]
135 fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void;
136 fn je_rallocx(ptr: *mut c_void, size: size_t,
137 flags: c_int) -> *mut c_void;
138 fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t,
139 flags: c_int) -> size_t;
140 fn je_sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
141 fn je_nallocx(size: size_t, flags: c_int) -> size_t;
142 fn je_malloc_stats_print(write_cb: Option<extern "C" fn(cbopaque: *mut c_void,
144 cbopaque: *mut c_void,
145 opts: *const c_char);
148 // -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
149 #[cfg(not(windows), not(target_os = "android"))]
150 #[link(name = "pthread")]
153 // MALLOCX_ALIGN(a) macro
155 fn mallocx_align(a: uint) -> c_int { a.trailing_zeros() as c_int }
158 fn align_to_flags(align: uint) -> c_int {
159 if align <= MIN_ALIGN { 0 } else { mallocx_align(align) }
163 pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
164 let flags = align_to_flags(align);
165 let ptr = je_mallocx(size as size_t, flags) as *mut u8;
173 pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
174 _old_size: uint) -> *mut u8 {
175 let flags = align_to_flags(align);
176 let ptr = je_rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8;
184 pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint,
185 _old_size: uint) -> bool {
186 let flags = align_to_flags(align);
187 je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) == size as size_t
191 pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
192 let flags = align_to_flags(align);
193 je_sdallocx(ptr as *mut c_void, size as size_t, flags)
197 pub fn usable_size(size: uint, align: uint) -> uint {
198 let flags = align_to_flags(align);
199 unsafe { je_nallocx(size as size_t, flags) as uint }
202 pub fn stats_print() {
204 je_malloc_stats_print(None, null_mut(), null())
209 #[cfg(not(jemalloc), unix)]
215 use super::MIN_ALIGN;
218 fn posix_memalign(memptr: *mut *mut libc::c_void,
220 size: libc::size_t) -> libc::c_int;
224 pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
225 if align <= MIN_ALIGN {
226 libc_heap::malloc_raw(size)
228 let mut out = 0 as *mut libc::c_void;
229 let ret = posix_memalign(&mut out,
230 align as libc::size_t,
231 size as libc::size_t);
240 pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
241 old_size: uint) -> *mut u8 {
242 if align <= MIN_ALIGN {
243 libc_heap::realloc_raw(ptr, size)
245 let new_ptr = allocate(size, align);
246 ptr::copy_memory(new_ptr, ptr as *const u8, cmp::min(size, old_size));
247 deallocate(ptr, old_size, align);
253 pub unsafe fn reallocate_inplace(_ptr: *mut u8, _size: uint, _align: uint,
254 _old_size: uint) -> bool {
259 pub unsafe fn deallocate(ptr: *mut u8, _size: uint, _align: uint) {
260 libc::free(ptr as *mut libc::c_void)
264 pub fn usable_size(size: uint, _align: uint) -> uint {
268 pub fn stats_print() {}
271 #[cfg(not(jemalloc), windows)]
273 use libc::{c_void, size_t};
276 use core::ptr::RawPtr;
277 use super::MIN_ALIGN;
280 fn _aligned_malloc(size: size_t, align: size_t) -> *mut c_void;
281 fn _aligned_realloc(block: *mut c_void, size: size_t,
282 align: size_t) -> *mut c_void;
283 fn _aligned_free(ptr: *mut c_void);
287 pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
288 if align <= MIN_ALIGN {
289 libc_heap::malloc_raw(size)
291 let ptr = _aligned_malloc(size as size_t, align as size_t);
300 pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
301 _old_size: uint) -> *mut u8 {
302 if align <= MIN_ALIGN {
303 libc_heap::realloc_raw(ptr, size)
305 let ptr = _aligned_realloc(ptr as *mut c_void, size as size_t,
315 pub unsafe fn reallocate_inplace(_ptr: *mut u8, _size: uint, _align: uint,
316 _old_size: uint) -> bool {
321 pub unsafe fn deallocate(ptr: *mut u8, _size: uint, align: uint) {
322 if align <= MIN_ALIGN {
323 libc::free(ptr as *mut libc::c_void)
325 _aligned_free(ptr as *mut c_void)
330 pub fn usable_size(size: uint, _align: uint) -> uint {
334 pub fn stats_print() {}
340 use self::test::Bencher;
343 fn alloc_owned_small(b: &mut Bencher) {