mirror of
https://github.com/SerenityOS/serenity
synced 2024-09-06 17:06:31 +00:00
LibC: Implement _aligned_malloc and _aligned_free
C++17 introduced aligned versions of `new` and `delete`, which are automatically called by the compiler when allocating over-aligned objects. As with the regular allocator functions, these are generally thin wrappers around LibC. We did not have support for aligned allocations in LibC, so this was not possible. While libstdc++ has a fallback implementation, libc++ does not, so the aligned allocation function was disabled internally. This made building the LLVM port with Clang impossible. Note that while the Microsoft docs say that aligned_malloc and _aligned_free are declared in `malloc.h`, libc++ doesn't #include that file, but instead relies on the definition coming from `stdlib.h`. Therefore, I chose to declare it in that file instead of creating a new LibC header. I chose not to implement the more Unix-y `memalign`, `posix_memalign`, or the C11 `aligned_alloc`, because that would require us to significantly alter the memory allocator's internals. See the comment in malloc.cpp.
This commit is contained in:
parent
069e64efd1
commit
40e7ac9967
|
@ -425,6 +425,37 @@ void* malloc(size_t size)
|
|||
return ptr;
|
||||
}
|
||||
|
||||
// This is a Microsoft extension, and is not found on other Unix-like systems.
|
||||
// FIXME: Implement aligned_alloc() instead
|
||||
//
|
||||
// This is used in libc++ to implement C++17 aligned new/delete.
|
||||
//
|
||||
// Both Unix-y alternatives to _aligned_malloc(), the C11 aligned_alloc() and
|
||||
// posix_memalign() say that the resulting pointer can be deallocated with
|
||||
// regular free(), which means that the allocator has to keep track of the
|
||||
// requested alignments. By contrast, _aligned_malloc() is paired with
|
||||
// _aligned_free(), so it can be easily implemented on top of malloc().
|
||||
void* _aligned_malloc(size_t size, size_t alignment)
|
||||
{
|
||||
if (__builtin_popcount(alignment) != 1) {
|
||||
errno = EINVAL;
|
||||
return nullptr;
|
||||
}
|
||||
alignment = max(alignment, sizeof(void*));
|
||||
if (Checked<size_t>::addition_would_overflow(size, alignment)) {
|
||||
errno = ENOMEM;
|
||||
return nullptr;
|
||||
}
|
||||
void* ptr = malloc(size + alignment);
|
||||
if (!ptr) {
|
||||
errno = ENOMEM;
|
||||
return nullptr;
|
||||
}
|
||||
auto aligned_ptr = (void*)(((FlatPtr)ptr + alignment) & ~(alignment - 1));
|
||||
((void**)aligned_ptr)[-1] = ptr;
|
||||
return aligned_ptr;
|
||||
}
|
||||
|
||||
void free(void* ptr)
|
||||
{
|
||||
MemoryAuditingSuppressor suppressor;
|
||||
|
@ -434,6 +465,12 @@ void free(void* ptr)
|
|||
free_impl(ptr);
|
||||
}
|
||||
|
||||
void _aligned_free(void* ptr)
|
||||
{
|
||||
if (ptr)
|
||||
free(((void**)ptr)[-1]);
|
||||
}
|
||||
|
||||
void* calloc(size_t count, size_t size)
|
||||
{
|
||||
MemoryAuditingSuppressor suppressor;
|
||||
|
|
|
@ -25,6 +25,8 @@ size_t malloc_good_size(size_t);
|
|||
void serenity_dump_malloc_stats(void);
|
||||
void free(void*);
|
||||
__attribute__((alloc_size(2))) void* realloc(void* ptr, size_t);
|
||||
__attribute__((malloc, alloc_size(1), alloc_align(2))) void* _aligned_malloc(size_t size, size_t alignment);
|
||||
void _aligned_free(void* memblock);
|
||||
char* getenv(const char* name);
|
||||
char* secure_getenv(const char* name);
|
||||
int putenv(char*);
|
||||
|
|
Loading…
Reference in a new issue