#include "MemMap.h"
#include <algorithm>
#ifdef _WIN64
#include <errhandlingapi.h>
#include <handleapi.h>
#include <memoryapi.h>
#endif
#include "Base/Log.h"
#include "Base/LogFile.h"
#include "Base/Panic.h"
#include "Base/SysCall.h"
namespace MapleRuntime {
using namespace std;
MemMap* MemMap::MapMemory(size_t reqSize, size_t initSize, const Option& opt)
{
void* mappedAddr = nullptr;
reqSize = AllocUtilRndUp<size_t>(reqSize, ALLOC_UTIL_PAGE_SIZE);
#ifdef _WIN64
mappedAddr = VirtualAlloc(NULL, reqSize, MEM_RESERVE, PAGE_READWRITE);
#else
DLOG(ALLOC, "MemMap::MapMemory size %zu", reqSize);
mappedAddr = mmap(opt.reqBase, reqSize, PROT_NONE, opt.flags, -1, 0);
#endif
bool failure = false;
#if defined(_WIN64) || defined(__APPLE__)
if (mappedAddr != NULL) {
#else
if (mappedAddr != MAP_FAILED) {
(void)madvise(mappedAddr, reqSize, MADV_NOHUGEPAGE);
MRT_PRCTL(mappedAddr, reqSize, opt.tag);
#endif
size_t protSize = opt.protAll ? reqSize : initSize;
if (!ProtectMemInternal(mappedAddr, protSize, opt.prot)) {
failure = true;
LOG(RTLOG_ERROR, "MemMap::MapMemory mprotect failed");
ALLOCUTIL_MEM_UNMAP(mappedAddr, reqSize);
}
} else {
failure = true;
}
CHECK_DETAIL(!failure, "MemMap::MapMemory failed reqSize: %zu initSize: %zu", reqSize, initSize);
DLOG(ALLOC, "MemMap::MapMemory size %zu successful at %p", reqSize, mappedAddr);
MemMap* memMap = new (std::nothrow) MemMap(mappedAddr, initSize, reqSize);
CHECK_DETAIL(memMap != nullptr, "new MemMap failed");
return memMap;
}
#ifdef _WIN64
void MemMap::CommitMemory(void* addr, size_t size)
{
CHECK_E(UNLIKELY(!VirtualAlloc(addr, size, MEM_COMMIT, PAGE_READWRITE)),
"VirtualAlloc commit failed in GetPage, errno: %d", GetLastError());
}
#endif
MemMap::MemMap(void* baseAddr, size_t initSize, size_t mappedSize)
: memBaseAddr(baseAddr), memCurrSize(initSize), memMappedSize(mappedSize)
{
memCurrEndAddr = reinterpret_cast<void*>(reinterpret_cast<MAddress>(memBaseAddr) + memCurrSize);
memMappedEndAddr = reinterpret_cast<void*>(reinterpret_cast<MAddress>(memBaseAddr) + memMappedSize);
}
bool MemMap::ProtectMemInternal(void* addr, size_t size, int prot)
{
DLOG(ALLOC, "MemMap::ProtectMem %p, size %zu, prot %d", addr, size, prot);
#ifdef _WIN64
return true;
#else
int ret = mprotect(addr, size, prot);
return (ret == 0);
#endif
}
MemMap::~MemMap()
{
ALLOCUTIL_MEM_UNMAP(memBaseAddr, memMappedSize);
memBaseAddr = nullptr;
memCurrEndAddr = nullptr;
memMappedEndAddr = nullptr;
}
}