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 25, 2021
1 parent fb8ae3b commit 1146885
Showing 1 changed file with 44 additions and 0 deletions.
44 changes: 44 additions & 0 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,11 +85,15 @@ 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);

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

#if !defined(__TBB_USE_POSIX_MEMALIGN) && !defined(__TBB_USE_MEMALIGN) && !defined(__TBB_USE_MSVC_ALIGNED_MALLOC)
//! Allocates memory using standard free. It is used when scalable_allocator is not available
static void std_cache_aligned_deallocate(void* p);
#endif

//! Handler for padded memory allocation
using cache_aligned_allocate_handler_type = void* (*)(std::size_t n, std::size_t alignment);
Expand Down Expand Up @@ -123,8 +145,16 @@ void initialize_handler_pointers() {
// which forces them to wait.
allocate_handler_unsafe = &std::malloc;
deallocate_handler = &std::free;
#if defined(__TBB_USE_POSIX_MEMALIGN) || defined(__TBB_USE_MEMALIGN)
cache_aligned_allocate_handler_unsafe = &std_cache_aligned_allocate;
cache_aligned_deallocate_handler = &::free;
#elif defined(__TBB_USE_MSVC_ALIGNED_MALLOC)
cache_aligned_allocate_handler_unsafe = &::_aligned_malloc;
cache_aligned_deallocate_handler = &::_aligned_free;
#else
cache_aligned_allocate_handler_unsafe = &std_cache_aligned_allocate;
cache_aligned_deallocate_handler = &std_cache_aligned_deallocate;
#endif
}

allocate_handler.store(allocate_handler_unsafe, std::memory_order_release);
Expand Down Expand Up @@ -184,7 +214,17 @@ void __TBB_EXPORTED_FUNC cache_aligned_deallocate(void* p) {
(*cache_aligned_deallocate_handler)(p);
}

#if !defined(__TBB_USE_MSVC_ALIGNED_MALLOC)
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;
#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,8 +239,11 @@ 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
}
#endif // !defined(__TBB_USE_MSVC_ALIGNED_MALLOC)

#if !defined(__TBB_USE_POSIX_MEMALIGN) && !defined(__TBB_USE_MEMALIGN) && !defined(__TBB_USE_MSVC_ALIGNED_MALLOC)
static void std_cache_aligned_deallocate(void* p) {
if (p) {
__TBB_ASSERT(reinterpret_cast<std::uintptr_t>(p) >= 0x4096, "attempt to free block not obtained from cache_aligned_allocator");
Expand All @@ -210,6 +253,7 @@ static void std_cache_aligned_deallocate(void* p) {
std::free(reinterpret_cast<void*>(base));
}
}
#endif // !defined(__TBB_USE_POSIX_MEMALIGN) && !defined(__TBB_USE_MEMALIGN) && !defined(__TBB_USE_MSVC_ALIGNED_MALLOC)

void* __TBB_EXPORTED_FUNC allocate_memory(std::size_t size) {
void* result = allocate_handler.load(std::memory_order_acquire)(size);
Expand Down

0 comments on commit 1146885

Please sign in to comment.