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: #13994: port to the sized deallocation API when available
12 // FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
15 use core::intrinsics::{abort, cttz32};
16 use core::option::{None, Option};
17 use core::ptr::{RawPtr, mut_null, null};
18 use libc::{c_char, c_int, c_void, size_t};
20 #[cfg(not(test))] use core::raw;
21 #[cfg(not(test))] use util;
23 #[link(name = "jemalloc", kind = "static")]
25 fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void;
26 fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
27 fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t,
28 flags: c_int) -> size_t;
29 fn je_dallocx(ptr: *mut c_void, flags: c_int);
30 fn je_nallocx(size: size_t, flags: c_int) -> size_t;
31 fn je_malloc_stats_print(write_cb: Option<extern "C" fn(cbopaque: *mut c_void, *c_char)>,
32 cbopaque: *mut c_void,
36 // -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
37 #[cfg(not(windows), not(target_os = "android"))]
38 #[link(name = "pthread")]
41 // MALLOCX_ALIGN(a) macro
43 fn mallocx_align(a: uint) -> c_int { unsafe { cttz32(a as u32) as c_int } }
45 /// Return a pointer to `size` bytes of memory.
47 /// Behavior is undefined if the requested size is 0 or the alignment is not a
48 /// power of 2. The alignment must be no larger than the largest supported page
49 /// size on the platform.
51 pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
52 let ptr = je_mallocx(size as size_t, mallocx_align(align)) as *mut u8;
59 /// Extend or shrink the allocation referenced by `ptr` to `size` bytes of
62 /// Behavior is undefined if the requested size is 0 or the alignment is not a
63 /// power of 2. The alignment must be no larger than the largest supported page
64 /// size on the platform.
66 /// The `old_size` and `align` parameters are the parameters that were used to
67 /// create the allocation referenced by `ptr`. The `old_size` parameter may also
68 /// be the value returned by `usable_size` for the requested size.
70 #[allow(unused_variable)] // for the parameter names in the documentation
71 pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
72 old_size: uint) -> *mut u8 {
73 let ptr = je_rallocx(ptr as *mut c_void, size as size_t,
74 mallocx_align(align)) as *mut u8;
81 /// Extend or shrink the allocation referenced by `ptr` to `size` bytes of
84 /// Return true if successful, otherwise false if the allocation was not
87 /// Behavior is undefined if the requested size is 0 or the alignment is not a
88 /// power of 2. The alignment must be no larger than the largest supported page
89 /// size on the platform.
91 /// The `old_size` and `align` parameters are the parameters that were used to
92 /// create the allocation referenced by `ptr`. The `old_size` parameter may be
93 /// any value in range_inclusive(requested_size, usable_size).
95 #[allow(unused_variable)] // for the parameter names in the documentation
96 pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint,
97 old_size: uint) -> bool {
98 je_xallocx(ptr as *mut c_void, size as size_t, 0,
99 mallocx_align(align)) == size as size_t
102 /// Deallocate the memory referenced by `ptr`.
104 /// The `ptr` parameter must not be null.
106 /// The `size` and `align` parameters are the parameters that were used to
107 /// create the allocation referenced by `ptr`. The `size` parameter may also be
108 /// the value returned by `usable_size` for the requested size.
110 #[allow(unused_variable)] // for the parameter names in the documentation
111 pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
112 je_dallocx(ptr as *mut c_void, mallocx_align(align))
115 /// Return the usable size of an allocation created with the specified the
116 /// `size` and `align`.
118 pub fn usable_size(size: uint, align: uint) -> uint {
119 unsafe { je_nallocx(size as size_t, mallocx_align(align)) as uint }
122 /// Print implementation-defined allocator statistics.
124 /// These statistics may be inconsistent if other threads use the allocator
127 pub fn stats_print() {
129 je_malloc_stats_print(None, mut_null(), null())
133 // The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size
134 // allocations can point to this `static`. It would be incorrect to use a null
135 // pointer, due to enums assuming types like unique pointers are never null.
136 pub static mut EMPTY: uint = 12345;
138 /// The allocator for unique pointers.
140 #[lang="exchange_malloc"]
142 unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 {
144 &EMPTY as *uint as *mut u8
146 allocate(size, align)
151 #[lang="exchange_free"]
153 unsafe fn exchange_free(ptr: *mut u8, size: uint, align: uint) {
154 deallocate(ptr, size, align);
159 #[lang="closure_exchange_malloc"]
162 unsafe fn closure_exchange_malloc(drop_glue: fn(*mut u8), size: uint,
163 align: uint) -> *mut u8 {
164 let total_size = util::get_box_size(size, align);
165 let p = allocate(total_size, 8);
167 let alloc = p as *mut raw::Box<()>;
168 (*alloc).drop_glue = drop_glue;
176 use self::test::Bencher;
179 fn alloc_owned_small(b: &mut Bencher) {