ReactOS 0.4.16-dev-732-g2d1144a
align.cpp
Go to the documentation of this file.
1/***
2*align.c - Aligned allocation, reallocation or freeing of memory in the heap
3*
4* Copyright (c) Microsoft Corporation. All rights reserved.
5*
6*Purpose:
7* Defines the _aligned_malloc(),
8* _aligned_realloc(),
9* _aligned_recalloc(),
10* _aligned_offset_malloc(),
11* _aligned_offset_realloc(),
12* _aligned_offset_recalloc(),
13* _aligned_free(),
14* _aligned_msize() functions.
15*
16*******************************************************************************/
17
18#include <corecrt_internal.h>
19#include <malloc.h>
20
21
22
23#define IS_2_POW_N(X) ((X) != 0 && ((X) & ((X) - 1)) == 0)
24#define PTR_SZ sizeof(void *)
25
26/***
27*
28* |1|___6___|2|3|4|_________5__________|_6_|
29*
30* 1 -> Pointer to start of the block allocated by malloc.
31* 2 -> Value of 1.
32* 3 -> Gap used to get 1 aligned on sizeof(void *).
33* 4 -> Pointer to the start of data block.
34* 4+5 -> Data block.
35* 6 -> Wasted memory at rear of data block.
36* 6 -> Wasted memory.
37*
38*******************************************************************************/
39
42 );
43
45static void* _aligned_malloc_base(
46 _In_ size_t size,
48 );
49
51static size_t _aligned_msize_base(
52 _Pre_notnull_ void* block,
53 _In_ size_t alignment,
54 _In_ size_t offset
55 );
56
59 _In_ size_t size,
60 _In_ size_t alignment,
61 _In_ size_t offset
62 );
63
67 _In_ size_t size,
68 _In_ size_t alignment,
69 _In_ size_t offset
70 );
71
75 _In_ size_t count,
76 _In_ size_t size,
77 _In_ size_t alignment,
78 _In_ size_t offset
79 );
80
82static void* _aligned_realloc_base(
84 _In_ size_t size,
85 _In_ size_t alignment
86 );
87
89static void* _aligned_recalloc_base(
91 _In_ size_t count,
92 _In_ size_t size,
93 _In_ size_t alignment
94 );
95
96/***
97* void *_aligned_malloc_base(size_t size, size_t alignment)
98* - Get a block of aligned memory from the heap.
99*
100* Purpose:
101* Allocate of block of aligned memory aligned on the alignment of at least
102* size bytes from the heap and return a pointer to it.
103*
104* Entry:
105* size_t size - size of block requested
106* size_t alignment - alignment of memory (needs to be a power of 2)
107*
108* Exit:
109* Success: Pointer to memory block
110* Failure: Null, errno is set
111*
112* Exceptions:
113* Input parameters are validated. Refer to the validation section of the function.
114*
115*******************************************************************************/
116
117static __forceinline void* __cdecl _aligned_malloc_base(
118 size_t const size,
119 size_t const alignment
120 )
121{
123}
124/***
125* void *_aligned_offset_malloc_base(size_t size, size_t alignment, int offset)
126* - Get a block of memory from the heap.
127*
128* Purpose:
129* Allocate a block of memory which is shifted by offset from alignment of
130* at least size bytes from the heap and return a pointer to it.
131*
132* Entry:
133* size_t size - size of block of memory
134* size_t alignment - alignment of memory (needs to be a power of 2)
135* size_t offset - offset of memory from the alignment
136*
137* Exit:
138* Success: Pointer to memory block
139* Failure: Null, errno is set
140*
141* Exceptions:
142* Input parameters are validated. Refer to the validation section of the function.
143*
144*******************************************************************************/
145
146
147static __forceinline void* __cdecl _aligned_offset_malloc_base(
148 size_t size,
149 size_t align,
150 size_t offset
151 )
152{
153 uintptr_t ptr, retptr, gap;
154 size_t nonuser_size,block_size;
155
156 /* validation section */
158 _VALIDATE_RETURN(offset == 0 || offset < size, EINVAL, nullptr);
159
160 align = (align > PTR_SZ ? align : PTR_SZ) -1;
161
162 /* gap = number of bytes needed to round up offset to align with PTR_SZ*/
163 gap = (0 - offset)&(PTR_SZ -1);
164
165 nonuser_size = PTR_SZ +gap +align;
166 block_size = nonuser_size + size;
168
169 if ( (ptr =(uintptr_t)malloc(block_size)) == (uintptr_t)nullptr)
170 return nullptr;
171
172 retptr =((ptr +nonuser_size+offset)&~align)- offset;
173 ((uintptr_t *)(retptr - gap))[-1] = ptr;
174
175 return (void *)retptr;
176}
177
178/***
179*
180* void *_aligned_realloc_base(void * memblock, size_t size, size_t alignment)
181* - Reallocate a block of aligned memory from the heap.
182*
183* Purpose:
184* Reallocates of block of aligned memory aligned on the alignment of at
185* least size bytes from the heap and return a pointer to it. Size can be
186* either greater or less than the original size of the block.
187* The reallocation may result in moving the block as well as changing the
188* size.
189*
190* Entry:
191* void *memblock - pointer to block in the heap previously allocated by
192* call to _aligned_malloc(), _aligned_offset_malloc(),
193* _aligned_realloc() or _aligned_offset_realloc().
194* size_t size - size of block requested
195* size_t alignment - alignment of memory
196*
197* Exit:
198* Success: Pointer to re-allocated memory block
199* Failure: Null, errno is set
200*
201* Exceptions:
202* Input parameters are validated. Refer to the validation section of the function.
203*
204*******************************************************************************/
205
206static __forceinline void* __cdecl _aligned_realloc_base(
207 void* const block,
208 size_t const size,
209 size_t const alignment
210 )
211{
213}
214
215/***
216*
217* void *_aligned_recalloc_base(void * memblock, size_t count, size_t size, size_t alignment)
218* - Reallocate a block of aligned memory from the heap.
219*
220* Purpose:
221* Reallocates of block of aligned memory aligned on the alignment of at
222* least size bytes from the heap and return a pointer to it. Size can be
223* either greater or less than the original size of the block.
224* The reallocation may result in moving the block as well as changing the
225* size.
226*
227* Entry:
228* void *memblock - pointer to block in the heap previously allocated by
229* call to _aligned_malloc(), _aligned_offset_malloc(),
230* _aligned_realloc() or _aligned_offset_realloc().
231* size_t count - count of items
232* size_t size - size of item
233* size_t alignment - alignment of memory
234*
235* Exit:
236* Success: Pointer to re-allocated memory block
237* Failure: Null, errno is set
238*
239* Exceptions:
240* Input parameters are validated. Refer to the validation section of the function.
241*
242*******************************************************************************/
243
244static __forceinline void* __cdecl _aligned_recalloc_base(
245 void* const block,
246 size_t const count,
247 size_t const size,
248 size_t const alignment
249 )
250{
252}
253
254/***
255*
256* void *_aligned_offset_realloc_base (void * memblock, size_t size,
257* size_t alignment, int offset)
258* - Reallocate a block of memory from the heap.
259*
260* Purpose:
261* Reallocates a block of memory which is shifted by offset from
262* alignment of at least size bytes from the heap and return a pointer
263* to it. Size can be either greater or less than the original size of the
264* block.
265*
266* Entry:
267* void *memblock - pointer to block in the heap previously allocated by
268* call to _aligned_malloc(), _aligned_offset_malloc(),
269* _aligned_realloc() or _aligned_offset_realloc().
270* size_t size - size of block of memory
271* size_t alignment - alignment of memory
272* size_t offset - offset of memory from the alignment
273*
274* Exit:
275* Success: Pointer to re-allocated memory block
276* Failure: Null, errno is set
277*
278* Exceptions:
279* Input parameters are validated. Refer to the validation section of the function.
280*
281*******************************************************************************/
282
283static __forceinline void* __cdecl _aligned_offset_realloc_base(
284 void* block,
285 size_t size,
286 size_t align,
287 size_t offset
288 )
289{
290 uintptr_t ptr, retptr, gap, stptr, diff;
291 uintptr_t movsz, reqsz;
292 int bFree = 0;
293
294 /* special cases */
295 if (block == nullptr)
296 {
298 }
299 if (size == 0)
300 {
302 return nullptr;
303 }
304
305 /* validation section */
307 _VALIDATE_RETURN(offset == 0 || offset < size, EINVAL, nullptr);
308
309 stptr = (uintptr_t)block;
310
311 /* ptr points to the pointer to starting of the memory block */
312 stptr = (stptr & ~(PTR_SZ -1)) - PTR_SZ;
313
314 /* ptr is the pointer to the start of memory block*/
315 stptr = *((uintptr_t *)stptr);
316
317 align = (align > PTR_SZ ? align : PTR_SZ) -1;
318 /* gap = number of bytes needed to round up offset to align with PTR_SZ*/
319 gap = (0 -offset)&(PTR_SZ -1);
320
321 diff = (uintptr_t)block - stptr;
322 /* Mov size is min of the size of data available and sizw requested.
323 */
324 #pragma warning(push)
325 #pragma warning(disable: 22018) // Silence prefast about overflow/underflow
326 movsz = _msize_base((void *)stptr) - ((uintptr_t)block - stptr);
327 #pragma warning(pop)
328
329 movsz = movsz > size ? size : movsz;
330 reqsz = PTR_SZ + gap + align + size;
331
332 _VALIDATE_RETURN_NOEXC(size <= reqsz, ENOMEM, nullptr);
333
334 /* First check if we can expand(reducing or expanding using expand) data
335 * safely, ie no data is lost. eg, reducing alignment and keeping size
336 * same might result in loss of data at the tail of data block while
337 * expanding.
338 *
339 * If no, use malloc to allocate the new data and move data.
340 *
341 * If yes, expand and then check if we need to move the data.
342 */
343 if ((stptr +align +PTR_SZ +gap)<(uintptr_t)block)
344 {
345 if ((ptr = (uintptr_t)malloc(reqsz)) == (uintptr_t) nullptr)
346 return nullptr;
347 bFree = 1;
348 }
349 else
350 {
351 /* we need to save errno, which can be modified by _expand */
352 errno_t save_errno = errno;
353 if ((ptr = (uintptr_t)_expand((void *)stptr, reqsz)) == (uintptr_t)nullptr)
354 {
355 errno = save_errno;
356 if ((ptr = (uintptr_t)malloc(reqsz)) == (uintptr_t) nullptr)
357 return nullptr;
358 bFree = 1;
359 }
360 else
361 stptr = ptr;
362 }
363
364
365 if ( ptr == ((uintptr_t)block - diff)
366 && !( ((size_t)block + gap +offset) & ~(align) ))
367 {
368 return block;
369 }
370
371 retptr =((ptr +PTR_SZ +gap +align +offset)&~align)- offset;
372 memmove((void *)retptr, (void *)(stptr + diff), movsz);
373 if ( bFree)
374 free ((void *)stptr);
375
376 ((uintptr_t *)(retptr - gap))[-1] = ptr;
377 return (void *)retptr;
378}
379
380
381/***
382*
383* size_t _aligned_msize_base(void *memblock, size_t align, size_t offset)
384*
385* Purpose:
386* Computes the size of an aligned block.
387*
388* Entry:
389* void * memblock - pointer to the aligned block of memory
390*
391* Exceptions:
392* None. If memblock == nullptr 0 is returned.
393*
394*******************************************************************************/
395
396static __forceinline size_t __cdecl _aligned_msize_base(
397 void* block,
398 size_t align,
399 size_t offset
400 )
401{
402 size_t header_size = 0; /* Size of the header block */
403 size_t footer_size = 0; /* Size of the footer block */
404 size_t total_size = 0; /* total size of the allocated block */
405 size_t user_size = 0; /* size of the user block*/
406 uintptr_t gap = 0; /* keep the alignment of the data block */
407 /* after the sizeof(void*) aligned pointer */
408 /* to the beginning of the allocated block */
409 uintptr_t ptr = 0; /* computes the beginning of the allocated block */
410
411 _VALIDATE_RETURN(block != nullptr, EINVAL, static_cast<size_t>(-1));
412
413 /* HEADER SIZE + FOOTER SIZE = GAP + ALIGN + SIZE OF A POINTER*/
414 /* HEADER SIZE + USER SIZE + FOOTER SIZE = TOTAL SIZE */
415
416 ptr = (uintptr_t)block; /* ptr points to the start of the aligned memory block */
417 ptr = (ptr & ~(PTR_SZ - 1)) - PTR_SZ; /* ptr is one position behind memblock */
418 /* the value in ptr is the start of the real allocated block */
419 ptr = *((uintptr_t *)ptr); /* after dereference ptr points to the beginning of the allocated block */
420
421 total_size = _msize_base((void*)ptr);
422 header_size = (uintptr_t) block - ptr;
423 gap = (0 - offset) & (PTR_SZ - 1);
424 /* Alignment cannot be less than sizeof(void*) */
425 align = (align > PTR_SZ ? align : PTR_SZ) -1;
426 footer_size = gap + align + PTR_SZ - header_size;
427 user_size = total_size - header_size - footer_size;
428
429 return user_size;
430}
431
432/***
433*
434* void *_aligned_offset_recalloc_base (void * memblock, size_t size, size_t count, size_t alignment, int offset)
435* - Reallocate a block of memory from the heap.
436*
437* Purpose:
438* Reallocates a block of memory which is shifted by offset from
439* alignment of at least size bytes from the heap and return a pointer
440* to it. Size can be either greater or less than the original size of the
441* block.
442*
443* Entry:
444* void *memblock - pointer to block in the heap previously allocated by
445* call to _aligned_malloc(), _aligned_offset_malloc(),
446* _aligned_realloc() or _aligned_offset_realloc().
447* size_t count - count of items
448* size_t size - size of items
449* size_t alignment - alignment of memory
450* size_t offset - offset of memory from the alignment
451*
452* Exit:
453* Success: Pointer to re-allocated memory block
454* Failure: Null, errno is set
455*
456* Exceptions:
457* Input parameters are validated. Refer to the validation section of the function.
458*
459*******************************************************************************/
460
461static __forceinline void* __cdecl _aligned_offset_recalloc_base(
462 void* block,
463 size_t count,
464 size_t size,
465 size_t align,
466 size_t offset
467 )
468{
469 size_t user_size = 0; /* wanted size, passed to aligned realoc */
470 size_t start_fill = 0; /* location where aligned recalloc starts to fill with 0 */
471 /* filling must start from the end of the previous user block */
472 void * retptr = nullptr; /* result of aligned recalloc*/
473
474 /* ensure that (size * num) does not overflow */
475 if (count > 0)
476 {
478 }
479
480 user_size = size * count;
481
482 if (block != nullptr)
483 {
484 start_fill = _aligned_msize_base(block, align, offset);
485 }
486
487 retptr = _aligned_offset_realloc_base(block, user_size, align, offset);
488
489 if (retptr != nullptr)
490 {
491 if (start_fill < user_size)
492 {
493 memset ((char*)retptr + start_fill, 0, user_size - start_fill);
494 }
495 }
496 return retptr;
497}
498
499/***
500*
501* void *_aligned_free_base(void *memblock)
502* - Free the memory which was allocated using _aligned_malloc or
503* _aligned_offset_memory
504*
505* Purpose:
506* Frees the aligned memory block which was allocated using _aligned_malloc.
507*
508* Entry:
509* void * memblock - pointer to the block of memory
510*
511* Exceptions:
512* None. If memblock == nullptr we simply return without doing anything.
513*
514*******************************************************************************/
515
516static __forceinline void __cdecl _aligned_free_base(void* const block)
517{
519
520 if (block == nullptr)
521 return;
522
524
525 /* ptr points to the pointer to starting of the memory block */
526 ptr = (ptr & ~(PTR_SZ -1)) - PTR_SZ;
527
528 /* ptr is the pointer to the start of memory block*/
529 ptr = *((uintptr_t*)ptr);
530 free((void *)ptr);
531}
532
533// These functions are patchable and therefore must be marked noinline.
534// Their *_base implementations are marked __forceinline in order to
535// ensure each export is separated from each other and that there is
536// enough space in each export to host a patch.
537
538extern "C" __declspec(noinline) void __cdecl _aligned_free(void* const block)
539{
540 #ifdef _DEBUG
542 #else
544 #endif
545}
546
548 size_t const size,
549 size_t const alignment
550 )
551{
552 #ifdef _DEBUG
553 return _aligned_offset_malloc_dbg(size, alignment, 0, nullptr, 0);
554 #else
556 #endif
557}
558
559extern "C" __declspec(noinline) size_t __cdecl _aligned_msize(
560 void* const block,
561 size_t const alignment,
562 size_t const offset)
563{
564 #ifdef _DEBUG
566 #else
568 #endif
569}
570
572 size_t const size,
573 size_t const alignment,
574 size_t const offset
575 )
576{
577 #ifdef _DEBUG
578 return _aligned_offset_malloc_dbg(size, alignment, offset, nullptr, 0);
579 #else
581 #endif
582}
583
585 void* const block,
586 size_t const size,
587 size_t const alignment,
588 size_t const offset
589 )
590{
591 #ifdef _DEBUG
593 #else
595 #endif
596}
597
598extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_offset_recalloc(
599 void* const block,
600 size_t const count,
601 size_t const size,
602 size_t const alignment,
603 size_t const offset
604 )
605{
606 #ifdef _DEBUG
608 #else
610 #endif
611}
612
614 void* const block,
615 size_t const size,
616 size_t const alignment
617 )
618{
619 #ifdef _DEBUG
620 return _aligned_offset_realloc_dbg(block, size, alignment, 0, nullptr, 0);
621 #else
623 #endif
624}
625
626extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_recalloc(
627 void* const block,
628 size_t const count,
629 size_t const size,
630 size_t const alignment
631 )
632{
633 #ifdef _DEBUG
634 return _aligned_offset_recalloc_dbg(block, count, size, alignment, 0, nullptr, 0);
635 #else
637 #endif
638}
#define EINVAL
Definition: acclib.h:90
#define ENOMEM
Definition: acclib.h:84
#define __cdecl
Definition: accygwin.h:79
_In_ size_t count
Definition: align.cpp:75
static __forceinline void *__cdecl _aligned_offset_recalloc_base(void *block, size_t count, size_t size, size_t align, size_t offset)
Definition: align.cpp:461
static __forceinline void *__cdecl _aligned_malloc_base(size_t const size, size_t const alignment)
Definition: align.cpp:117
_In_ size_t size
Definition: align.cpp:67
_Check_return_ _Ret_maybenull_ _In_ size_t _In_ size_t offset
Definition: align.cpp:62
static __forceinline void *__cdecl _aligned_realloc_base(void *const block, size_t const size, size_t const alignment)
Definition: align.cpp:206
_Check_return_ _Ret_maybenull_ _In_ size_t alignment
Definition: align.cpp:48
static void _aligned_free_base(_Pre_maybenull_ _Post_invalid_ void *block)
#define PTR_SZ
Definition: align.cpp:24
static __forceinline void *__cdecl _aligned_recalloc_base(void *const block, size_t const count, size_t const size, size_t const alignment)
Definition: align.cpp:244
static __forceinline void *__cdecl _aligned_offset_malloc_base(size_t size, size_t align, size_t offset)
Definition: align.cpp:147
static __forceinline void *__cdecl _aligned_offset_realloc_base(void *block, size_t size, size_t align, size_t offset)
Definition: align.cpp:283
#define IS_2_POW_N(X)
Definition: align.cpp:23
static _Check_return_ size_t _aligned_msize_base(_Pre_notnull_ void *block, _In_ size_t alignment, _In_ size_t offset)
return
Definition: dirsup.c:529
#define _VALIDATE_RETURN(expr, errorcode, retexpr)
_Check_return_ _ACRTIMP size_t __cdecl _msize_base(_Pre_notnull_ void *_Block) _CRT_NOEXCEPT
_Check_return_ _ACRTIMP size_t __cdecl _aligned_msize(_Pre_notnull_ void *_Block, _In_ size_t _Alignment, _In_ size_t _Offset)
#define _CRTRESTRICT
Definition: corecrt.h:17
#define _aligned_offset_malloc_dbg(s, a, o, f, l)
Definition: crtdbg.h:216
#define _aligned_offset_realloc_dbg(p, s, a, o, f, l)
Definition: crtdbg.h:217
#define _aligned_free_dbg(p)
Definition: crtdbg.h:215
#define _aligned_offset_recalloc_dbg(p, c, s, a, o, f, l)
Definition: crtdbg.h:218
#define _HEAP_MAXREQ
Definition: malloc.h:24
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define noinline
Definition: types.h:64
int align(int length, int align)
Definition: dsound8.c:36
void __declspec(noinline) __cdecl _free_base(void *const block)
Definition: free_base.cpp:98
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
_CRTIMP void __cdecl _aligned_free(_Pre_maybenull_ _Post_invalid_ void *_Memory)
#define _VALIDATE_RETURN_NOEXC(expr, errorcode, retexpr)
static DWORD block_size(DWORD block)
Definition: jsutils.c:66
void * _expand(void *_ptr, size_t _size)
Definition: malloc.c:100
unsigned int uintptr_t
Definition: intrin.h:47
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
static PVOID ptr
Definition: dispmode.c:27
#define _Ret_maybenull_
Definition: no_sal2.h:328
#define _Success_(c)
Definition: no_sal2.h:84
#define _Pre_maybenull_
Definition: no_sal2.h:514
#define _Check_return_
Definition: no_sal2.h:60
#define _Post_writable_byte_size_(s)
Definition: no_sal2.h:542
#define _Pre_notnull_
Definition: no_sal2.h:516
#define _Post_invalid_
Definition: no_sal2.h:524
#define _In_
Definition: no_sal2.h:158
#define errno
Definition: errno.h:18
void *CDECL _aligned_offset_malloc(size_t size, size_t alignment, size_t offset)
Definition: heap.c:581
void *CDECL _aligned_offset_realloc(void *memblock, size_t size, size_t alignment, size_t offset)
Definition: heap.c:633
void *CDECL _aligned_malloc(size_t size, size_t alignment)
Definition: heap.c:624
void *CDECL _aligned_realloc(void *memblock, size_t size, size_t alignment)
Definition: heap.c:748
#define memset(x, y, z)
Definition: compat.h:39
int errno_t
Definition: corecrt.h:615
#define _aligned_msize_dbg(p, a, o)
Definition: crtdbg.h:260
static unsigned int block
Definition: xmlmemory.c:101
#define const
Definition: zconf.h:233