1use crate::__internal::UsizeExt;
2use crate::backend::Backend;
3use crate::reserve::{ReserveHeader, ReserveType, RESERVE_ALIGN};
4use crate::{huge, subhuge};
5use core::alloc::{GlobalAlloc, Layout};
6use core::marker::PhantomData;
7use core::{cmp, ptr};
8
9pub struct Alloc<B> {
10 _backend: PhantomData<B>,
11}
12
13impl<B> Copy for Alloc<B> {}
14
15impl<B> Clone for Alloc<B> {
16 #[inline]
17 fn clone(&self) -> Self {
18 Self {
19 _backend: PhantomData,
20 }
21 }
22}
23
24impl<B> Alloc<B> {
25 pub const unsafe fn new() -> Self {
31 Self {
32 _backend: PhantomData,
33 }
34 }
35}
36
37impl<B: Backend> Alloc<B> {
38 #[inline]
42 pub unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
43 if layout.align() > RESERVE_ALIGN {
44 ptr::null_mut()
45 } else if layout.size() > subhuge::MAX || layout.align() > B::pagesize() {
46 huge::alloc::<B>(layout)
47 } else {
48 subhuge::alloc::<B>(layout, false)
49 }
50 }
51
52 #[inline]
56 pub unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
57 if layout.align() > RESERVE_ALIGN {
58 ptr::null_mut()
59 } else if layout.size() > subhuge::MAX || layout.align() > B::pagesize() {
60 huge::alloc::<B>(layout)
61 } else {
62 subhuge::alloc::<B>(layout, true)
63 }
64 }
65
66 pub unsafe fn realloc(&self, ptr: *mut u8, layout: Layout) -> *mut u8 {
72 let header = (ptr as usize - 1).align_down(RESERVE_ALIGN) as *mut ReserveHeader;
73 match (*header).ty {
74 ReserveType::Huge => {
75 if huge::realloc_in_place::<B>(header, ptr, layout) {
76 return ptr;
77 }
78 }
79 ReserveType::SubHuge => {
80 if subhuge::realloc_in_place::<B>(header, ptr, layout) {
81 return ptr;
82 }
83 }
84 }
85
86 let new = self.alloc(layout);
87 if new.is_null() {
88 return ptr::null_mut();
89 }
90 new.copy_from_nonoverlapping(ptr, cmp::min(layout.size(), self.size(ptr)));
91 self.dealloc(ptr);
92 new
93 }
94
95 #[inline]
99 pub unsafe fn dealloc(&self, ptr: *mut u8) {
100 let header = (ptr as usize - 1).align_down(RESERVE_ALIGN) as *mut ReserveHeader;
101 match (*header).ty {
102 ReserveType::Huge => huge::dealloc::<B>(header),
103 ReserveType::SubHuge => subhuge::dealloc::<B>(header, ptr),
104 }
105 }
106
107 #[inline]
111 pub unsafe fn size(&self, ptr: *mut u8) -> usize {
112 let header = (ptr as usize - 1).align_down(RESERVE_ALIGN) as *mut ReserveHeader;
113 match (*header).ty {
114 ReserveType::Huge => huge::size(header, ptr),
115 ReserveType::SubHuge => subhuge::size::<B>(ptr),
116 }
117 }
118}
119
120unsafe impl<B: Backend> GlobalAlloc for Alloc<B> {
121 #[inline]
122 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
123 self.alloc(layout)
124 }
125
126 #[inline]
127 unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) {
128 self.dealloc(ptr)
129 }
130
131 #[inline]
132 unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
133 self.alloc_zeroed(layout)
134 }
135
136 #[inline]
137 unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
138 self.realloc(
139 ptr,
140 Layout::from_size_align_unchecked(new_size, layout.align()),
141 )
142 }
143}