Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use system functions to allocate aligned memory #671

Merged
merged 1 commit into from
Dec 3, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Lastique marked this conversation as resolved.
Show resolved Hide resolved
// 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