jemalloc/
lib.rs

1#![no_std]
2
3extern crate loca;
4
5use core::ptr::NonNull;
6use loca::*;
7
8use c::*;
9
10mod c {
11    // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
12    // file at the top-level directory of this distribution and at
13    // http://rust-lang.org/COPYRIGHT.
14    //
15    // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
16    // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
17    // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
18    // option. This file may not be copied, modified, or distributed
19    // except according to those terms.
20
21    // Note that the symbols here are prefixed by default on macOS and Windows (we
22    // don't explicitly request it), and on Android and DragonFly we explicitly
23    // request it as unprefixing cause segfaults (mismatches in allocators).
24    extern "C" {
25        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
26                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
27                   link_name = "je_mallocx")]
28        pub fn mallocx(size: usize, flags: usize) -> *mut u8;
29        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
30                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
31                   link_name = "je_rallocx")]
32        pub fn rallocx(ptr: *mut u8, size: usize, flags: usize) -> *mut u8;
33        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
34                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
35                   link_name = "je_xallocx")]
36        pub fn xallocx(ptr: *mut u8, size: usize, extra: usize, flags: usize) -> usize;
37        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
38                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
39                   link_name = "je_sdallocx")]
40        pub fn sdallocx(ptr: *mut u8, size: usize, flags: usize);
41        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
42                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
43                   link_name = "je_nallocx")]
44        pub fn nallocx(size: usize, flags: usize) -> usize;
45    }
46}
47
48#[derive(Clone, Copy, Default, Debug)]
49pub struct Jemalloc;
50
51use AllocErr::*;
52
53const MALLOCX_ZERO: usize = 0x40;
54
55unsafe impl Alloc for Jemalloc {
56    #[inline]
57    unsafe fn alloc(&mut self, l: Layout) -> Result<NonNull<u8>, AllocErr> {
58        NonNull::new(mallocx(l.size(), l.align().get().trailing_zeros() as _))
59            .ok_or(Exhausted { request: l })
60    }
61
62    #[inline]
63    unsafe fn alloc_zeroed(&mut self, l: Layout) -> Result<NonNull<u8>, AllocErr> {
64        NonNull::new(mallocx(l.size(), l.align().get().trailing_zeros() as usize | MALLOCX_ZERO))
65            .ok_or(Exhausted { request: l })
66    }
67
68    #[inline]
69    unsafe fn realloc(&mut self, ptr: NonNull<u8>, old_l: Layout, new_size: usize) -> Result<NonNull<u8>, AllocErr> {
70        NonNull::new(rallocx(ptr.as_ptr(), new_size, old_l.align().get().trailing_zeros() as _))
71            .ok_or(Exhausted { request: Layout::from_size_align(new_size, old_l.align().get()).unwrap() })
72    }
73
74    #[inline]
75    unsafe fn dealloc(&mut self, ptr: NonNull<u8>, l: Layout) {
76        sdallocx(ptr.as_ptr(), l.size(), l.align().get().trailing_zeros() as _)
77    }
78
79    #[inline]
80    unsafe fn resize_in_place(&mut self, ptr: NonNull<u8>, old_l: Layout, new_size: usize) -> Result<(), CannotReallocInPlace> {
81        if new_size ==
82           xallocx(ptr.as_ptr(), new_size, 0, old_l.align().get().trailing_zeros() as _) { Ok(()) }
83        else { Err(CannotReallocInPlace) }
84    }
85
86    #[inline]
87    fn usable_size(&self, l: Layout) -> (usize, usize) {
88        (l.size(), ::core::cmp::max(l.size(), unsafe {
89            nallocx(l.size(), l.align().get().trailing_zeros() as _)
90        }))
91    }
92}