1 //! **Ralloc:** The memory efficient allocator. 2 //! 3 //! This crates define the user space allocator for Redox, which emphasizes performance and memory 4 //! efficiency. 5 //! 6 //! # Ralloc seems to reimplement everything. Why? 7 //! 8 //! Memory allocators cannot depend on libraries or primitives, which allocates. This is a 9 //! relatively strong condition, which means that you are forced to rewrite primitives and make 10 //! sure no allocation ever happens. 11 12 #![cfg_attr(feature = "clippy", feature(plugin))] 13 #![cfg_attr(feature = "clippy", plugin(clippy))] 14 #![no_std] 15 #![feature( 16 allocator_api, const_fn, core_intrinsics, stmt_expr_attributes, optin_builtin_traits, 17 type_ascription, thread_local, linkage, try_from, const_unsafe_cell_new, const_atomic_bool_new, 18 const_nonzero_new, const_atomic_ptr_new 19 )] 20 #![warn(missing_docs)] 21 22 extern crate ralloc_shim as shim; 23 24 #[macro_use] 25 mod log; 26 #[macro_use] 27 #[cfg(feature = "tls")] 28 mod tls; 29 30 #[macro_use] 31 mod unborrow; 32 33 mod allocator; 34 mod block; 35 mod bookkeeper; 36 mod brk; 37 mod cell; 38 mod fail; 39 mod lazy_init; 40 mod leak; 41 mod prelude; 42 mod ptr; 43 mod sync; 44 mod vec; 45 46 use core::alloc::GlobalAlloc; 47 use core::alloc::{Alloc, AllocErr, CannotReallocInPlace, Layout}; 48 use core::ptr::NonNull; 49 50 pub use allocator::{alloc, free, realloc, realloc_inplace}; 51 pub use brk::sbrk; 52 pub use fail::set_oom_handler; 53 #[cfg(feature = "tls")] 54 pub use fail::set_thread_oom_handler; 55 56 /// The rallocator 57 pub struct Allocator; 58 59 unsafe impl<'a> Alloc for &'a Allocator { 60 unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> { 61 let ptr = allocator::alloc(layout.size(), layout.align()); 62 if ptr.is_null() { 63 Err(AllocErr) 64 } else { 65 Ok(NonNull::new_unchecked(ptr)) 66 } 67 } 68 69 unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) { 70 allocator::free(ptr.as_ptr(), layout.size()); 71 } 72 73 unsafe fn realloc( 74 &mut self, 75 ptr: NonNull<u8>, 76 layout: Layout, 77 new_size: usize, 78 ) -> Result<NonNull<u8>, AllocErr> { 79 let ptr = allocator::realloc(ptr.as_ptr(), layout.size(), new_size, layout.align()); 80 if ptr.is_null() { 81 Err(AllocErr) 82 } else { 83 Ok(NonNull::new_unchecked(ptr)) 84 } 85 } 86 87 unsafe fn grow_in_place( 88 &mut self, 89 ptr: NonNull<u8>, 90 layout: Layout, 91 new_size: usize, 92 ) -> Result<(), CannotReallocInPlace> { 93 if allocator::realloc_inplace(ptr.as_ptr(), layout.size(), new_size).is_ok() { 94 Ok(()) 95 } else { 96 Err(CannotReallocInPlace) 97 } 98 } 99 100 unsafe fn shrink_in_place( 101 &mut self, 102 ptr: NonNull<u8>, 103 layout: Layout, 104 new_size: usize, 105 ) -> Result<(), CannotReallocInPlace> { 106 if allocator::realloc_inplace(ptr.as_ptr(), layout.size(), new_size).is_ok() { 107 Ok(()) 108 } else { 109 Err(CannotReallocInPlace) 110 } 111 } 112 113 fn usable_size(&self, layout: &Layout) -> (usize, usize) { 114 // Yay! It matches exactly. 115 (layout.size(), layout.size()) 116 } 117 } 118 119 unsafe impl GlobalAlloc for Allocator { 120 unsafe fn alloc(&self, layout: Layout) -> *mut u8 { 121 allocator::alloc(layout.size(), layout.align()) 122 } 123 unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { 124 allocator::free(ptr, layout.size()); 125 } 126 } 127