/src/cpython/Objects/mimalloc/alloc-aligned.c
Line | Count | Source |
1 | | /* ---------------------------------------------------------------------------- |
2 | | Copyright (c) 2018-2021, Microsoft Research, Daan Leijen |
3 | | This is free software; you can redistribute it and/or modify it under the |
4 | | terms of the MIT license. A copy of the license can be found in the file |
5 | | "LICENSE" at the root of this distribution. |
6 | | -----------------------------------------------------------------------------*/ |
7 | | |
8 | | #include "mimalloc.h" |
9 | | #include "mimalloc/internal.h" |
10 | | #include "mimalloc/prim.h" // mi_prim_get_default_heap |
11 | | |
12 | | #include <string.h> // memset |
13 | | |
14 | | // ------------------------------------------------------ |
15 | | // Aligned Allocation |
16 | | // ------------------------------------------------------ |
17 | | |
18 | 0 | static bool mi_malloc_is_naturally_aligned( size_t size, size_t alignment ) { |
19 | | // objects up to `MI_MAX_ALIGN_GUARANTEE` are allocated aligned to their size (see `segment.c:_mi_segment_page_start`). |
20 | 0 | mi_assert_internal(mi_alignment_is_valid(alignment)); |
21 | 0 | if (alignment > size) return false; |
22 | 0 | if (alignment <= MI_MAX_ALIGN_SIZE) return true; |
23 | 0 | const size_t bsize = mi_good_size(size); |
24 | 0 | return (bsize <= MI_MAX_ALIGN_GUARANTEE && (bsize & (alignment-1)) == 0); |
25 | 0 | } |
26 | | |
27 | | #if MI_GUARDED |
28 | | static mi_decl_noinline mi_decl_restrict void* mi_heap_malloc_guarded_aligned(mi_heap_t* heap, size_t size, size_t alignment, bool zero, mi_page_t** ppage) mi_attr_noexcept { |
29 | | // use over allocation for guarded blocksl |
30 | | mi_assert_internal(alignment > 0 && alignment < MI_BLOCK_ALIGNMENT_MAX); |
31 | | if mi_unlikely(alignment >= MI_BLOCK_ALIGNMENT_MAX || size > (MI_MAX_ALLOC_SIZE - MI_PADDING_SIZE - alignment)) { |
32 | | _mi_error_message(EOVERFLOW, "(guarded) aligned allocation request is too large (size %zu, alignment %zu)\n", size, alignment); |
33 | | return NULL; |
34 | | } |
35 | | const size_t oversize = size + alignment - 1; |
36 | | void* const base = _mi_heap_malloc_guarded(heap, oversize, zero, ppage); |
37 | | if (base==NULL) return NULL; |
38 | | void* const p = _mi_align_up_ptr(base, alignment); |
39 | | mi_track_align(base, p, (uint8_t*)p - (uint8_t*)base, size); |
40 | | mi_assert_internal(mi_usable_size(p) >= size); |
41 | | mi_assert_internal(_mi_is_aligned(p, alignment)); |
42 | | return p; |
43 | | } |
44 | | |
45 | | static void* mi_heap_malloc_zero_no_guarded(mi_heap_t* heap, size_t size, bool zero, mi_page_t** ppage) { |
46 | | const size_t rate = heap->guarded_sample_rate; |
47 | | // only write if `rate!=0` so we don't write to the constant `_mi_heap_empty` |
48 | | if (rate != 0) { heap->guarded_sample_rate = 0; } |
49 | | void* p = _mi_heap_malloc_zero_ex(heap, size, zero, 0, ppage); |
50 | | if (rate != 0) { heap->guarded_sample_rate = rate; } |
51 | | return p; |
52 | | } |
53 | | #else |
54 | 0 | static void* mi_heap_malloc_zero_no_guarded(mi_heap_t* heap, size_t size, bool zero, mi_page_t** ppage) { |
55 | 0 | return _mi_heap_malloc_zero_ex(heap, size, zero, 0, ppage); |
56 | 0 | } |
57 | | #endif |
58 | | |
59 | | // Fallback aligned allocation that over-allocates -- split out for better codegen |
60 | | static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_overalloc(mi_heap_t* const heap, const size_t size, const size_t alignment, const size_t offset, const bool zero, mi_page_t** ppage) mi_attr_noexcept |
61 | 0 | { |
62 | 0 | mi_assert_internal(size <= (MI_MAX_ALLOC_SIZE - MI_PADDING_SIZE)); |
63 | 0 | mi_assert_internal(mi_alignment_is_valid(alignment)); |
64 | |
|
65 | 0 | void* p; |
66 | 0 | size_t oversize; |
67 | 0 | mi_page_t* page; |
68 | 0 | if mi_unlikely(alignment > MI_BLOCK_ALIGNMENT_MAX) { |
69 | | // use OS allocation for very large alignment and allocate inside a huge page (dedicated segment with 1 page) |
70 | | // This can support alignments >= MI_SEGMENT_SIZE by ensuring the object can be aligned at a point in the |
71 | | // first (and single) page such that the segment info is `MI_SEGMENT_SIZE` bytes before it (so it can be found by aligning the pointer down) |
72 | 0 | if mi_unlikely(offset != 0) { |
73 | | // todo: cannot support offset alignment for very large alignments yet |
74 | 0 | _mi_error_message(EOVERFLOW, "aligned allocation with a very large alignment cannot be used with an alignment offset (size %zu, alignment %zu, offset %zu)\n", size, alignment, offset); |
75 | 0 | return NULL; |
76 | 0 | } |
77 | 0 | oversize = (size <= MI_SMALL_SIZE_MAX ? MI_SMALL_SIZE_MAX + 1 /* ensure we use generic malloc path */ : size); |
78 | | // note: no guarded as alignment > 0 |
79 | 0 | p = _mi_heap_malloc_zero_ex(heap, oversize, false, alignment, &page); // the page block size should be large enough to align in the single huge page block |
80 | | // zero afterwards as only the area from the aligned_p may be committed! |
81 | 0 | if (p == NULL) return NULL; |
82 | 0 | } |
83 | 0 | else { |
84 | | // otherwise over-allocate |
85 | 0 | mi_assert_internal(size <= (MI_MAX_ALLOC_SIZE - MI_PADDING_SIZE) && alignment <= MI_BLOCK_ALIGNMENT_MAX); |
86 | 0 | mi_assert_internal(size < SIZE_MAX - alignment); // `oversize` cannot overflow |
87 | 0 | oversize = (size < MI_MAX_ALIGN_SIZE ? MI_MAX_ALIGN_SIZE : size) + alignment - 1; // adjust for size <= 16; with size 0 and alignment 64k, we would allocate a 64k block and pointing just beyond that. |
88 | 0 | p = mi_heap_malloc_zero_no_guarded(heap, oversize, zero, &page); |
89 | 0 | if (p == NULL) return NULL; |
90 | 0 | } |
91 | 0 | mi_assert_internal(page == _mi_ptr_page(p)); |
92 | 0 | if (ppage!=NULL) { *ppage = page; } |
93 | | |
94 | | // .. and align within the allocation |
95 | 0 | const uintptr_t align_mask = alignment - 1; // for any x, `(x & align_mask) == (x % alignment)` |
96 | 0 | const uintptr_t poffset = ((uintptr_t)p + offset) & align_mask; |
97 | 0 | const uintptr_t adjust = (poffset == 0 ? 0 : alignment - poffset); |
98 | 0 | mi_assert_internal(adjust < alignment); |
99 | 0 | void* aligned_p = (void*)((uintptr_t)p + adjust); |
100 | 0 | if (aligned_p != p) { |
101 | 0 | mi_page_set_has_aligned(page, true); |
102 | | // if (pblock_size!=NULL) { |
103 | | // mi_assert_internal(*pblock_size > adjust); |
104 | | // if (*pblock_size > adjust) { *pblock_size = *pblock_size - adjust; } |
105 | | // mi_assert_internal(*pblock_size >= size); |
106 | | // } |
107 | | #if MI_GUARDED |
108 | | // set tag to aligned so mi_usable_size works with guard pages |
109 | | if (adjust >= sizeof(mi_block_t)) { |
110 | | mi_block_t* const block = (mi_block_t*)p; |
111 | | block->next = MI_BLOCK_TAG_ALIGNED; |
112 | | } |
113 | | #endif |
114 | 0 | _mi_padding_shrink(page, (mi_block_t*)p, adjust + size); |
115 | 0 | } |
116 | | // todo: expand padding if overallocated ? |
117 | |
|
118 | 0 | mi_assert_internal(mi_page_usable_block_size(page) >= adjust + size); |
119 | 0 | mi_assert_internal(((uintptr_t)aligned_p + offset) % alignment == 0); |
120 | 0 | mi_assert_internal(mi_usable_size(aligned_p)>=size); |
121 | 0 | mi_assert_internal(mi_usable_size(p) == mi_usable_size(aligned_p)+adjust); |
122 | | #if MI_DEBUG > 1 |
123 | | mi_page_t* const apage = _mi_ptr_page(aligned_p); |
124 | | void* unalign_p = _mi_page_ptr_unalign(apage, aligned_p); |
125 | | mi_assert_internal(p == unalign_p); |
126 | | #endif |
127 | | |
128 | | // now zero the block if needed |
129 | 0 | if (alignment > MI_BLOCK_ALIGNMENT_MAX) { |
130 | | // for the tracker, on huge aligned allocations only the memory from the start of the large block is defined |
131 | 0 | mi_track_mem_undefined(aligned_p, size); |
132 | 0 | if (zero) { |
133 | 0 | _mi_memzero(aligned_p, mi_usable_size(aligned_p)); // cannot be aligned due to abitrary offset... (todo: require offset to be a multiple of sizeof(void*)?) |
134 | 0 | } |
135 | 0 | } |
136 | |
|
137 | 0 | if (p != aligned_p) { |
138 | 0 | mi_track_align(p,aligned_p,adjust,mi_usable_size(aligned_p)); |
139 | | #if MI_GUARDED |
140 | | mi_track_mem_defined(p, sizeof(mi_block_t)); |
141 | | #endif |
142 | 0 | } |
143 | 0 | return aligned_p; |
144 | 0 | } |
145 | | |
146 | | // Generic primitive aligned allocation -- split out for better codegen |
147 | | static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_generic(mi_heap_t* const heap, const size_t size, const size_t alignment, const size_t offset, const bool zero, mi_page_t** ppage) mi_attr_noexcept |
148 | 0 | { |
149 | 0 | mi_assert_internal(mi_alignment_is_valid(alignment)); |
150 | | // we don't allocate more than MI_MAX_ALLOC_SIZE (see <https://sourceware.org/ml/libc-announce/2019/msg00001.html>) |
151 | 0 | if mi_unlikely(size > (MI_MAX_ALLOC_SIZE - MI_PADDING_SIZE)) { |
152 | 0 | _mi_error_message(EINVAL, "aligned allocation request is too large (size %zu, alignment %zu)\n", size, alignment); |
153 | 0 | return NULL; |
154 | 0 | } |
155 | | |
156 | | // use regular allocation if it is guaranteed to fit the alignment constraints. |
157 | | // this is important to try as the fast path in `mi_heap_malloc_zero_aligned` only works when there exist |
158 | | // a page with the right block size, and if we always use the over-alloc fallback that would never happen. |
159 | 0 | if (offset == 0 && mi_malloc_is_naturally_aligned(size,alignment)) { |
160 | 0 | void* p = mi_heap_malloc_zero_no_guarded(heap, size, zero, ppage); |
161 | 0 | mi_assert_internal(p == NULL || ((uintptr_t)p % alignment) == 0); |
162 | 0 | const bool is_aligned_or_null = (((uintptr_t)p) & (alignment-1))==0; |
163 | 0 | if mi_likely(is_aligned_or_null) { |
164 | 0 | return p; |
165 | 0 | } |
166 | 0 | else { |
167 | | // this should never happen if the `mi_malloc_is_naturally_aligned` check is correct.. |
168 | 0 | mi_assert(false); |
169 | 0 | mi_free(p); |
170 | 0 | } |
171 | 0 | } |
172 | | |
173 | | // fall back to over-allocation |
174 | 0 | return mi_heap_malloc_zero_aligned_at_overalloc(heap,size,alignment,offset,zero,ppage); |
175 | 0 | } |
176 | | |
177 | | |
178 | 0 | static mi_decl_cold mi_decl_noinline void* mi_error_bad_alignment(size_t size, size_t alignment, size_t offset) { |
179 | 0 | _mi_error_message(EINVAL, "aligned allocation requires the alignment to be a power-of-two (size %zu, alignment %zu, offset %zu)\n", size, alignment, offset); |
180 | 0 | return NULL; |
181 | 0 | } |
182 | | |
183 | | // Primitive aligned allocation |
184 | | static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t size, |
185 | | const size_t alignment, const size_t offset, const bool zero, |
186 | | mi_page_t** ppage) mi_attr_noexcept |
187 | 0 | { |
188 | | // note: we don't require `size > offset`, we just guarantee that the address at offset is aligned regardless of the allocated size. |
189 | 0 | if mi_unlikely(!mi_alignment_is_valid(alignment)) { // require power-of-two and multiple of void* (see <https://en.cppreference.com/w/c/memory/aligned_alloc#Notes>) |
190 | 0 | return mi_error_bad_alignment(size, alignment, offset); |
191 | 0 | } |
192 | | |
193 | | #if MI_GUARDED |
194 | | if (offset==0 && alignment < MI_BLOCK_ALIGNMENT_MAX && mi_heap_malloc_use_guarded(heap,size)) { |
195 | | return mi_heap_malloc_guarded_aligned(heap, size, alignment, zero, ppage); |
196 | | } |
197 | | #endif |
198 | | |
199 | | // try first if there happens to be a small block available with just the right alignment |
200 | 0 | if mi_likely(size <= MI_SMALL_SIZE_MAX && alignment <= size) { |
201 | 0 | const uintptr_t align_mask = alignment-1; // for any x, `(x & align_mask) == (x % alignment)` |
202 | 0 | const size_t padsize = size + MI_PADDING_SIZE; |
203 | 0 | mi_page_t* page = _mi_heap_get_free_small_page(heap, padsize); |
204 | 0 | if mi_likely(page->free != NULL) { |
205 | 0 | const bool is_aligned = (((uintptr_t)page->free + offset) & align_mask)==0; |
206 | 0 | if mi_likely(is_aligned) |
207 | 0 | { |
208 | 0 | if (ppage!=NULL) { *ppage = page; } |
209 | 0 | void* p = (zero ? _mi_page_malloc_zeroed(heap,page,padsize) : _mi_page_malloc(heap,page,padsize)); // call specific page malloc for better codegen |
210 | 0 | mi_assert_internal(p != NULL); |
211 | 0 | mi_assert_internal(((uintptr_t)p + offset) % alignment == 0); |
212 | 0 | mi_track_malloc(p,size,zero); |
213 | 0 | return p; |
214 | 0 | } |
215 | 0 | } |
216 | 0 | } |
217 | | |
218 | | // fallback to generic aligned allocation |
219 | 0 | return mi_heap_malloc_zero_aligned_at_generic(heap, size, alignment, offset, zero, ppage); |
220 | 0 | } |
221 | | |
222 | | |
223 | | // ------------------------------------------------------ |
224 | | // Optimized mi_heap_malloc_aligned / mi_malloc_aligned |
225 | | // ------------------------------------------------------ |
226 | | |
227 | 0 | mi_decl_nodiscard mi_decl_restrict void* mi_heap_malloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { |
228 | 0 | return mi_heap_malloc_zero_aligned_at(heap, size, alignment, offset, false, NULL); |
229 | 0 | } |
230 | | |
231 | 0 | mi_decl_nodiscard mi_decl_restrict void* mi_heap_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept { |
232 | 0 | return mi_heap_malloc_aligned_at(heap, size, alignment, 0); |
233 | 0 | } |
234 | | |
235 | | // ensure a definition is emitted |
236 | | #if defined(__cplusplus) |
237 | | void* _mi_extern_heap_malloc_aligned = (void*)&mi_heap_malloc_aligned; |
238 | | #endif |
239 | | |
240 | | // ------------------------------------------------------ |
241 | | // Aligned Allocation |
242 | | // ------------------------------------------------------ |
243 | | |
244 | 0 | mi_decl_nodiscard mi_decl_restrict void* mi_heap_zalloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { |
245 | 0 | return mi_heap_malloc_zero_aligned_at(heap, size, alignment, offset, true, NULL); |
246 | 0 | } |
247 | | |
248 | 0 | mi_decl_nodiscard mi_decl_restrict void* mi_heap_zalloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept { |
249 | 0 | return mi_heap_zalloc_aligned_at(heap, size, alignment, 0); |
250 | 0 | } |
251 | | |
252 | 0 | mi_decl_nodiscard mi_decl_restrict void* mi_heap_calloc_aligned_at(mi_heap_t* heap, size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { |
253 | 0 | size_t total; |
254 | 0 | if (mi_count_size_overflow(count, size, &total)) return NULL; |
255 | 0 | return mi_heap_zalloc_aligned_at(heap, total, alignment, offset); |
256 | 0 | } |
257 | | |
258 | 0 | mi_decl_nodiscard mi_decl_restrict void* mi_heap_calloc_aligned(mi_heap_t* heap, size_t count, size_t size, size_t alignment) mi_attr_noexcept { |
259 | 0 | return mi_heap_calloc_aligned_at(heap,count,size,alignment,0); |
260 | 0 | } |
261 | | |
262 | 0 | mi_decl_nodiscard mi_decl_restrict void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept { |
263 | 0 | return mi_heap_malloc_aligned_at(mi_prim_get_default_heap(), size, alignment, offset); |
264 | 0 | } |
265 | | |
266 | 0 | mi_decl_nodiscard mi_decl_restrict void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept { |
267 | 0 | return mi_heap_malloc_aligned(mi_prim_get_default_heap(), size, alignment); |
268 | 0 | } |
269 | | |
270 | 0 | mi_decl_nodiscard mi_decl_restrict void* mi_umalloc_aligned(size_t size, size_t alignment, size_t* pblock_size) mi_attr_noexcept { |
271 | 0 | mi_page_t* page; |
272 | 0 | void* p = mi_heap_malloc_zero_aligned_at(mi_prim_get_default_heap(), size, alignment, 0, false, &page); |
273 | 0 | if (p!=NULL && pblock_size!=NULL) { *pblock_size = mi_page_block_size(page); } |
274 | 0 | return p; |
275 | 0 | } |
276 | | |
277 | 0 | mi_decl_nodiscard mi_decl_restrict void* mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept { |
278 | 0 | return mi_heap_zalloc_aligned_at(mi_prim_get_default_heap(), size, alignment, offset); |
279 | 0 | } |
280 | | |
281 | 0 | mi_decl_nodiscard mi_decl_restrict void* mi_zalloc_aligned(size_t size, size_t alignment) mi_attr_noexcept { |
282 | 0 | return mi_heap_zalloc_aligned(mi_prim_get_default_heap(), size, alignment); |
283 | 0 | } |
284 | | |
285 | 0 | mi_decl_nodiscard mi_decl_restrict void* mi_uzalloc_aligned(size_t size, size_t alignment, size_t* pblock_size) mi_attr_noexcept { |
286 | 0 | mi_page_t* page; |
287 | 0 | void* p = mi_heap_malloc_zero_aligned_at(mi_prim_get_default_heap(), size, alignment, 0, true, &page); |
288 | 0 | if (p!=NULL && pblock_size!=NULL) { *pblock_size = mi_page_block_size(page); } |
289 | 0 | return p; |
290 | 0 | } |
291 | | |
292 | 0 | mi_decl_nodiscard mi_decl_restrict void* mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { |
293 | 0 | return mi_heap_calloc_aligned_at(mi_prim_get_default_heap(), count, size, alignment, offset); |
294 | 0 | } |
295 | | |
296 | 0 | mi_decl_nodiscard mi_decl_restrict void* mi_calloc_aligned(size_t count, size_t size, size_t alignment) mi_attr_noexcept { |
297 | 0 | return mi_heap_calloc_aligned(mi_prim_get_default_heap(), count, size, alignment); |
298 | 0 | } |
299 | | |
300 | | |
301 | | // ------------------------------------------------------ |
302 | | // Aligned re-allocation |
303 | | // ------------------------------------------------------ |
304 | | |
305 | 0 | static void* mi_heap_realloc_zero_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset, bool zero) mi_attr_noexcept { |
306 | 0 | mi_assert(mi_alignment_is_valid(alignment)); |
307 | 0 | if mi_unlikely(!mi_alignment_is_valid(alignment)) { // require power-of-two (see <https://en.cppreference.com/w/c/memory/aligned_alloc>) |
308 | 0 | return mi_error_bad_alignment(newsize,alignment,offset); |
309 | 0 | } |
310 | 0 | if (alignment <= sizeof(uintptr_t) && offset==0) return _mi_heap_realloc_zero(heap,p,newsize,zero,NULL,NULL); |
311 | 0 | if (p == NULL) return mi_heap_malloc_zero_aligned_at(heap,newsize,alignment,offset,zero,NULL); |
312 | 0 | const size_t size = mi_usable_size(p); |
313 | 0 | if (newsize <= size && newsize >= (size - (size / 2)) && (((uintptr_t)p + offset) & (alignment-1)) == 0) { |
314 | 0 | return p; // reallocation still fits, is aligned and not more than 50% waste |
315 | 0 | } |
316 | 0 | else { |
317 | | // note: we don't zero allocate upfront so we only zero initialize the expanded part (at the cost of calling mi_usable_size) |
318 | 0 | mi_page_t* newpage; |
319 | 0 | void* const newp = mi_heap_malloc_zero_aligned_at(heap,newsize,alignment,offset,false /* no zero*/, &newpage); |
320 | 0 | if (newp != NULL) { |
321 | 0 | const size_t copy_size = (newsize > size ? size : newsize); |
322 | 0 | const size_t zero_start = (copy_size >= sizeof(intptr_t) ? copy_size - sizeof(intptr_t) : 0); // also set last word in the previous allocation to zero to ensure any padding is zero-initialized |
323 | 0 | const size_t usable = _mi_page_usable_size(newpage,newp); |
324 | 0 | mi_assert_internal(usable >= newsize); // use usable for zero'ing, issue #763 |
325 | 0 | if (zero && usable > zero_start) { |
326 | | // also set last word in the previous allocation to zero to ensure any padding is zero-initialized |
327 | 0 | _mi_memzero((uint8_t*)newp + zero_start, usable - zero_start); |
328 | 0 | } |
329 | 0 | _mi_memcpy(newp, p, copy_size); // cannot be aligned due to abitrary offset... (todo: require offset to be a multiple of sizeof(void*)?) |
330 | 0 | mi_free(p); // only free if successful |
331 | 0 | } |
332 | 0 | return newp; |
333 | 0 | } |
334 | 0 | } |
335 | | |
336 | 0 | static void* mi_heap_realloc_zero_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, bool zero) mi_attr_noexcept { |
337 | 0 | mi_assert(alignment > 0); |
338 | 0 | if (alignment <= sizeof(uintptr_t)) return _mi_heap_realloc_zero(heap,p,newsize,zero,NULL,NULL); |
339 | 0 | return mi_heap_realloc_zero_aligned_at(heap,p,newsize,alignment,0,zero); |
340 | 0 | } |
341 | | |
342 | 0 | mi_decl_nodiscard void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { |
343 | 0 | return mi_heap_realloc_zero_aligned_at(heap,p,newsize,alignment,offset,false); |
344 | 0 | } |
345 | | |
346 | 0 | mi_decl_nodiscard void* mi_heap_realloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept { |
347 | 0 | return mi_heap_realloc_zero_aligned(heap,p,newsize,alignment,false); |
348 | 0 | } |
349 | | |
350 | 0 | mi_decl_nodiscard void* mi_heap_rezalloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { |
351 | 0 | return mi_heap_realloc_zero_aligned_at(heap, p, newsize, alignment, offset, true); |
352 | 0 | } |
353 | | |
354 | 0 | mi_decl_nodiscard void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept { |
355 | 0 | return mi_heap_realloc_zero_aligned(heap, p, newsize, alignment, true); |
356 | 0 | } |
357 | | |
358 | 0 | mi_decl_nodiscard void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { |
359 | 0 | size_t total; |
360 | 0 | if (mi_count_size_overflow(newcount, size, &total)) return NULL; |
361 | 0 | return mi_heap_rezalloc_aligned_at(heap, p, total, alignment, offset); |
362 | 0 | } |
363 | | |
364 | 0 | mi_decl_nodiscard void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { |
365 | 0 | size_t total; |
366 | 0 | if (mi_count_size_overflow(newcount, size, &total)) return NULL; |
367 | 0 | return mi_heap_rezalloc_aligned(heap, p, total, alignment); |
368 | 0 | } |
369 | | |
370 | 0 | mi_decl_nodiscard void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { |
371 | 0 | return mi_heap_realloc_aligned_at(mi_prim_get_default_heap(), p, newsize, alignment, offset); |
372 | 0 | } |
373 | | |
374 | 0 | mi_decl_nodiscard void* mi_realloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept { |
375 | 0 | return mi_heap_realloc_aligned(mi_prim_get_default_heap(), p, newsize, alignment); |
376 | 0 | } |
377 | | |
378 | 0 | mi_decl_nodiscard void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { |
379 | 0 | return mi_heap_rezalloc_aligned_at(mi_prim_get_default_heap(), p, newsize, alignment, offset); |
380 | 0 | } |
381 | | |
382 | 0 | mi_decl_nodiscard void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept { |
383 | 0 | return mi_heap_rezalloc_aligned(mi_prim_get_default_heap(), p, newsize, alignment); |
384 | 0 | } |
385 | | |
386 | 0 | mi_decl_nodiscard void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { |
387 | 0 | return mi_heap_recalloc_aligned_at(mi_prim_get_default_heap(), p, newcount, size, alignment, offset); |
388 | 0 | } |
389 | | |
390 | 0 | mi_decl_nodiscard void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { |
391 | 0 | return mi_heap_recalloc_aligned(mi_prim_get_default_heap(), p, newcount, size, alignment); |
392 | 0 | } |
393 | | |
394 | | |