From 0f4bd21805780f45ccb443236b6fc0e3e1a10d05 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Thu, 13 Feb 2020 19:44:24 +0100 Subject: [PATCH] Use Use C11 aligned_alloc See https://github.com/gnuradio/volk/pull/334 --- .../volk_gnsssdr/CMakeLists.txt | 19 ++- .../volk_gnsssdr/apps/CMakeLists.txt | 6 +- .../apps/volk_gnsssdr-config-info.cc | 8 +- .../volk_gnsssdr/volk_gnsssdr_malloc.h | 30 +++-- .../volk_gnsssdr/lib/CMakeLists.txt | 13 +- .../volk_gnsssdr/lib/volk_gnsssdr_malloc.c | 111 ++++++------------ 6 files changed, 80 insertions(+), 107 deletions(-) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt index 2082d35d6..621759afa 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt @@ -249,7 +249,24 @@ if(NOT ${FILESYSTEM_FOUND}) endif() endif() -# Orc + +######################################################################## +# check for aligned_alloc, since some compilers lack this C11 feature. +# For Apple-clang use `posix_memalign` +# For MSVC use `_aligned_malloc`. +######################################################################## +include(CheckSymbolExists) +if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")) + check_symbol_exists(aligned_alloc stdlib.h USE_ALIGNED_ALLOC) +endif() +if(NOT USE_ALIGNED_ALLOC) + check_symbol_exists(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN) +endif() + + +######################################################################## +# Check if Orc is available +######################################################################## option(ENABLE_ORC "Enable Orc" TRUE) if(ENABLE_ORC) find_package(ORC) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/CMakeLists.txt b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/CMakeLists.txt index 24c64f98b..1551fac8e 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/CMakeLists.txt +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/CMakeLists.txt @@ -17,7 +17,6 @@ else() set(orc_lib "") endif() - # allow 'large' files in 32 bit builds if(UNIX) add_definitions(-D_LARGEFILE_SOURCE @@ -26,6 +25,11 @@ if(UNIX) ) endif() +# POSIX_MEMALIGN: If we have to fall back to `posix_memalign`. +if(HAVE_POSIX_MEMALIGN) + message(STATUS "Use `posix_memalign` for aligned malloc!") + add_definitions(-DHAVE_POSIX_MEMALIGN) +endif(HAVE_POSIX_MEMALIGN) # MAKE volk_gnsssdr_profile add_executable(volk_gnsssdr_profile diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/volk_gnsssdr-config-info.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/volk_gnsssdr-config-info.cc index 6cab4c2c5..67c287713 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/volk_gnsssdr-config-info.cc +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/volk_gnsssdr-config-info.cc @@ -28,12 +28,12 @@ void print_malloc() // You don't want to change the volk_malloc code, so just copy the if/else // structure from there and give an explanation for the implementations std::cout << "Used malloc implementation: "; -#if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || HAVE_POSIX_MEMALIGN +#if HAVE_POSIX_MEMALIGN std::cout << "posix_memalign" << std::endl; -#elif _MSC_VER >= 1400 - std::cout << "aligned_malloc" << std::endl; +#elif defined(_MSC_VER) + std::cout << "_aligned_malloc" << std::endl; #else - std::cout << "No standard handler available, using own implementation." << std::endl; + std::cout << "C11 aligned_alloc." << std::endl; #endif } diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/include/volk_gnsssdr/volk_gnsssdr_malloc.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/include/volk_gnsssdr/volk_gnsssdr_malloc.h index 34b551f3a..a14b498e3 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/include/volk_gnsssdr/volk_gnsssdr_malloc.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/include/volk_gnsssdr/volk_gnsssdr_malloc.h @@ -25,22 +25,20 @@ __VOLK_DECL_BEGIN * \brief Allocate \p size bytes of data aligned to \p alignment. * * \details - * Because we don't have a standard method to allocate buffers in - * memory that are guaranteed to be on an alignment, VOLK handles this - * itself. The volk_gnsssdr_malloc function behaves like malloc in that it - * returns a pointer to the allocated memory. However, it also takes - * in an alignment specification, which is usually something like 16 or - * 32 to ensure that the aligned memory is located on a particular - * byte boundary for use with SIMD. + * We use C11 and want to rely on C11 library features, + * namely we use `aligned_alloc` to allocate aligned memory. + * see: https://en.cppreference.com/w/c/memory/aligned_alloc * - * Internally, the volk_gnsssdr_malloc first checks if the compiler is C11 - * compliant and uses the new aligned_alloc method. If not, it checks - * if the system is POSIX compliant and uses posix_memalign. If that - * fails, volk_gnsssdr_malloc handles the memory allocation and alignment - * internally. + * Not all platforms support this feature. + * For Apple Clang, we fall back to `posix_memalign`. + * see: https://linux.die.net/man/3/aligned_alloc + * For MSVC, we fall back to `_aligned_malloc`. + * see: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/aligned-malloc?view=vs-2019 * * Because of the ways in which volk_gnsssdr_malloc may allocate memory, it is * important to always free volk_gnsssdr_malloc pointers using volk_gnsssdr_free. + * Mainly, in case MSVC is used. Consult corresponding documentation + * in case you use MSVC. * * \param size The number of bytes to allocate. * \param alignment The byte alignment of the allocated memory. @@ -50,7 +48,13 @@ VOLK_API void *volk_gnsssdr_malloc(size_t size, size_t alignment); /*! * \brief Free's memory allocated by volk_gnsssdr_malloc. - * \param aptr The aligned pointer allocaed by volk_gnsssdr_malloc. + * + * \details + * We rely on C11 syntax and compilers and just call `free` + * on memory that was allocated with `aligned_alloc`. + * Thus, `volk_gnsssdr_free` inherits the same behavoir `free` exhibits. + * + * \param aptr The aligned pointer allocated by volk_gnsssdr_malloc. */ VOLK_API void volk_gnsssdr_free(void *aptr); diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/CMakeLists.txt b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/CMakeLists.txt index ed927cef5..b5a7a82a5 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/CMakeLists.txt +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/CMakeLists.txt @@ -60,21 +60,14 @@ if(COMPILER_NAME MATCHES "GNU") endif() ######################################################################## -# check for posix_memalign, since some OSs do not internally define -# _XOPEN_SOURCE or _POSIX_C_SOURCE; they leave this to the user. +# POSIX_MEMALIGN: If we have to fall back to `posix_memalign`, +# make it known to the compiler. ######################################################################## - -include(CheckSymbolExists) -check_symbol_exists(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN) - if(HAVE_POSIX_MEMALIGN) + message(STATUS "Use `posix_memalign` for aligned malloc!") add_definitions(-DHAVE_POSIX_MEMALIGN) endif() -if(NOT DEFINED _XOPEN_SOURCE AND NOT MSVC) - add_definitions(-D_XOPEN_SOURCE=700) -endif() - ######################################################################## # detect x86 flavor of CPU ######################################################################## diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/volk_gnsssdr_malloc.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/volk_gnsssdr_malloc.c index 0b58fcd9d..14781ecbc 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/volk_gnsssdr_malloc.c +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/volk_gnsssdr_malloc.c @@ -14,107 +14,62 @@ #include /* - * For #defines used to determine support for allocation functions, - * see: http://linux.die.net/man/3/aligned_alloc + * C11 features: + * see: https://en.cppreference.com/w/c/memory/aligned_alloc + * + * MSVC is broken + * see: https://docs.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance?view=vs-2019 + * This section: + * C11 The Universal CRT implemented the parts of the + * C11 Standard Library that are required by C++17, + * with the exception of C99 strftime() E/O alternative + * conversion specifiers, C11 fopen() exclusive mode, + * and C11 aligned_alloc(). The latter is unlikely to + * be implemented, because C11 specified aligned_alloc() + * in a way that's incompatible with the Microsoft + * implementation of free(): + * namely, that free() must be able to handle highly aligned allocations. + * + * We must work around this problem because MSVC is non-compliant! */ -// Otherwise, test if we are a POSIX or X/Open system -// This only has a restriction that alignment be a power of 2and a -// multiple of sizeof(void *). -#if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || HAVE_POSIX_MEMALIGN - void *volk_gnsssdr_malloc(size_t size, size_t alignment) { - void *ptr; - +#if HAVE_POSIX_MEMALIGN // quoting posix_memalign() man page: // "alignment must be a power of two and a multiple of sizeof(void *)" - // volk_get_alignment() could return 1 for some machines (e.g. generic_orc) + // volk_gnsssdr_get_alignment() could return 1 for some machines (e.g. generic_orc) if (alignment == 1) - return malloc(size); - - int err = posix_memalign(&ptr, alignment, size); - if (err == 0) { - return ptr; + return malloc(size); } - else + void *ptr; + int err = posix_memalign(&ptr, alignment, size); + if (err != 0) { + ptr = NULL; fprintf(stderr, "VOLK_GNSSSDR: Error allocating memory " "(posix_memalign: error %d: %s)\n", err, strerror(err)); - return NULL; } -} - -void volk_gnsssdr_free(void *ptr) -{ - free(ptr); -} - -// _aligned_malloc has no restriction on size, -// available on Windows since Visual C++ 2005 -#elif _MSC_VER >= 1400 - -void *volk_gnsssdr_malloc(size_t size, size_t alignment) -{ +#elif defined(_MSC_VER) void *ptr = _aligned_malloc(size, alignment); +#else + void *ptr = aligned_alloc(alignment, size); +#endif if (ptr == NULL) { - fprintf(stderr, "VOLK_GNSSSDR: Error allocating memory (_aligned_malloc)\n"); + fprintf(stderr, "VOLK_GNSSSDR: Error allocating memory (aligned_alloc/_aligned_malloc)\n"); } return ptr; } void volk_gnsssdr_free(void *ptr) { +#if defined(_MSC_VER) _aligned_free(ptr); +#else + free(ptr); +#endif } - -// No standard handlers; we'll do it ourselves. -#else // _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || HAVE_POSIX_MEMALIGN - -struct block_info -{ - void *real; -}; - -void * -volk_gnsssdr_malloc(size_t size, size_t alignment) -{ - void *real, *user; - struct block_info *info; - - /* At least align to sizeof our struct */ - if (alignment < sizeof(struct block_info)) - alignment = sizeof(struct block_info); - - /* Alloc */ - real = malloc(size + (2 * alignment - 1)); - - /* Get pointer to the various zones */ - user = (void *)((((uintptr_t)real) + sizeof(struct block_info) + alignment - 1) & ~(alignment - 1)); - info = (struct block_info *)(((uintptr_t)user) - sizeof(struct block_info)); - - /* Store the info for the free */ - info->real = real; - - /* Return pointer to user */ - return user; -} - -void volk_gnsssdr_free(void *ptr) -{ - struct block_info *info; - - /* Get the real pointer */ - info = (struct block_info *)(((uintptr_t)ptr) - sizeof(struct block_info)); - - /* Release real pointer */ - free(info->real); -} - -#endif // _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || HAVE_POSIX_MEMALIGN - -//#endif //_ISOC11_SOURCE