#![no_std]
extern crate libmimalloc_sys as ffi;
use core::alloc::{GlobalAlloc, Layout};
use core::ffi::c_void;
use ffi::*;
const MI_MAX_ALIGN_SIZE: usize = 16;
#[inline]
fn may_use_unaligned_api(size: usize, alignment: usize) -> bool {
debug_assert!(size != 0 && alignment.is_power_of_two());
(alignment <= MI_MAX_ALIGN_SIZE && size >= alignment)
|| (alignment == size && alignment <= 4096)
}
pub struct MiMalloc;
unsafe impl GlobalAlloc for MiMalloc {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
if may_use_unaligned_api(layout.size(), layout.align()) {
mi_malloc(layout.size()) as *mut u8
} else {
mi_malloc_aligned(layout.size(), layout.align()) as *mut u8
}
}
#[inline]
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
if may_use_unaligned_api(layout.size(), layout.align()) {
mi_zalloc(layout.size()) as *mut u8
} else {
mi_zalloc_aligned(layout.size(), layout.align()) as *mut u8
}
}
#[inline]
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
mi_free(ptr as *mut c_void);
}
#[inline]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
if may_use_unaligned_api(new_size, layout.align()) {
mi_realloc(ptr as *mut c_void, new_size) as *mut u8
} else {
mi_realloc_aligned(ptr as *mut c_void, new_size, layout.align()) as *mut u8
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_frees_allocated_memory() {
unsafe {
let layout = Layout::from_size_align(8, 8).unwrap();
let alloc = MiMalloc;
let ptr = alloc.alloc(layout);
alloc.dealloc(ptr, layout);
}
}
#[test]
fn it_frees_allocated_big_memory() {
unsafe {
let layout = Layout::from_size_align(1 << 20, 32).unwrap();
let alloc = MiMalloc;
let ptr = alloc.alloc(layout);
alloc.dealloc(ptr, layout);
}
}
#[test]
fn it_frees_zero_allocated_memory() {
unsafe {
let layout = Layout::from_size_align(8, 8).unwrap();
let alloc = MiMalloc;
let ptr = alloc.alloc_zeroed(layout);
alloc.dealloc(ptr, layout);
}
}
#[test]
fn it_frees_zero_allocated_big_memory() {
unsafe {
let layout = Layout::from_size_align(1 << 20, 32).unwrap();
let alloc = MiMalloc;
let ptr = alloc.alloc_zeroed(layout);
alloc.dealloc(ptr, layout);
}
}
#[test]
fn it_frees_reallocated_memory() {
unsafe {
let layout = Layout::from_size_align(8, 8).unwrap();
let alloc = MiMalloc;
let ptr = alloc.alloc(layout);
let ptr = alloc.realloc(ptr, layout, 16);
alloc.dealloc(ptr, layout);
}
}
#[test]
fn it_frees_reallocated_big_memory() {
unsafe {
let layout = Layout::from_size_align(1 << 20, 32).unwrap();
let alloc = MiMalloc;
let ptr = alloc.alloc(layout);
let ptr = alloc.realloc(ptr, layout, 2 << 20);
alloc.dealloc(ptr, layout);
}
}
}