21#include <winpr/config.h>
24#include <winpr/debug.h>
28#if !defined(_WIN32) || (defined(__MINGW32__) && !defined(_UCRT))
33#define WINPR_ALIGNED_MEM_SIGNATURE 0x0BA0BAB
35#define WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(_memptr) \
36 (WINPR_ALIGNED_MEM*)(((size_t)(((BYTE*)(_memptr)) - sizeof(WINPR_ALIGNED_MEM))))
41#define TAG WINPR_TAG("crt")
43struct winpr_aligned_mem
49typedef struct winpr_aligned_mem WINPR_ALIGNED_MEM;
51#define get_aligned_mem_block(ptr) get_aligned_mem_block_((ptr), __func__, __FILE__, __LINE__)
54static inline WINPR_ALIGNED_MEM* get_aligned_mem_block_(
void* memblock,
const char* fkt,
55 const char* file,
size_t line)
60 WINPR_ALIGNED_MEM* pMem = WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(memblock);
61 if (pMem->sig != WINPR_ALIGNED_MEM_SIGNATURE)
63 const DWORD level = WLOG_ERROR;
64 wLog* log = WLog_Get(TAG);
65 if (WLog_IsLevelActive(log, level))
67 WLog_PrintTextMessage(log, level, line, file, fkt,
68 "memory block was not allocated by _aligned_malloc!");
69 winpr_log_backtrace_ex(log, WLOG_ERROR, 20);
77void* winpr_aligned_malloc(
size_t size,
size_t alignment)
79 return winpr_aligned_offset_malloc(size, alignment, 0);
82void* winpr_aligned_calloc(
size_t count,
size_t size,
size_t alignment)
84 return winpr_aligned_recalloc(
nullptr, count, size, alignment);
87void* winpr_aligned_realloc(
void* memblock,
size_t size,
size_t alignment)
89 return winpr_aligned_offset_realloc(memblock, size, alignment, 0);
92void* winpr_aligned_recalloc(
void* memblock,
size_t num,
size_t size,
size_t alignment)
94 return winpr_aligned_offset_recalloc(memblock, num, size, alignment, 0);
97void* winpr_aligned_offset_malloc(
size_t size,
size_t alignment,
size_t offset)
100 size_t alignsize = 0;
101 uintptr_t basesize = 0;
102 void* base =
nullptr;
103 void* memblock =
nullptr;
104 WINPR_ALIGNED_MEM* pMem =
nullptr;
107 if (alignment % 2 == 1)
115 if (alignment <
sizeof(
void*))
116 alignment =
sizeof(
void*);
118 if (alignment > SIZE_MAX -
sizeof(WINPR_ALIGNED_MEM))
121 header =
sizeof(WINPR_ALIGNED_MEM) + alignment;
123 if (size > SIZE_MAX - header)
126 alignsize = size + header;
128#if defined(_ISOC11_SOURCE)
129 base = aligned_alloc(alignment, alignsize);
130#elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) || (_XOPEN_SOURCE >= 600)
131 if (posix_memalign(&base, alignment, alignsize) != 0)
134 base = malloc(alignsize);
139 basesize = (uintptr_t)base;
141 if ((offset > UINTPTR_MAX) || (header > UINTPTR_MAX - offset) ||
142 (basesize > UINTPTR_MAX - header - offset))
148 memblock = (
void*)(((basesize + header + offset) & ~(alignment - 1)) - offset);
149 pMem = WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(memblock);
150 pMem->sig = WINPR_ALIGNED_MEM_SIGNATURE;
151 pMem->base_addr = base;
156void* winpr_aligned_offset_realloc(
void* memblock,
size_t size,
size_t alignment,
size_t offset)
161 return winpr_aligned_offset_malloc(size, alignment, offset);
163 WINPR_ALIGNED_MEM* pMem = get_aligned_mem_block(memblock);
169 winpr_aligned_free(memblock);
173 void* newMemblock = winpr_aligned_offset_malloc(size, alignment, offset);
177 WINPR_ALIGNED_MEM* pNewMem = WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(newMemblock);
178 copySize = (pNewMem->size < pMem->size) ? pNewMem->size : pMem->size;
179 CopyMemory(newMemblock, memblock, copySize);
180 winpr_aligned_free(memblock);
184WINPR_ATTR_NODISCARD
static inline size_t cMIN(
size_t a,
size_t b)
191void* winpr_aligned_offset_recalloc(
void* memblock,
size_t num,
size_t size,
size_t alignment,
194 char* newMemblock =
nullptr;
195 WINPR_ALIGNED_MEM* pNewMem =
nullptr;
199 newMemblock = winpr_aligned_offset_malloc(size * num, alignment, offset);
203 pNewMem = WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(newMemblock);
204 ZeroMemory(newMemblock, pNewMem->size);
210 WINPR_ALIGNED_MEM* pMem = get_aligned_mem_block(memblock);
214 if ((num == 0) || (size == 0))
217 if (pMem->size > (1ull * num * size) + alignment)
220 newMemblock = winpr_aligned_offset_malloc(size * num, alignment, offset);
225 pNewMem = WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(newMemblock);
227 const size_t csize = cMIN(pMem->size, pNewMem->size);
228 memcpy(newMemblock, memblock, csize);
229 ZeroMemory(newMemblock + csize, pNewMem->size - csize);
232 winpr_aligned_free(memblock);
236size_t winpr_aligned_msize(
void* memblock, WINPR_ATTR_UNUSED
size_t alignment,
237 WINPR_ATTR_UNUSED
size_t offset)
239 WINPR_ALIGNED_MEM* pMem = get_aligned_mem_block(memblock);
247void winpr_aligned_free(
void* memblock)
249 WINPR_ALIGNED_MEM* pMem = get_aligned_mem_block(memblock);
254 free(pMem->base_addr);