You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/CryEngine/CrySystem/MemoryAddressRange.cpp

146 lines
3.8 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySystem_precompiled.h"
#include "MemoryAddressRange.h"
#include "System.h"
#if defined(APPLE) || defined(LINUX)
#include <sys/mman.h>
#endif
CMemoryAddressRange::CMemoryAddressRange(char* pBaseAddress, size_t nPageSize, size_t nPageCount, [[maybe_unused]] const char* sName)
: m_pBaseAddress(pBaseAddress)
, m_nPageSize(nPageSize)
, m_nPageCount(nPageCount)
{
}
void CMemoryAddressRange::Release()
{
delete this;
}
char* CMemoryAddressRange::GetBaseAddress() const
{
return m_pBaseAddress;
}
size_t CMemoryAddressRange::GetPageCount() const
{
return m_nPageCount;
}
size_t CMemoryAddressRange::GetPageSize() const
{
return m_nPageSize;
}
#if AZ_LEGACY_CRYSYSTEM_TRAIT_MEMADDRESSRANGE_WINDOWS_STYLE
void* CMemoryAddressRange::ReserveSpace(size_t capacity)
{
return VirtualAlloc(NULL, capacity, MEM_RESERVE, PAGE_READWRITE);
}
size_t CMemoryAddressRange::GetSystemPageSize()
{
SYSTEM_INFO si;
GetSystemInfo(&si);
return si.dwPageSize;
}
CMemoryAddressRange::CMemoryAddressRange(size_t capacity, [[maybe_unused]] const char* name)
{
m_nPageSize = GetSystemPageSize();
size_t algnCap = Align(capacity, m_nPageSize);
m_pBaseAddress = (char*)ReserveSpace(algnCap);
m_nPageCount = algnCap / m_nPageSize;
}
CMemoryAddressRange::~CMemoryAddressRange()
{
VirtualFree(m_pBaseAddress, 0, MEM_RELEASE);
}
void* CMemoryAddressRange::MapPage(size_t pageIdx)
{
void* pRet = VirtualAlloc(m_pBaseAddress + pageIdx * m_nPageSize, m_nPageSize, MEM_COMMIT, PAGE_READWRITE);
return pRet;
}
void CMemoryAddressRange::UnmapPage(size_t pageIdx)
{
char* pBase = m_pBaseAddress + pageIdx * m_nPageSize;
// Disable warning about only decommitting pages, and not releasing them
VirtualFree(pBase, m_nPageSize, MEM_DECOMMIT);
}
#elif defined(AZ_RESTRICTED_PLATFORM)
#include AZ_RESTRICTED_FILE(MemoryAddressRange_cpp)
#elif defined(APPLE) || defined(LINUX)
void* CMemoryAddressRange::ReserveSpace(size_t capacity)
{
return mmap(0, capacity, PROT_NONE, MAP_ANON | MAP_NORESERVE | MAP_PRIVATE, -1, 0);
}
size_t CMemoryAddressRange::GetSystemPageSize()
{
return sysconf(_SC_PAGESIZE);
}
CMemoryAddressRange::CMemoryAddressRange(size_t capacity, const char* name)
{
m_nPageSize = GetSystemPageSize();
m_allocatedSpace = Align(capacity, m_nPageSize);
m_pBaseAddress = (char*)ReserveSpace(m_allocatedSpace);
assert(m_pBaseAddress != MAP_FAILED);
m_nPageCount = m_allocatedSpace / m_nPageSize;
}
CMemoryAddressRange::~CMemoryAddressRange()
{
int ret = munmap(m_pBaseAddress, m_allocatedSpace);
(void) ret;
assert(ret == 0);
}
void* CMemoryAddressRange::MapPage(size_t pageIdx)
{
// There is no equivalent to this function with mmap, this
// happens automatically in the OS. We just return the
// correct address.
void* pRet = NULL;
if (0 == mprotect(m_pBaseAddress + (pageIdx * m_nPageSize), m_nPageSize, PROT_READ | PROT_WRITE))
{
pRet = m_pBaseAddress + (pageIdx * m_nPageSize);
}
return pRet;
}
void CMemoryAddressRange::UnmapPage(size_t pageIdx)
{
char* pBase = m_pBaseAddress + pageIdx * m_nPageSize;
int ret = mprotect(pBase, m_nPageSize, PROT_NONE);
(void) ret;
assert(ret == 0);
}
#endif