Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639/****align.c - Aligned allocation, reallocation or freeing of memory in the heap** Copyright (c) Microsoft Corporation. All rights reserved.**Purpose:* Defines the _aligned_malloc(),* _aligned_realloc(),* _aligned_recalloc(),* _aligned_offset_malloc(),* _aligned_offset_realloc(),* _aligned_offset_recalloc(),* _aligned_free(),* _aligned_msize() functions.********************************************************************************/
#include <corecrt_internal.h>#include <malloc.h>
#define IS_2_POW_N(X) ((X) != 0 && ((X) & ((X) - 1)) == 0)#define PTR_SZ sizeof(void *)
/***** |1|___6___|2|3|4|_________5__________|_6_|** 1 -> Pointer to start of the block allocated by malloc.* 2 -> Value of 1.* 3 -> Gap used to get 1 aligned on sizeof(void *).* 4 -> Pointer to the start of data block.* 4+5 -> Data block.* 6 -> Wasted memory at rear of data block.* 6 -> Wasted memory.********************************************************************************/
static void _aligned_free_base( _Pre_maybenull_ _Post_invalid_ void* block );
_Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size)static void* _aligned_malloc_base( _In_ size_t size, _In_ size_t alignment );
_Check_return_static size_t _aligned_msize_base( _Pre_notnull_ void* block, _In_ size_t alignment, _In_ size_t offset );
_Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size)static void* _aligned_offset_malloc_base( _In_ size_t size, _In_ size_t alignment, _In_ size_t offset );
_Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size)static void* _aligned_offset_realloc_base( _Pre_maybenull_ _Post_invalid_ void* block, _In_ size_t size, _In_ size_t alignment, _In_ size_t offset );
_Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size * count)static void* _aligned_offset_recalloc_base( _Pre_maybenull_ _Post_invalid_ void* block, _In_ size_t count, _In_ size_t size, _In_ size_t alignment, _In_ size_t offset );
_Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size)static void* _aligned_realloc_base( _Pre_maybenull_ _Post_invalid_ void* block, _In_ size_t size, _In_ size_t alignment );
_Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size * count)static void* _aligned_recalloc_base( _Pre_maybenull_ _Post_invalid_ void* block, _In_ size_t count, _In_ size_t size, _In_ size_t alignment );
/**** void *_aligned_malloc_base(size_t size, size_t alignment)* - Get a block of aligned memory from the heap.** Purpose:* Allocate of block of aligned memory aligned on the alignment of at least* size bytes from the heap and return a pointer to it.** Entry:* size_t size - size of block requested* size_t alignment - alignment of memory (needs to be a power of 2)** Exit:* Success: Pointer to memory block* Failure: Null, errno is set** Exceptions:* Input parameters are validated. Refer to the validation section of the function.********************************************************************************/
static __forceinline void* __cdecl _aligned_malloc_base( size_t const size, size_t const alignment ){ return _aligned_offset_malloc_base(size, alignment, 0);}/**** void *_aligned_offset_malloc_base(size_t size, size_t alignment, int offset)* - Get a block of memory from the heap.** Purpose:* Allocate a block of memory which is shifted by offset from alignment of* at least size bytes from the heap and return a pointer to it.** Entry:* size_t size - size of block of memory* size_t alignment - alignment of memory (needs to be a power of 2)* size_t offset - offset of memory from the alignment** Exit:* Success: Pointer to memory block* Failure: Null, errno is set** Exceptions:* Input parameters are validated. Refer to the validation section of the function.********************************************************************************/
static __forceinline void* __cdecl _aligned_offset_malloc_base( size_t size, size_t align, size_t offset ){ uintptr_t ptr, retptr, gap; size_t nonuser_size,block_size;
/* validation section */ _VALIDATE_RETURN(IS_2_POW_N(align), EINVAL, nullptr); _VALIDATE_RETURN(offset == 0 || offset < size, EINVAL, nullptr);
align = (align > PTR_SZ ? align : PTR_SZ) -1;
/* gap = number of bytes needed to round up offset to align with PTR_SZ*/ gap = (0 - offset)&(PTR_SZ -1);
nonuser_size = PTR_SZ +gap +align; block_size = nonuser_size + size; _VALIDATE_RETURN_NOEXC(size <= block_size, ENOMEM, nullptr)
if ( (ptr =(uintptr_t)malloc(block_size)) == (uintptr_t)nullptr) return nullptr;
retptr =((ptr +nonuser_size+offset)&~align)- offset; ((uintptr_t *)(retptr - gap))[-1] = ptr;
return (void *)retptr;}
/***** void *_aligned_realloc_base(void * memblock, size_t size, size_t alignment)* - Reallocate a block of aligned memory from the heap.** Purpose:* Reallocates of block of aligned memory aligned on the alignment of at* least size bytes from the heap and return a pointer to it. Size can be* either greater or less than the original size of the block.* The reallocation may result in moving the block as well as changing the* size.** Entry:* void *memblock - pointer to block in the heap previously allocated by* call to _aligned_malloc(), _aligned_offset_malloc(),* _aligned_realloc() or _aligned_offset_realloc().* size_t size - size of block requested* size_t alignment - alignment of memory** Exit:* Success: Pointer to re-allocated memory block* Failure: Null, errno is set** Exceptions:* Input parameters are validated. Refer to the validation section of the function.********************************************************************************/
static __forceinline void* __cdecl _aligned_realloc_base( void* const block, size_t const size, size_t const alignment ){ return _aligned_offset_realloc_base(block, size, alignment, 0);}
/***** void *_aligned_recalloc_base(void * memblock, size_t count, size_t size, size_t alignment)* - Reallocate a block of aligned memory from the heap.** Purpose:* Reallocates of block of aligned memory aligned on the alignment of at* least size bytes from the heap and return a pointer to it. Size can be* either greater or less than the original size of the block.* The reallocation may result in moving the block as well as changing the* size.** Entry:* void *memblock - pointer to block in the heap previously allocated by* call to _aligned_malloc(), _aligned_offset_malloc(),* _aligned_realloc() or _aligned_offset_realloc().* size_t count - count of items* size_t size - size of item* size_t alignment - alignment of memory** Exit:* Success: Pointer to re-allocated memory block* Failure: Null, errno is set** Exceptions:* Input parameters are validated. Refer to the validation section of the function.********************************************************************************/
static __forceinline void* __cdecl _aligned_recalloc_base( void* const block, size_t const count, size_t const size, size_t const alignment ){ return _aligned_offset_recalloc_base(block, count, size, alignment, 0);}
/***** void *_aligned_offset_realloc_base (void * memblock, size_t size,* size_t alignment, int offset)* - Reallocate a block of memory from the heap.** Purpose:* Reallocates a block of memory which is shifted by offset from* alignment of at least size bytes from the heap and return a pointer* to it. Size can be either greater or less than the original size of the* block.** Entry:* void *memblock - pointer to block in the heap previously allocated by* call to _aligned_malloc(), _aligned_offset_malloc(),* _aligned_realloc() or _aligned_offset_realloc().* size_t size - size of block of memory* size_t alignment - alignment of memory* size_t offset - offset of memory from the alignment** Exit:* Success: Pointer to re-allocated memory block* Failure: Null, errno is set** Exceptions:* Input parameters are validated. Refer to the validation section of the function.********************************************************************************/
static __forceinline void* __cdecl _aligned_offset_realloc_base( void* block, size_t size, size_t align, size_t offset ){ uintptr_t ptr, retptr, gap, stptr, diff; uintptr_t movsz, reqsz; int bFree = 0;
/* special cases */ if (block == nullptr) { return _aligned_offset_malloc_base(size, align, offset); } if (size == 0) { _aligned_free_base(block); return nullptr; }
/* validation section */ _VALIDATE_RETURN(IS_2_POW_N(align), EINVAL, nullptr); _VALIDATE_RETURN(offset == 0 || offset < size, EINVAL, nullptr);
stptr = (uintptr_t)block;
/* ptr points to the pointer to starting of the memory block */ stptr = (stptr & ~(PTR_SZ -1)) - PTR_SZ;
/* ptr is the pointer to the start of memory block*/ stptr = *((uintptr_t *)stptr);
align = (align > PTR_SZ ? align : PTR_SZ) -1; /* gap = number of bytes needed to round up offset to align with PTR_SZ*/ gap = (0 -offset)&(PTR_SZ -1);
diff = (uintptr_t)block - stptr; /* Mov size is min of the size of data available and sizw requested. */ #pragma warning(push) #pragma warning(disable: 22018) // Silence prefast about overflow/underflow movsz = _msize_base((void *)stptr) - ((uintptr_t)block - stptr); #pragma warning(pop)
movsz = movsz > size ? size : movsz; reqsz = PTR_SZ + gap + align + size;
_VALIDATE_RETURN_NOEXC(size <= reqsz, ENOMEM, nullptr);
/* First check if we can expand(reducing or expanding using expand) data * safely, ie no data is lost. eg, reducing alignment and keeping size * same might result in loss of data at the tail of data block while * expanding. * * If no, use malloc to allocate the new data and move data. * * If yes, expand and then check if we need to move the data. */ if ((stptr +align +PTR_SZ +gap)<(uintptr_t)block) { if ((ptr = (uintptr_t)malloc(reqsz)) == (uintptr_t) nullptr) return nullptr; bFree = 1; } else { /* we need to save errno, which can be modified by _expand */ errno_t save_errno = errno; if ((ptr = (uintptr_t)_expand((void *)stptr, reqsz)) == (uintptr_t)nullptr) { errno = save_errno; if ((ptr = (uintptr_t)malloc(reqsz)) == (uintptr_t) nullptr) return nullptr; bFree = 1; } else stptr = ptr; }
if ( ptr == ((uintptr_t)block - diff) && !( ((size_t)block + gap +offset) & ~(align) )) { return block; }
retptr =((ptr +PTR_SZ +gap +align +offset)&~align)- offset; memmove((void *)retptr, (void *)(stptr + diff), movsz); if ( bFree) free ((void *)stptr);
((uintptr_t *)(retptr - gap))[-1] = ptr; return (void *)retptr;}
/***** size_t _aligned_msize_base(void *memblock, size_t align, size_t offset)** Purpose:* Computes the size of an aligned block.** Entry:* void * memblock - pointer to the aligned block of memory** Exceptions:* None. If memblock == nullptr 0 is returned.********************************************************************************/
static __forceinline size_t __cdecl _aligned_msize_base( void* block, size_t align, size_t offset ){ size_t header_size = 0; /* Size of the header block */ size_t footer_size = 0; /* Size of the footer block */ size_t total_size = 0; /* total size of the allocated block */ size_t user_size = 0; /* size of the user block*/ uintptr_t gap = 0; /* keep the alignment of the data block */ /* after the sizeof(void*) aligned pointer */ /* to the beginning of the allocated block */ uintptr_t ptr = 0; /* computes the beginning of the allocated block */
_VALIDATE_RETURN(block != nullptr, EINVAL, static_cast<size_t>(-1));
/* HEADER SIZE + FOOTER SIZE = GAP + ALIGN + SIZE OF A POINTER*/ /* HEADER SIZE + USER SIZE + FOOTER SIZE = TOTAL SIZE */
ptr = (uintptr_t)block; /* ptr points to the start of the aligned memory block */ ptr = (ptr & ~(PTR_SZ - 1)) - PTR_SZ; /* ptr is one position behind memblock */ /* the value in ptr is the start of the real allocated block */ ptr = *((uintptr_t *)ptr); /* after dereference ptr points to the beginning of the allocated block */
total_size = _msize_base((void*)ptr); header_size = (uintptr_t) block - ptr; gap = (0 - offset) & (PTR_SZ - 1); /* Alignment cannot be less than sizeof(void*) */ align = (align > PTR_SZ ? align : PTR_SZ) -1; footer_size = gap + align + PTR_SZ - header_size; user_size = total_size - header_size - footer_size;
return user_size;}
/***** void *_aligned_offset_recalloc_base (void * memblock, size_t size, size_t count, size_t alignment, int offset)* - Reallocate a block of memory from the heap.** Purpose:* Reallocates a block of memory which is shifted by offset from* alignment of at least size bytes from the heap and return a pointer* to it. Size can be either greater or less than the original size of the* block.** Entry:* void *memblock - pointer to block in the heap previously allocated by* call to _aligned_malloc(), _aligned_offset_malloc(),* _aligned_realloc() or _aligned_offset_realloc().* size_t count - count of items* size_t size - size of items* size_t alignment - alignment of memory* size_t offset - offset of memory from the alignment** Exit:* Success: Pointer to re-allocated memory block* Failure: Null, errno is set** Exceptions:* Input parameters are validated. Refer to the validation section of the function.********************************************************************************/
static __forceinline void* __cdecl _aligned_offset_recalloc_base( void* block, size_t count, size_t size, size_t align, size_t offset ){ size_t user_size = 0; /* wanted size, passed to aligned realoc */ size_t start_fill = 0; /* location where aligned recalloc starts to fill with 0 */ /* filling must start from the end of the previous user block */ void * retptr = nullptr; /* result of aligned recalloc*/
/* ensure that (size * num) does not overflow */ if (count > 0) { _VALIDATE_RETURN_NOEXC((_HEAP_MAXREQ / count) >= size, ENOMEM, nullptr); }
user_size = size * count;
if (block != nullptr) { start_fill = _aligned_msize_base(block, align, offset); }
retptr = _aligned_offset_realloc_base(block, user_size, align, offset);
if (retptr != nullptr) { if (start_fill < user_size) { memset ((char*)retptr + start_fill, 0, user_size - start_fill); } } return retptr;}
/***** void *_aligned_free_base(void *memblock)* - Free the memory which was allocated using _aligned_malloc or* _aligned_offset_memory** Purpose:* Frees the aligned memory block which was allocated using _aligned_malloc.** Entry:* void * memblock - pointer to the block of memory** Exceptions:* None. If memblock == nullptr we simply return without doing anything.********************************************************************************/
static __forceinline void __cdecl _aligned_free_base(void* const block){ uintptr_t ptr;
if (block == nullptr) return;
ptr = (uintptr_t)block;
/* ptr points to the pointer to starting of the memory block */ ptr = (ptr & ~(PTR_SZ -1)) - PTR_SZ;
/* ptr is the pointer to the start of memory block*/ ptr = *((uintptr_t*)ptr); free((void *)ptr);}
// These functions are patchable and therefore must be marked noinline.// Their *_base implementations are marked __forceinline in order to// ensure each export is separated from each other and that there is// enough space in each export to host a patch.
extern "C" __declspec(noinline) void __cdecl _aligned_free(void* const block){ #ifdef _DEBUG _aligned_free_dbg(block); #else _aligned_free_base(block); #endif}
extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_malloc( size_t const size, size_t const alignment ){ #ifdef _DEBUG return _aligned_offset_malloc_dbg(size, alignment, 0, nullptr, 0); #else return _aligned_malloc_base(size, alignment); #endif}
extern "C" __declspec(noinline) size_t __cdecl _aligned_msize( void* const block, size_t const alignment, size_t const offset){ #ifdef _DEBUG return _aligned_msize_dbg(block, alignment, offset); #else return _aligned_msize_base(block, alignment, offset); #endif}
extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_offset_malloc( size_t const size, size_t const alignment, size_t const offset ){ #ifdef _DEBUG return _aligned_offset_malloc_dbg(size, alignment, offset, nullptr, 0); #else return _aligned_offset_malloc_base(size, alignment, offset); #endif}
extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_offset_realloc( void* const block, size_t const size, size_t const alignment, size_t const offset ){ #ifdef _DEBUG return _aligned_offset_realloc_dbg(block, size, alignment, offset, nullptr, 0); #else return _aligned_offset_realloc_base(block, size, alignment, offset); #endif}
extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_offset_recalloc( void* const block, size_t const count, size_t const size, size_t const alignment, size_t const offset ){ #ifdef _DEBUG return _aligned_offset_recalloc_dbg(block, count, size, alignment, offset, nullptr, 0); #else return _aligned_offset_recalloc_base(block, count, size, alignment, offset); #endif}
extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_realloc( void* const block, size_t const size, size_t const alignment ){ #ifdef _DEBUG return _aligned_offset_realloc_dbg(block, size, alignment, 0, nullptr, 0); #else return _aligned_realloc_base(block, size, alignment); #endif}
extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_recalloc( void* const block, size_t const count, size_t const size, size_t const alignment ){ #ifdef _DEBUG return _aligned_offset_recalloc_dbg(block, count, size, alignment, 0, nullptr, 0); #else return _aligned_recalloc_base(block, count, size, alignment); #endif}