From 0f4bd21805780f45ccb443236b6fc0e3e1a10d05 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Thu, 13 Feb 2020 19:44:24 +0100 Subject: [PATCH 1/6] 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 From ad79c7a7b5b0938a1c1e9e0920dee995598f4b0d Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Sat, 15 Feb 2020 15:16:10 +0100 Subject: [PATCH 2/6] Update changelog --- docs/changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog b/docs/changelog index c97fda85a..1b97f5bb2 100644 --- a/docs/changelog +++ b/docs/changelog @@ -67,6 +67,7 @@ SPDX-License-Identifier: GPL-3.0-or-later - The software can now be built using Xcode (passing -GXcode to CMake) without previous manual installation of volk_gnsssdr. - The software can now be built using Xcode (passing -GXcode to CMake) without gflags, glog, matio, PugiXML, Protocol Buffers or googletest previously installed. - Now the volk_gnsssdr library can be built on Microsoft Windows. +- Now the volk_gnsssdr library makes use of C11 aligned_alloc where available. - Improved CMake script for cross-compilation and for the detection of AVX, AVX2 and NEON (v7 and v8) instructions. From 0715fd8e8e2765588f201978b2f72517c931121f Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Sun, 16 Feb 2020 12:25:27 +0100 Subject: [PATCH 3/6] Update Protocol Buffers to 3.11.4 --- CMakeLists.txt | 2 +- README.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d55b97cfc..2854467fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -287,7 +287,7 @@ set(GNSSSDR_GNSS_SIM_LOCAL_VERSION "master") set(GNSSSDR_GPSTK_LOCAL_VERSION "2.12") set(GNSSSDR_MATIO_LOCAL_VERSION "1.5.17") set(GNSSSDR_PUGIXML_LOCAL_VERSION "1.10") -set(GNSSSDR_PROTOCOLBUFFERS_LOCAL_VERSION "3.11.3") +set(GNSSSDR_PROTOCOLBUFFERS_LOCAL_VERSION "3.11.4") if(CMAKE_VERSION VERSION_LESS "3.0.2") set(GNSSSDR_GFLAGS_LOCAL_VERSION "2.2.1") # Fix for CentOS 7 diff --git a/README.md b/README.md index ab2467609..4c35efc8a 100644 --- a/README.md +++ b/README.md @@ -311,9 +311,9 @@ $ sudo apt-get install autoconf automake libtool curl make g++ unzip and then: ~~~~~~ -$ wget https://github.com/protocolbuffers/protobuf/releases/download/v3.11.3/protobuf-cpp-3.11.3.tar.gz -$ tar xvfz protobuf-cpp-3.11.3.tar.gz -$ cd protobuf-3.11.3 +$ wget https://github.com/protocolbuffers/protobuf/releases/download/v3.11.4/protobuf-cpp-3.11.4.tar.gz +$ tar xvfz protobuf-cpp-3.11.4.tar.gz +$ cd protobuf-3.11.4 $ ./autogen.sh $ ./configure $ make From 42352f2493bb44c0a79a17898906fff89ca4708f Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Sun, 16 Feb 2020 12:38:34 +0100 Subject: [PATCH 4/6] Update Armadillo to 9.850.1 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4c35efc8a..b02dcb684 100644 --- a/README.md +++ b/README.md @@ -229,9 +229,9 @@ $ sudo apt-get install libblas-dev liblapack-dev # For Debian/Ubuntu/Linux $ sudo yum install lapack-devel blas-devel # For Fedora/CentOS/RHEL $ sudo zypper install lapack-devel blas-devel # For OpenSUSE $ sudo pacman -S blas lapack # For Arch Linux -$ wget https://sourceforge.net/projects/arma/files/armadillo-9.800.4.tar.xz -$ tar xvfz armadillo-9.800.4.tar.xz -$ cd armadillo-9.800.4 +$ wget https://sourceforge.net/projects/arma/files/armadillo-9.850.1.tar.xz +$ tar xvfz armadillo-9.850.1.tar.xz +$ cd armadillo-9.850.1 $ cmake . $ make $ sudo make install From 448995f8b0aeef0277028fb18636589e5ab1fcd9 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Mon, 17 Feb 2020 08:00:52 +0100 Subject: [PATCH 5/6] Improve documentation --- .../include/volk_gnsssdr/volk_gnsssdr_malloc.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) 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 a14b498e3..5ff613148 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 @@ -4,7 +4,7 @@ * returns a pointer to the allocated memory. * \author Andres Cecilia, 2014. a.cecilia.luque(at)gmail.com * - * Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software-defined Global Navigation Satellite Systems receiver * @@ -46,13 +46,17 @@ __VOLK_DECL_BEGIN */ VOLK_API void *volk_gnsssdr_malloc(size_t size, size_t alignment); + /*! * \brief Free's memory allocated 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. + * We rely on C11 syntax and compilers and just call `free` in case + * memory was allocated with `aligned_alloc` or `posix_memalign`. + * Thus, in this case `volk_gnsssdr_free` inherits the same behavior `free` exhibits. + * see: https://en.cppreference.com/w/c/memory/free + * In case `_aligned_malloc` was used, we call `_aligned_free`. + * see: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/aligned-free?view=vs-2019 * * \param aptr The aligned pointer allocated by volk_gnsssdr_malloc. */ From ac7a77fd47e373c5cb8ebf0c44c55141ad6e3c67 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Mon, 17 Feb 2020 08:02:59 +0100 Subject: [PATCH 6/6] Minor fixes --- .../libs/volk_gnsssdr_module/volk_gnsssdr/lib/qa_utils.cc | 4 ++-- .../volk_gnsssdr/lib/volk_gnsssdr_prefs.c | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/qa_utils.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/qa_utils.cc index 682dc3e4c..b0404f29b 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/qa_utils.cc +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/qa_utils.cc @@ -171,7 +171,7 @@ volk_gnsssdr_type_t volk_gnsssdr_type_from_string(std::string name) type.is_signed = false; break; default: - throw; + throw std::string("Error: no such type: '") + name[i] + "'"; } } @@ -238,7 +238,7 @@ static void get_signatures_from_name(std::vector &inputsig, } catch (...) { - if (token[0] == 'x' && (token.size() > 1) && (token[1] > '0' || token[1] < '9')) + if (token[0] == 'x' && (token.size() > 1) && (token[1] > '0' && token[1] < '9')) { if (side == SIDE_INPUT) assert(inputsig.size() > 0); diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/volk_gnsssdr_prefs.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/volk_gnsssdr_prefs.c index e76f72edc..c47c62f3d 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/volk_gnsssdr_prefs.c +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/volk_gnsssdr_prefs.c @@ -102,7 +102,13 @@ size_t volk_gnsssdr_load_preferences(volk_gnsssdr_arch_pref_t **prefs_res) // reset the file pointer and write the prefs into volk_gnsssdr_arch_prefs while (fgets(line, sizeof(line), config_file) != NULL) { - prefs = (volk_gnsssdr_arch_pref_t *)realloc(prefs, (n_arch_prefs + 1) * sizeof(*prefs)); + void *new_prefs = realloc(prefs, (n_arch_prefs + 1) * sizeof(*prefs)); + if (!new_prefs) + { + printf("volk_gnsssdr_load_preferences: bad malloc\n"); + break; + } + prefs = (volk_gnsssdr_arch_pref_t *)new_prefs; volk_gnsssdr_arch_pref_t *p = prefs + n_arch_prefs; if (sscanf(line, "%s %s %s", p->name, p->impl_a, p->impl_u) == 3 && !strncmp(p->name, "volk_gnsssdr_", 5)) {