1use crate::Mimalloc;
2use core::alloc::{GlobalAlloc, Layout};
3use core::ffi::c_void;
4use core::ptr::null_mut;
5use libc::{mmap, munmap, sysconf};
6use libc::{MAP_ANONYMOUS, MAP_FAILED, MAP_PRIVATE, PROT_READ, PROT_WRITE, _SC_PAGE_SIZE};
7
8#[derive(Default)]
12pub struct MmapAlloc;
13
14pub type MimallocMmap = Mimalloc<MmapAlloc>;
16
17pub const fn new_mimalloc_mmap() -> MimallocMmap {
19 Mimalloc::with_os_allocator(MmapAlloc)
20}
21
22unsafe fn mmap_anoymous(size: usize) -> *mut c_void {
23 mmap(
24 null_mut(),
25 size,
26 PROT_READ | PROT_WRITE,
27 MAP_PRIVATE | MAP_ANONYMOUS,
28 -1,
29 0,
30 )
31}
32
33unsafe impl GlobalAlloc for MmapAlloc {
34 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
40 let size = layout.size();
41 let align = layout.align();
42
43 debug_assert!(size % sysconf(_SC_PAGE_SIZE) as usize == 0);
45 debug_assert!(align % sysconf(_SC_PAGE_SIZE) as usize == 0);
46
47 let p = mmap_anoymous(size);
49 if p == MAP_FAILED {
50 return null_mut();
51 }
52
53 if p as usize % align == 0 {
54 return p.cast();
56 }
57 munmap(p, size);
59
60 let start = mmap_anoymous(size + align - 1);
62 if start == MAP_FAILED {
63 return null_mut();
64 }
65
66 let offset = start.align_offset(align);
67 let aligned = start.add(offset);
68 if offset != 0 {
69 munmap(start, offset);
70 }
71 if offset != align - 1 {
72 let end = aligned.add(size);
73 munmap(end, align - 1 - offset);
74 }
75 aligned.cast()
76 }
77
78 unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
79 munmap(ptr.cast(), layout.size());
80 }
81}