Skip to content

Commit

Permalink
Use memalign, posix_memalign and _aligned_malloc to allocate aligned …
Browse files Browse the repository at this point in the history
…memory.

This uses the standard allocator for allocating and freeing memory with
higher alignment requirements instead of the hand-rolled implementation.

Signed-off-by: Andrey Semashev <andrey.semashev@gmail.com>
  • Loading branch information
Lastique committed Nov 26, 2021
1 parent fb8ae3b commit 0365020
Showing 1 changed file with 38 additions and 2 deletions.
40 changes: 38 additions & 2 deletions src/tbb/allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,24 @@
#include <dlfcn.h>
#endif

#if (!defined(_WIN32) && !defined(_WIN64)) || defined(__CYGWIN__)
#include <stdlib.h> // posix_memalign, free
// With glibc, uClibc and musl on Linux and bionic on Android it is safe to use memalign(), as the allocated memory
// can be freed with free(). It is also better to use memalign() since posix_memalign() is just a wrapper on top of
// memalign() and it offers nothing but overhead due to inconvenient interface. This is likely the case with other
// standard libraries as well, and more libraries can be added to the preprocessor check below. Unfortunately, we
// can't detect musl, so we simply enable memalign() on Linux and Android in general.
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__ANDROID__)
#include <malloc.h> // memalign
#define __TBB_USE_MEMALIGN
#else
#define __TBB_USE_POSIX_MEMALIGN
#endif
#elif defined(_MSC_VER) || defined(__MINGW32__)
#include <malloc.h> // _aligned_malloc, _aligned_free
#define __TBB_USE_MSVC_ALIGNED_MALLOC
#endif

#if __TBB_WEAK_SYMBOLS_PRESENT

#pragma weak scalable_malloc
Expand Down Expand Up @@ -67,10 +85,10 @@ static void (*deallocate_handler)(void* pointer) = nullptr;
//! Initialization routine used for first indirect call via cache_aligned_allocate_handler.
static void* initialize_cache_aligned_allocate_handler(std::size_t n, std::size_t alignment);

//! Allocates memory using standard malloc. It is used when scalable_allocator is not available
//! Allocates overaligned memory using standard memory allocator. It is used when scalable_allocator is not available.
static void* std_cache_aligned_allocate(std::size_t n, std::size_t alignment);

//! Allocates memory using standard free. It is used when scalable_allocator is not available
//! Deallocates overaligned memory using standard memory allocator. It is used when scalable_allocator is not available.
static void std_cache_aligned_deallocate(void* p);

//! Handler for padded memory allocation
Expand Down Expand Up @@ -185,6 +203,17 @@ void __TBB_EXPORTED_FUNC cache_aligned_deallocate(void* p) {
}

static void* std_cache_aligned_allocate(std::size_t bytes, std::size_t alignment) {
#if defined(__TBB_USE_MEMALIGN)
return memalign(alignment, bytes);
#elif defined(__TBB_USE_POSIX_MEMALIGN)
void* p = nullptr;
int res = posix_memalign(&p, alignment, bytes);
if (res != 0)
p = nullptr;
return p;
#elif defined(__TBB_USE_MSVC_ALIGNED_MALLOC)
return _aligned_malloc(bytes, alignment);
#else
// TODO: make it common with cache_aligned_resource
std::size_t space = alignment + bytes;
std::uintptr_t base = reinterpret_cast<std::uintptr_t>(std::malloc(space));
Expand All @@ -199,16 +228,23 @@ static void* std_cache_aligned_allocate(std::size_t bytes, std::size_t alignment
// Record where block actually starts.
(reinterpret_cast<std::uintptr_t*>(result))[-1] = base;
return reinterpret_cast<void*>(result);
#endif
}

static void std_cache_aligned_deallocate(void* p) {
#if defined(__TBB_USE_MEMALIGN) || defined(__TBB_USE_POSIX_MEMALIGN)
free(p);
#elif defined(__TBB_USE_MSVC_ALIGNED_MALLOC)
_aligned_free(p);
#else
if (p) {
__TBB_ASSERT(reinterpret_cast<std::uintptr_t>(p) >= 0x4096, "attempt to free block not obtained from cache_aligned_allocator");
// Recover where block actually starts
std::uintptr_t base = (reinterpret_cast<std::uintptr_t*>(p))[-1];
__TBB_ASSERT(((base + nfs_size) & ~(nfs_size - 1)) == reinterpret_cast<std::uintptr_t>(p), "Incorrect alignment or not allocated by std_cache_aligned_deallocate?");
std::free(reinterpret_cast<void*>(base));
}
#endif
}

void* __TBB_EXPORTED_FUNC allocate_memory(std::size_t size) {
Expand Down

0 comments on commit 0365020

Please sign in to comment.