xref: /relibc/ralloc/src/lib.rs (revision 311db75868ff73089a3ab46258ce8cdb2d1670f9)
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