1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef _LIBCPP___MEMORY_ALIGNED_ALLOC_H 10 #define _LIBCPP___MEMORY_ALIGNED_ALLOC_H 11 12 #include <__config> 13 #include <cstdlib> 14 15 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 16 # pragma GCC system_header 17 #endif 18 19 _LIBCPP_BEGIN_NAMESPACE_STD 20 21 #if _LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION 22 23 // Low-level helpers to call the aligned allocation and deallocation functions 24 // on the target platform. This is used to implement libc++'s own memory 25 // allocation routines -- if you need to allocate memory inside the library, 26 // chances are that you want to use `__libcpp_allocate` instead. 27 // 28 // Returns the allocated memory, or `nullptr` on failure. 29 inline _LIBCPP_HIDE_FROM_ABI void* __libcpp_aligned_alloc(std::size_t __alignment, std::size_t __size) { 30 # if defined(_LIBCPP_MSVCRT_LIKE) 31 return ::_aligned_malloc(__size, __alignment); 32 # elif _LIBCPP_STD_VER >= 17 && _LIBCPP_HAS_C11_ALIGNED_ALLOC 33 // aligned_alloc() requires that __size is a multiple of __alignment, 34 // but for C++ [new.delete.general], only states "if the value of an 35 // alignment argument passed to any of these functions is not a valid 36 // alignment value, the behavior is undefined". 37 // To handle calls such as ::operator new(1, std::align_val_t(128)), we 38 // round __size up to the next multiple of __alignment. 39 size_t __rounded_size = (__size + __alignment - 1) & ~(__alignment - 1); 40 // Rounding up could have wrapped around to zero, so we have to add another 41 // max() ternary to the actual call site to avoid succeeded in that case. 42 return ::aligned_alloc(__alignment, __size > __rounded_size ? __size : __rounded_size); 43 # else 44 void* __result = nullptr; 45 (void)::posix_memalign(&__result, __alignment, __size); 46 // If posix_memalign fails, __result is unmodified so we still return `nullptr`. 47 return __result; 48 # endif 49 } 50 51 inline _LIBCPP_HIDE_FROM_ABI void __libcpp_aligned_free(void* __ptr) { 52 # if defined(_LIBCPP_MSVCRT_LIKE) 53 ::_aligned_free(__ptr); 54 # else 55 ::free(__ptr); 56 # endif 57 } 58 59 #endif // _LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION 60 61 _LIBCPP_END_NAMESPACE_STD 62 63 #endif // _LIBCPP___MEMORY_ALIGNED_ALLOC_H 64