1#![no_std]
2#![allow(non_snake_case, non_camel_case_types)]
3extern crate libisoalloc_sys as ffi;
4
5use core::alloc::{GlobalAlloc, Layout};
6use core::ffi::c_void;
7use ffi::*;
8
9pub struct IsoAlloc;
10
11unsafe impl GlobalAlloc for IsoAlloc {
13 #[inline]
14 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
15 iso_alloc(layout.size()) as *mut u8
16 }
17
18 #[inline]
19 unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
20 iso_calloc(1usize, layout.size()) as *mut u8
21 }
22
23 #[inline]
24 unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
25 iso_free_size(ptr as *mut c_void, layout.size());
26 }
27
28 #[inline]
29 unsafe fn realloc(&self, ptr: *mut u8, _: Layout, size: usize) -> *mut u8 {
30 iso_realloc(ptr as *mut c_void, size) as *mut u8
31 }
32}
33
34impl IsoAlloc {
35 pub unsafe fn reallocarray(
41 &self,
42 ptr: *mut u8,
43 _: Layout,
44 nmemb: usize,
45 size: usize,
46 ) -> *mut u8 {
47 iso_reallocarray(ptr as *mut c_void, nmemb, size) as *mut u8
48 }
49
50 pub fn usable_size(&self, ptr: *mut u8) -> usize {
52 unsafe { iso_chunksz(ptr as *mut c_void) }
53 }
54
55 pub fn verify_zones(&self) {
57 unsafe { iso_verify_zones() };
58 }
59
60 pub fn mem_usage(&self) -> u64 {
62 unsafe { iso_alloc_mem_usage() }
63 }
64
65 pub fn leaks(&self) -> u64 {
67 unsafe { iso_alloc_detect_leaks() }
68 }
69
70 fn page_size(&self) -> u64 {
71 static HDL: spin::Once = spin::Once::new();
72 static mut PSZ: u64 = 0;
73
74 unsafe {
75 HDL.call_once(|| PSZ = libc::sysconf(libc::_SC_PAGESIZE) as u64);
76 PSZ
77 }
78 }
79
80 pub fn IS_PAGE_ALIGNED(&self, p: u64) -> bool {
81 p & (self.page_size() - 1) == 0
82 }
83
84 pub const fn IS_ALIGNED(&self, p: u64) -> bool {
85 p & (8 - 1) == 0
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn reuse_mem() {
95 unsafe {
96 let l = Layout::from_size_align(1024, 8)
97 .expect("should be able to work 8 with bytes alignment");
98 let mut p = IsoAlloc.alloc_zeroed(l);
99 p = IsoAlloc.realloc(p, l, 4096);
100 assert!(IsoAlloc.IS_ALIGNED(p as u64));
101 IsoAlloc.dealloc(p, l);
102 }
103 }
104
105 #[test]
106 fn large_alloc() {
107 unsafe {
108 let l = Layout::from_size_align(1 << 20, 32).unwrap();
109 let p = IsoAlloc.alloc(l);
110 assert!(IsoAlloc.IS_PAGE_ALIGNED(p as u64));
111 IsoAlloc.dealloc(p, l);
112 }
113 }
114
115 #[test]
116 fn realloc_array() {
117 unsafe {
118 let l = Layout::from_size_align(8, 8).unwrap();
119 let mut p = core::ptr::null_mut();
120 p = IsoAlloc.realloc(p, l, 1024);
121 p = IsoAlloc.reallocarray(p, l, 2, 1024);
122 IsoAlloc.dealloc(p, l);
123 }
124 }
125
126 #[test]
127 fn utils() {
128 use core::convert::TryInto;
129 unsafe {
130 let l = Layout::from_size_align(8, 8).unwrap();
131 let a = IsoAlloc.alloc(l);
132 assert!(IsoAlloc.usable_size(a) >= l.size());
133 let ta = IsoAlloc.mem_usage();
134 assert!(ta > l.size().try_into().unwrap());
135 let b = IsoAlloc.alloc(l);
136 let tb = IsoAlloc.mem_usage();
137 assert!(tb >= ta);
138 IsoAlloc.dealloc(b, l);
139 IsoAlloc.dealloc(a, l);
140 assert_eq!(IsoAlloc.leaks(), 0u64);
141 IsoAlloc.verify_zones();
142 }
143 }
144}