Skip to content

Commit 8d8d83d

Browse files
committed
allow malloc or calloc to be passed in as allocators. Make unsafe areas of the library explicit so the user of the library has to invoke unsafe constructs in unsafe blocks and can choose to use a safe subset of the library explicitly without any unsafe code
1 parent e50f2af commit 8d8d83d

File tree

4 files changed

+112
-48
lines changed

4 files changed

+112
-48
lines changed

src/bin/example.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ mod heap_alloc;
88
pub use heap_alloc::HeapAllocator;
99

1010
mod tests;
11+
extern {
12+
fn calloc(n_elem : usize, el_size : usize) -> *mut u8;
13+
}
14+
extern {
15+
fn free(ptr : *mut u8);
16+
}
1117

1218

1319
//use alloc::AllocatedSlice;
@@ -22,10 +28,6 @@ declare_stack_allocator_struct!(CallocAllocatedFreelist4, 4, calloc);
2228
declare_stack_allocator_struct!(StackAllocatedFreelist16, 16, stack);
2329
declare_stack_allocator_struct!(BoxAllocatedFreelist, heap);
2430

25-
extern {
26-
pub fn calloc(nobj: usize, size: usize) -> *mut u8;
27-
}
28-
2931
fn main() {
3032
//let mut global_buffer : [u8; 1024 * 4096] = [0;4096*1024];
3133
//let max_memory_pool_size : usize = 1024 * 1024 * 200;
@@ -39,8 +41,8 @@ fn main() {
3941
//let global_ptr : *mut u8 = unsafe {core::mem::transmute(allocated_mem)};
4042
//let mut global_buffer = unsafe {core::slice::from_raw_parts_mut(global_ptr, max_memory_pool_size)};
4143
//trace_macros!(true);
42-
define_allocator_memory_pool!(global_buffer, 4, u8, [0; 1024 * 1024 * 200], calloc);
43-
44+
let global_buffer = unsafe {define_allocator_memory_pool!(4, u8, [0; 1024 * 1024 * 200], calloc)};
45+
//let global_buffer = alloc_no_stdlib::CallocBackingStore<u8>(1024 * 1024 * 200, alloc_no_stdlib::AllocatorC::Calloc(calloc), free, true);
4446
let mut ags = CallocAllocatedFreelist4::<u8>::new_allocator(global_buffer, bzero);
4547

4648
{
@@ -62,7 +64,7 @@ fn main() {
6264
println!("x[0] = {:?} z[0] = {:?} z[1] = {:?} r3[0] = {:?} r3[1] = {:?}", x.mem[0], z.mem[0], z.mem[1], reget_three[0], reget_three.slice()[1]);
6365
let mut _z = ags.alloc_cell(1);
6466
}
65-
define_allocator_memory_pool!(zero_global_buffer, 4, u8, [0; 1024 * 1024 * 20], heap);
67+
let mut zero_global_buffer = define_allocator_memory_pool!(4, u8, [0; 1024 * 1024 * 20], heap);
6668

6769
let mut boxallocator = BoxAllocatedFreelist::<u8>::new_allocator(1024 * 1024, &mut zero_global_buffer, bzero);
6870

@@ -86,7 +88,7 @@ fn main() {
8688
let mut _z = boxallocator.alloc_cell(1);
8789
}
8890

89-
define_allocator_memory_pool!(stack_global_buffer, 16, u8, [0; 1024 * 1024], stack);
91+
let mut stack_global_buffer = define_allocator_memory_pool!(16, u8, [0; 1024 * 1024], stack);
9092
let mut stackallocator = StackAllocatedFreelist16::<u8>::new_allocator(&mut stack_global_buffer, bzero);
9193
{
9294
let mut x = stackallocator.alloc_cell(9999);

src/init.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,11 @@ macro_rules! define_stack_allocator_traits(
6565
}
6666
define_stack_allocator_traits!($name, generic);
6767
};
68+
($name : ident, $freelist_size : tt, malloc) => {
69+
define_stack_allocator_traits!($name, calloc);
70+
};
6871
($name : ident, $freelist_size : tt, calloc) => {
72+
6973
impl<'a, T: 'a> Default for $name<'a, T> {
7074
fn default() -> Self {
7175
return $name::<'a, T>{freelist : static_array!(&mut[]; $freelist_size), backing_store : None};
@@ -136,7 +140,9 @@ macro_rules! declare_stack_allocator_struct(
136140
}
137141
}
138142
};
139-
143+
($name :ident, $freelist_size : tt, malloc) => {
144+
declare_stack_allocator_struct!($name, $freelist_size, calloc);
145+
};
140146
($name :ident, $freelist_size : tt, calloc) => {
141147
struct $name<'a, T : 'a> {
142148
freelist : [&'a mut [T]; declare_stack_allocator_struct!(@as_expr $freelist_size)],
@@ -204,9 +210,9 @@ macro_rules! declare_stack_allocator_struct(
204210
#[macro_export]
205211
macro_rules! bind_global_buffers_to_allocator(
206212
($allocator : expr, $buffer : ident, $T : ty) => {
207-
$allocator.free_list_start = unsafe{$buffer::freelist.len()};
208-
$allocator.system_resources.freelist = unsafe{&mut $buffer::freelist};
209-
$allocator.free_cell(AllocatedStackMemory::<$T>{mem:unsafe{&mut $buffer::heap}});
213+
$allocator.free_list_start = $buffer::freelist.len();
214+
$allocator.system_resources.freelist = &mut $buffer::freelist;
215+
$allocator.free_cell(AllocatedStackMemory::<$T>{mem:&mut $buffer::heap});
210216
};
211217
);
212218

@@ -215,19 +221,25 @@ macro_rules! define_allocator_memory_pool(
215221
(@as_expr $expr:expr) => {$expr};
216222

217223

218-
($name : ident, $freelist_size : tt, $T : ty, [0; $heap_size : expr], calloc) => {
219-
let $name : alloc_no_stdlib::CallocBackingStore<$T> = alloc_no_stdlib::CallocBackingStore::<$T>::new($heap_size, true);
224+
($freelist_size : tt, $T : ty, [0; $heap_size : expr], calloc) => {
225+
alloc_no_stdlib::CallocBackingStore::<$T>::new($heap_size, alloc_no_stdlib::AllocatorC::Calloc(calloc), free, true);
226+
};
227+
($freelist_size : tt, $T : ty, [0; $heap_size : expr], calloc_no_free) => {
228+
alloc_no_stdlib::CallocBackingStore::<$T>::new($heap_size, alloc_no_stdlib::AllocatorC::Calloc(calloc), free, false);
229+
};
230+
($freelist_size : tt, $T : ty, [0; $heap_size : expr], malloc) => {
231+
alloc_no_stdlib::CallocBackingStore::<$T>::new($heap_size, alloc_no_stdlib::AllocatorC::Malloc(malloc), free, true);
220232
};
221-
($name : ident, $freelist_size : tt, $T : ty, [0; $heap_size : expr], calloc_no_free) => {
222-
let $name : alloc_no_stdlib::CallocBackingStore<$T> = alloc_no_stdlib::CallocBackingStore::<$T>::new($heap_size, false);
233+
($freelist_size : tt, $T : ty, [0; $heap_size : expr], malloc_no_free) => {
234+
alloc_no_stdlib::CallocBackingStore::<$T>::new($heap_size, alloc_no_stdlib::AllocatorC::Malloc(malloc), free, false);
223235
};
224-
($name : ident, $freelist_size : tt, $T : ty, [$default_value : expr; $heap_size : expr], heap) => {
225-
let mut $name : Box<[$T]> = (vec![$default_value; $heap_size]).into_boxed_slice();
236+
($freelist_size : tt, $T : ty, [$default_value : expr; $heap_size : expr], heap) => {
237+
(vec![$default_value; $heap_size]).into_boxed_slice();
226238
};
227-
($name : ident, $freelist_size : tt, $T : ty, [$default_value : expr; $heap_size : expr], stack) => {
228-
let mut $name : [$T; $heap_size] = [$default_value; $heap_size];
239+
($freelist_size : tt, $T : ty, [$default_value : expr; $heap_size : expr], stack) => {
240+
[$default_value; $heap_size];
229241
};
230-
($name : ident, $freelist_size : tt, $T : ty, [$default_value : expr; $heap_size : expr], global) => {
242+
($freelist_size : tt, $T : ty, [$default_value : expr; $heap_size : expr], global, $name : ident) => {
231243
pub mod $name {
232244
pub static mut freelist : [&'static mut [$T];
233245
define_allocator_memory_pool!(@as_expr $freelist_size)]

src/lib.rs

100644100755
Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,29 +27,36 @@ pub fn uninitialized<T> (_data : &mut[T]) {}
2727
pub struct CallocBackingStore<'a, T : 'a> {
2828
pub raw_data : *mut u8,
2929
pub data : &'a mut[T],
30+
free : unsafe extern "C" fn(*mut u8),
3031
}
31-
extern {
32-
fn calloc(n_elem : usize, el_size : usize) -> *mut u8;
33-
}
34-
extern {
35-
fn free(ptr : *mut u8);
32+
33+
pub enum AllocatorC {
34+
Calloc(unsafe extern "C" fn(usize, usize) -> *mut u8),
35+
Malloc(unsafe extern "C" fn(usize) -> *mut u8),
36+
Custom(fn(usize) -> *mut u8),
3637
}
3738
impl<'a, T : 'a> CallocBackingStore<'a, T> {
38-
pub fn new(num_elements : usize, should_free : bool) -> Self{
39-
let retval : *mut u8 = unsafe{calloc(num_elements, core::mem::size_of::<T>())};
40-
let raw_data : *mut T = unsafe{core::mem::transmute(retval)};
39+
pub unsafe fn new(num_elements : usize, alloc : AllocatorC, free : unsafe extern "C" fn (*mut u8), should_free : bool) -> Self{
40+
let retval : *mut u8 = match alloc {
41+
AllocatorC::Calloc(calloc) => calloc(num_elements, core::mem::size_of::<T>()),
42+
AllocatorC::Malloc(malloc) => malloc(num_elements *core::mem::size_of::<T>()),
43+
AllocatorC::Custom(malloc) => malloc(num_elements *core::mem::size_of::<T>()),
44+
};
45+
let raw_data : *mut T = core::mem::transmute(retval);
4146
if should_free {
4247
return CallocBackingStore::<'a, T>{
4348
raw_data : retval,
44-
data : unsafe{core::slice::from_raw_parts_mut(raw_data,
45-
num_elements)},
49+
data : core::slice::from_raw_parts_mut(raw_data,
50+
num_elements),
51+
free : free,
4652
};
4753
} else {
4854
let null_ptr : *const u8 = core::ptr::null();
4955
return CallocBackingStore::<'a, T>{
50-
raw_data : unsafe{core::mem::transmute(null_ptr)},//retval,
51-
data : unsafe{core::slice::from_raw_parts_mut(raw_data,
52-
num_elements)},
56+
raw_data : core::mem::transmute(null_ptr),//retval,
57+
data : core::slice::from_raw_parts_mut(raw_data,
58+
num_elements),
59+
free : free,
5360
};
5461
}
5562
}
@@ -59,9 +66,9 @@ impl<'a, T:'a> Drop for CallocBackingStore<'a, T> {
5966
// core::mem::forget(core::mem::replace(self.data, &mut[]));
6067
core::mem::forget(core::mem::replace(&mut self.data, &mut[]));
6168
if !self.raw_data.is_null() {
62-
unsafe {
63-
free(self.raw_data);
64-
}
69+
let local_free = self.free;
70+
unsafe {(local_free)(self.raw_data)};
71+
6572
}
6673
}
6774
}

tests/lib.rs

100644100755
Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,23 @@ use alloc_no_stdlib::{Allocator, SliceWrapperMut, SliceWrapper,
1414

1515
declare_stack_allocator_struct!(HeapAllocatedFreelist, heap);
1616
declare_stack_allocator_struct!(CallocAllocatedFreelist4096, 4096, calloc);
17+
declare_stack_allocator_struct!(MallocAllocatedFreelist4096, 4096, malloc);
1718
declare_stack_allocator_struct!(StackAllocatedFreelist4, 4, stack);
1819
declare_stack_allocator_struct!(StackAllocatedFreelist8, 8, stack);
1920
declare_stack_allocator_struct!(GlobalAllocatedFreelist, 16, global);
2021
//trace_macros!(true);
2122

22-
define_allocator_memory_pool!(global_buffer, 16, u8, [0; 1024 * 1024 * 100], global);
23-
define_allocator_memory_pool!(global_buffer2, 16, u8, [0; 1024 * 1024 * 100], global);
23+
define_allocator_memory_pool!(16, u8, [0; 1024 * 1024 * 100], global, global_buffer);
24+
define_allocator_memory_pool!(16, u8, [0; 1024 * 1024 * 100], global, global_buffer2);
2425
extern {
2526
fn calloc(n_elem : usize, el_size : usize) -> *mut u8;
27+
fn malloc(len : usize) -> *mut u8;
28+
fn free(item : *mut u8);
2629
}
2730
#[test]
2831
fn uninitialized_stack_pool_test() {
2932
{
30-
define_allocator_memory_pool!(stack_global_buffer, 4, u8, [0; 65536], stack);
33+
let mut stack_global_buffer = define_allocator_memory_pool!(4, u8, [0; 65536], stack);
3134
let mut ags = StackAllocatedFreelist4::<u8>::new_allocator(&mut stack_global_buffer, uninitialized);
3235
{
3336
let mut x = ags.alloc_cell(9999);
@@ -56,7 +59,7 @@ fn uninitialized_stack_pool_test() {
5659
}
5760
#[test]
5861
fn uninitialized_stack_pool_free_null() {
59-
define_allocator_memory_pool!(stack_global_buffer, 8, u8, [0; 256 - 8], stack);
62+
let mut stack_global_buffer = define_allocator_memory_pool!(8, u8, [0; 256 - 8], stack);
6063
let mut ags = StackAllocatedFreelist8::<u8>::new_allocator(&mut stack_global_buffer, uninitialized);
6164
{
6265
let s = ags.alloc_cell(0);
@@ -130,7 +133,7 @@ fn uninitialized_stack_pool_free_null() {
130133
#[test]
131134
fn uninitialized_heap_pool_test() {
132135
{
133-
define_allocator_memory_pool!(heap_global_buffer, 4096, u8, [0; 6 * 1024 * 1024], heap);
136+
let mut heap_global_buffer = define_allocator_memory_pool!(4096, u8, [0; 6 * 1024 * 1024], heap);
134137
let mut ags = HeapAllocatedFreelist::<u8>::new_allocator(4096, &mut heap_global_buffer, uninitialized);
135138
{
136139
let mut x = ags.alloc_cell(9999);
@@ -161,7 +164,7 @@ fn uninitialized_heap_pool_test() {
161164
fn uninitialized_calloc_pool_test() {
162165

163166
{
164-
define_allocator_memory_pool!(calloc_global_buffer, 4096, u8, [0; 200 * 1024 * 1024], calloc);
167+
let calloc_global_buffer = unsafe{define_allocator_memory_pool!(4096, u8, [0; 200 * 1024 * 1024], calloc)};
165168
let mut ags = CallocAllocatedFreelist4096::<u8>::new_allocator(calloc_global_buffer, uninitialized);
166169
{
167170
let mut x = ags.alloc_cell(9999);
@@ -193,7 +196,9 @@ println!("{:?}", ags.free_list_start);
193196
fn uninitialized_global_pool_test() {
194197
{
195198
let mut ags = GlobalAllocatedFreelist::<u8>::new_allocator(uninitialized);
199+
unsafe {
196200
bind_global_buffers_to_allocator!(ags, global_buffer, u8);
201+
}
197202
{
198203
let mut x = ags.alloc_cell(9999);
199204
x.slice_mut()[0] = 4;
@@ -223,7 +228,7 @@ fn uninitialized_global_pool_test() {
223228
#[test]
224229
fn stack_pool_test() {
225230
{
226-
define_allocator_memory_pool!(stack_global_buffer, 4, u8, [0; 65536], stack);
231+
let mut stack_global_buffer = define_allocator_memory_pool!(4, u8, [0; 65536], stack);
227232
let mut ags = StackAllocatedFreelist4::<u8>::new_allocator(&mut stack_global_buffer, bzero);
228233
{
229234
let mut x = ags.alloc_cell(9999);
@@ -252,7 +257,7 @@ fn stack_pool_test() {
252257
}
253258
#[test]
254259
fn stack_pool_free_null() {
255-
define_allocator_memory_pool!(stack_global_buffer, 8, u8, [0; 256 - 8], stack);
260+
let mut stack_global_buffer = define_allocator_memory_pool!(8, u8, [0; 256 - 8], stack);
256261
let mut ags = StackAllocatedFreelist8::<u8>::new_allocator(&mut stack_global_buffer, bzero);
257262
{
258263
let s = ags.alloc_cell(0);
@@ -326,7 +331,7 @@ fn stack_pool_free_null() {
326331
#[test]
327332
fn heap_pool_test() {
328333
{
329-
define_allocator_memory_pool!(heap_global_buffer, 4096, u8, [0; 6 * 1024 * 1024], heap);
334+
let mut heap_global_buffer = define_allocator_memory_pool!(4096, u8, [0; 6 * 1024 * 1024], heap);
330335
let mut ags = HeapAllocatedFreelist::<u8>::new_allocator(4096, &mut heap_global_buffer, bzero);
331336
{
332337
let mut x = ags.alloc_cell(9999);
@@ -357,7 +362,7 @@ fn heap_pool_test() {
357362
fn calloc_pool_test() {
358363

359364
{
360-
define_allocator_memory_pool!(calloc_global_buffer, 4096, u8, [0; 200 * 1024 * 1024], calloc);
365+
let calloc_global_buffer = unsafe {define_allocator_memory_pool!(4096, u8, [0; 200 * 1024 * 1024], calloc)};
361366
let mut ags = CallocAllocatedFreelist4096::<u8>::new_allocator(calloc_global_buffer, bzero);
362367
{
363368
let mut x = ags.alloc_cell(9999);
@@ -391,7 +396,7 @@ fn calloc_pool_test() {
391396
fn calloc_leak_pool_test() {
392397

393398
{
394-
define_allocator_memory_pool!(calloc_global_buffer, 4096, u8, [0; 200 * 1024 * 1024], calloc_no_free);
399+
let calloc_global_buffer = unsafe{define_allocator_memory_pool!(4096, u8, [0; 200 * 1024 * 1024], calloc_no_free)};
395400
let mut ags = CallocAllocatedFreelist4096::<u8>::new_allocator(calloc_global_buffer, bzero);
396401
{
397402
let mut x = ags.alloc_cell(9999);
@@ -419,11 +424,49 @@ fn calloc_leak_pool_test() {
419424
}
420425
}
421426

427+
428+
#[test]
429+
fn malloc_pool_test() {
430+
431+
{
432+
let malloc_global_buffer = unsafe {define_allocator_memory_pool!(4096, u8, [0; 200 * 1024 * 1024], malloc)};
433+
let mut ags = MallocAllocatedFreelist4096::<u8>::new_allocator(malloc_global_buffer, bzero);
434+
{
435+
let mut x = ags.alloc_cell(9999);
436+
x.slice_mut()[0] = 4;
437+
let mut y = ags.alloc_cell(4);
438+
y[0] = 5;
439+
ags.free_cell(y);
440+
441+
let mut three = ags.alloc_cell(3);
442+
three[0] = 6;
443+
ags.free_cell(three);
444+
445+
let mut z = ags.alloc_cell(4);
446+
z.slice_mut()[1] = 8;
447+
let mut reget_three = ags.alloc_cell(4);
448+
reget_three.slice_mut()[1] = 9;
449+
//y.mem[0] = 6; // <-- this is an error (use after free)
450+
assert_eq!(x[0], 4);
451+
assert_eq!(z[0], 0);
452+
assert_eq!(z[1], 8);
453+
assert_eq!(reget_three[0], 0);
454+
assert_eq!(reget_three[1], 9);
455+
let mut _z = ags.alloc_cell(1);
456+
}
457+
}
458+
}
459+
460+
461+
462+
422463
#[test]
423464
fn global_pool_test() {
424465
{
425466
let mut ags = GlobalAllocatedFreelist::<u8>::new_allocator(bzero);
467+
unsafe {
426468
bind_global_buffers_to_allocator!(ags, global_buffer2, u8);
469+
}
427470
{
428471
let mut x = ags.alloc_cell(9999);
429472
x.slice_mut()[0] = 4;

0 commit comments

Comments
 (0)