diff --git a/Userland/Libraries/LibC/malloc.cpp b/Userland/Libraries/LibC/malloc.cpp index 8819f020db..e4268fb76c 100644 --- a/Userland/Libraries/LibC/malloc.cpp +++ b/Userland/Libraries/LibC/malloc.cpp @@ -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::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; diff --git a/Userland/Libraries/LibC/stdlib.h b/Userland/Libraries/LibC/stdlib.h index 8d624a6aa8..56f067d8c1 100644 --- a/Userland/Libraries/LibC/stdlib.h +++ b/Userland/Libraries/LibC/stdlib.h @@ -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*);