#ifndef _itt_shared_malloc_MapMemory_H
#define _itt_shared_malloc_MapMemory_H
#include <stdlib.h>
#if __unix__ || __APPLE__ || __sun || __FreeBSD__
#if __sun && !defined(_XPG4_2)
#define _XPG4_2 1
#define XPG4_WAS_DEFINED 1
#endif
#include <sys/mman.h>
#if __unix__
#define __TBB_MAP_HUGETLB 0x40000
#else
#define __TBB_MAP_HUGETLB 0
#endif
#if XPG4_WAS_DEFINED
#undef _XPG4_2
#undef XPG4_WAS_DEFINED
#endif
inline void* mmap_impl(size_t map_size, void* map_hint = NULL, int map_flags = 0) {
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
return mmap(map_hint, map_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | map_flags, -1, 0);
}
inline void* mmapTHP(size_t bytes) {
static void* hint;
hint = hint ? (void*)((uintptr_t)hint - bytes) : hint;
void* result = mmap_impl(bytes, hint);
if (result == MAP_FAILED) {
hint = NULL;
return MAP_FAILED;
}
if (!isAligned(result, HUGE_PAGE_SIZE)) {
munmap(result, bytes);
result = mmap_impl(bytes + HUGE_PAGE_SIZE);
if (result == MAP_FAILED) {
hint = NULL;
return MAP_FAILED;
}
uintptr_t offset = 0;
if (!isAligned(result, HUGE_PAGE_SIZE)) {
offset = HUGE_PAGE_SIZE - ((uintptr_t)result & (HUGE_PAGE_SIZE - 1));
munmap(result, offset);
result = (void*)((uintptr_t)result + offset);
}
munmap((void*)((uintptr_t)result + bytes), HUGE_PAGE_SIZE - offset);
}
hint = result;
MALLOC_ASSERT(isAligned(result, HUGE_PAGE_SIZE), "Mapped address is not aligned on huge page size.");
return result;
}
#define MEMORY_MAPPING_USES_MALLOC 0
void* MapMemory (size_t bytes, PageType pageType)
{
void* result = 0;
int prevErrno = errno;
switch (pageType) {
case REGULAR:
{
result = mmap_impl(bytes);
break;
}
case PREALLOCATED_HUGE_PAGE:
{
MALLOC_ASSERT((bytes % HUGE_PAGE_SIZE) == 0, "Mapping size should be divisible by huge page size");
result = mmap_impl(bytes, NULL, __TBB_MAP_HUGETLB);
break;
}
case TRANSPARENT_HUGE_PAGE:
{
MALLOC_ASSERT((bytes % HUGE_PAGE_SIZE) == 0, "Mapping size should be divisible by huge page size");
result = mmapTHP(bytes);
break;
}
default:
{
MALLOC_ASSERT(false, "Unknown page type");
}
}
if (result == MAP_FAILED) {
errno = prevErrno;
return 0;
}
return result;
}
int UnmapMemory(void *area, size_t bytes)
{
int prevErrno = errno;
int ret = munmap(area, bytes);
if (-1 == ret)
errno = prevErrno;
return ret;
}
#elif (_WIN32 || _WIN64) && !__TBB_WIN8UI_SUPPORT
#include <windows.h>
#define MEMORY_MAPPING_USES_MALLOC 0
void* MapMemory (size_t bytes, PageType)
{
return VirtualAlloc(NULL, bytes, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
}
int UnmapMemory(void *area, size_t )
{
BOOL result = VirtualFree(area, 0, MEM_RELEASE);
return !result;
}
#else
void *ErrnoPreservingMalloc(size_t bytes)
{
int prevErrno = errno;
void *ret = malloc( bytes );
if (!ret)
errno = prevErrno;
return ret;
}
#define MEMORY_MAPPING_USES_MALLOC 1
void* MapMemory (size_t bytes, PageType)
{
return ErrnoPreservingMalloc( bytes );
}
int UnmapMemory(void *area, size_t )
{
free( area );
return 0;
}
#endif
#if MALLOC_CHECK_RECURSION && MEMORY_MAPPING_USES_MALLOC
#error Impossible to protect against malloc recursion when memory mapping uses malloc.
#endif
#endif