|
| 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. |
| 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 | +use intrinsics::{abort, cttz32}; |
| 12 | +use libc::{c_int, c_void, size_t}; |
| 13 | +use ptr::RawPtr; |
| 14 | + |
| 15 | +#[link(name = "jemalloc", kind = "static")] |
| 16 | +extern { |
| 17 | + fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void; |
| 18 | + fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void; |
| 19 | + fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t; |
| 20 | + fn je_dallocx(ptr: *mut c_void, flags: c_int); |
| 21 | + fn je_nallocx(size: size_t, flags: c_int) -> size_t; |
| 22 | +} |
| 23 | + |
| 24 | +// -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough |
| 25 | +#[cfg(not(windows))] |
| 26 | +#[link(name = "pthread")] |
| 27 | +extern {} |
| 28 | + |
| 29 | +// MALLOCX_ALIGN(a) macro |
| 30 | +#[inline(always)] |
| 31 | +fn mallocx_align(a: uint) -> c_int { unsafe { cttz32(a as u32) as c_int } } |
| 32 | + |
| 33 | +/// Return a pointer to `size` bytes of memory. |
| 34 | +/// |
| 35 | +/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The |
| 36 | +/// alignment must be no larger than the largest supported page size on the platform. |
| 37 | +#[inline] |
| 38 | +pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 { |
| 39 | + let ptr = je_mallocx(size as size_t, mallocx_align(align)) as *mut u8; |
| 40 | + if ptr.is_null() { |
| 41 | + abort() |
| 42 | + } |
| 43 | + ptr |
| 44 | +} |
| 45 | + |
| 46 | +/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of memory. |
| 47 | +/// |
| 48 | +/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The |
| 49 | +/// alignment must be no larger than the largest supported page size on the platform. |
| 50 | +/// |
| 51 | +/// The `old_size` and `align` parameters are the parameters that were used to create the |
| 52 | +/// allocation referenced by `ptr`. The `old_size` parameter may also be the value returned by |
| 53 | +/// `usable_size` for the requested size. |
| 54 | +#[inline] |
| 55 | +#[allow(unused_variable)] // for the parameter names in the documentation |
| 56 | +pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint, old_size: uint) -> *mut u8 { |
| 57 | + let ptr = je_rallocx(ptr as *mut c_void, size as size_t, mallocx_align(align)) as *mut u8; |
| 58 | + if ptr.is_null() { |
| 59 | + abort() |
| 60 | + } |
| 61 | + ptr |
| 62 | +} |
| 63 | + |
| 64 | +/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of memory in-place. |
| 65 | +/// |
| 66 | +/// Return true if successful, otherwise false if the allocation was not altered. |
| 67 | +/// |
| 68 | +/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The |
| 69 | +/// alignment must be no larger than the largest supported page size on the platform. |
| 70 | +/// |
| 71 | +/// The `old_size` and `align` parameters are the parameters that were used to |
| 72 | +/// create the allocation referenced by `ptr`. The `old_size` parameter may be |
| 73 | +/// any value in range_inclusive(requested_size, usable_size). |
| 74 | +#[inline] |
| 75 | +#[allow(unused_variable)] // for the parameter names in the documentation |
| 76 | +pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint, old_size: uint) -> bool { |
| 77 | + je_xallocx(ptr as *mut c_void, size as size_t, 0, mallocx_align(align)) == size as size_t |
| 78 | +} |
| 79 | + |
| 80 | +/// Deallocate the memory referenced by `ptr`. |
| 81 | +/// |
| 82 | +/// The `ptr` parameter must not be null. |
| 83 | +/// |
| 84 | +/// The `size` and `align` parameters are the parameters that were used to create the |
| 85 | +/// allocation referenced by `ptr`. The `size` parameter may also be the value returned by |
| 86 | +/// `usable_size` for the requested size. |
| 87 | +#[inline] |
| 88 | +#[allow(unused_variable)] // for the parameter names in the documentation |
| 89 | +pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) { |
| 90 | + je_dallocx(ptr as *mut c_void, mallocx_align(align)) |
| 91 | +} |
| 92 | + |
| 93 | +/// Return the usable size of an allocation created with the specified the `size` and `align`. |
| 94 | +#[inline] |
| 95 | +pub fn usable_size(size: uint, align: uint) -> uint { |
| 96 | + unsafe { je_nallocx(size as size_t, mallocx_align(align)) as uint } |
| 97 | +} |
0 commit comments