Cemu/src/util/MemMapper/MemMapperUnix.cpp
2025-01-25 20:15:37 -05:00

70 lines
1.9 KiB
C++

#include "util/MemMapper/MemMapper.h"
#include <unistd.h>
#include <sys/mman.h>
namespace MemMapper
{
const size_t sPageSize{ []()
{
return (size_t)getpagesize();
}()
};
size_t GetPageSize()
{
return sPageSize;
}
int GetProt(PAGE_PERMISSION permissionFlags)
{
int p = 0;
if (HAS_FLAG(permissionFlags, PAGE_PERMISSION::P_READ) && HAS_FLAG(permissionFlags, PAGE_PERMISSION::P_WRITE) && HAS_FLAG(permissionFlags, PAGE_PERMISSION::P_EXECUTE))
p = PROT_READ | PROT_WRITE | PROT_EXEC;
else if (HAS_FLAG(permissionFlags, PAGE_PERMISSION::P_READ) && HAS_FLAG(permissionFlags, PAGE_PERMISSION::P_WRITE) && !HAS_FLAG(permissionFlags, PAGE_PERMISSION::P_EXECUTE))
p = PROT_READ | PROT_WRITE;
else if (HAS_FLAG(permissionFlags, PAGE_PERMISSION::P_READ) && !HAS_FLAG(permissionFlags, PAGE_PERMISSION::P_WRITE) && !HAS_FLAG(permissionFlags, PAGE_PERMISSION::P_EXECUTE))
p = PROT_READ;
else
cemu_assert_unimplemented();
return p;
}
void* ReserveMemory(void* baseAddr, size_t size, PAGE_PERMISSION permissionFlags)
{
return mmap(baseAddr, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
}
void FreeReservation(void* baseAddr, size_t size)
{
munmap(baseAddr, size);
}
void* AllocateMemory(void* baseAddr, size_t size, PAGE_PERMISSION permissionFlags, bool fromReservation)
{
void* r;
if(fromReservation)
{
uint64 page_size = sysconf(_SC_PAGESIZE);
void* page = baseAddr;
if ( (uint64) baseAddr % page_size != 0 )
page = (void*) ((uint64)baseAddr & ~(page_size - 1));
if( mprotect(page, size, GetProt(permissionFlags)) == 0 )
r = baseAddr;
else
r = nullptr;
}
else
r = mmap(baseAddr, size, GetProt(permissionFlags), MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
return r;
}
void FreeMemory(void* baseAddr, size_t size, bool fromReservation)
{
if (fromReservation)
mprotect(baseAddr, size, PROT_NONE);
else
munmap(baseAddr, size);
}
};