1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-06-16 10:09:58 +00:00

Use Use C11 aligned_alloc

See https://github.com/gnuradio/volk/pull/334
This commit is contained in:
Carles Fernandez 2020-02-13 19:44:24 +01:00
parent 10fc3fc48e
commit 0f4bd21805
No known key found for this signature in database
GPG Key ID: 4C583C52B0C3877D
6 changed files with 80 additions and 107 deletions

View File

@ -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)

View File

@ -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

View File

@ -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
}

View File

@ -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);

View File

@ -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
########################################################################

View File

@ -14,107 +14,62 @@
#include <string.h>
/*
* 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