mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
vm: fix mapping of file's last page
thanks @red_prig for investigation
This commit is contained in:
parent
ea2915467a
commit
e6022c1c4c
|
|
@ -14,10 +14,6 @@ orbis::SysResult orbis::sys_sstk(Thread *, sint) {
|
||||||
orbis::SysResult orbis::sys_mmap(Thread *thread, caddr_t addr, size_t len,
|
orbis::SysResult orbis::sys_mmap(Thread *thread, caddr_t addr, size_t len,
|
||||||
sint prot, sint flags, sint fd, off_t pos) {
|
sint prot, sint flags, sint fd, off_t pos) {
|
||||||
if (auto impl = thread->tproc->ops->mmap) {
|
if (auto impl = thread->tproc->ops->mmap) {
|
||||||
// hack for audio control shared memory
|
|
||||||
if (len == 3880) {
|
|
||||||
return impl(thread, addr, 0x10000, prot, flags, fd, pos);
|
|
||||||
}
|
|
||||||
return impl(thread, addr, len, prot, flags, fd, pos);
|
return impl(thread, addr, len, prot, flags, fd, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include "orbis/thread/Thread.hpp"
|
#include "orbis/thread/Thread.hpp"
|
||||||
#include "orbis/uio.hpp"
|
#include "orbis/uio.hpp"
|
||||||
#include "orbis/utils/Logs.hpp"
|
#include "orbis/utils/Logs.hpp"
|
||||||
|
#include "rx/mem.hpp"
|
||||||
#include "vfs.hpp"
|
#include "vfs.hpp"
|
||||||
#include "vm.hpp"
|
#include "vm.hpp"
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
|
@ -15,6 +16,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <optional>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
@ -25,7 +27,6 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
struct HostFile : orbis::File {
|
struct HostFile : orbis::File {
|
||||||
bool closeOnExit = true;
|
bool closeOnExit = true;
|
||||||
|
|
@ -339,20 +340,54 @@ static orbis::ErrorCode host_mmap(orbis::File *file, void **address,
|
||||||
return orbis::ErrorCode::ISDIR;
|
return orbis::ErrorCode::ISDIR;
|
||||||
|
|
||||||
auto result =
|
auto result =
|
||||||
rx::vm::map(*address, size, prot, flags, rx::vm::kMapInternalReserveOnly);
|
rx::vm::map(*address, size, prot, flags, rx::vm::kMapInternalReserveOnly,
|
||||||
|
hostFile->device.cast<IoDevice>().get(), offset);
|
||||||
|
|
||||||
if (result == (void *)-1) {
|
if (result == (void *)-1) {
|
||||||
return orbis::ErrorCode::NOMEM;
|
return orbis::ErrorCode::NOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ::mmap(result, size, prot & rx::vm::kMapProtCpuAll,
|
size = utils::alignUp(size, rx::vm::kPageSize);
|
||||||
MAP_SHARED | MAP_FIXED, hostFile->hostFd, offset);
|
|
||||||
|
result = ::mmap(
|
||||||
|
result, size, prot & rx::vm::kMapProtCpuAll,
|
||||||
|
((prot & rx::vm::kMapFlagPrivate) != 0 ? MAP_PRIVATE : MAP_SHARED) |
|
||||||
|
MAP_FIXED,
|
||||||
|
hostFile->hostFd, offset);
|
||||||
if (result == (void *)-1) {
|
if (result == (void *)-1) {
|
||||||
auto result = convertErrno();
|
auto errc = convertErrno();
|
||||||
return result;
|
std::printf("Failed to map file at %p-%p\n", *address,
|
||||||
|
(char *)*address + size);
|
||||||
|
return errc;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::printf("shm mapped at %p-%p\n", result, (char *)result + size);
|
std::printf("file mapped at %p-%p:%lx\n", result, (char *)result + size,
|
||||||
|
offset);
|
||||||
|
|
||||||
|
struct stat stat;
|
||||||
|
fstat(hostFile->hostFd, &stat);
|
||||||
|
if (stat.st_size < offset + size) {
|
||||||
|
std::size_t rest =
|
||||||
|
std::min(offset + size - stat.st_size, rx::vm::kPageSize);
|
||||||
|
|
||||||
|
if (rest > rx::mem::pageSize) {
|
||||||
|
auto fillSize =
|
||||||
|
utils::alignUp(rest, rx::mem::pageSize) - rx::mem::pageSize;
|
||||||
|
|
||||||
|
std::printf("adding dummy mapping %p-%p, file ends at %p\n",
|
||||||
|
(char *)result + size - fillSize, (char *)result + size,
|
||||||
|
(char *)result + (stat.st_size - offset));
|
||||||
|
|
||||||
|
auto ptr = ::mmap((char *)result + size - fillSize, fillSize,
|
||||||
|
prot & rx::vm::kMapProtCpuAll,
|
||||||
|
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||||
|
|
||||||
|
if (ptr == (void *)-1) {
|
||||||
|
std::printf("failed to add dummy mapping %p-%p\n", result,
|
||||||
|
(char *)result + size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*address = result;
|
*address = result;
|
||||||
return {};
|
return {};
|
||||||
|
|
@ -701,7 +736,8 @@ orbis::ErrorCode createSocket(orbis::Ref<orbis::File> *file,
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::optional<std::string> findFileInDir(const std::filesystem::path &dir, const char *name) {
|
static std::optional<std::string>
|
||||||
|
findFileInDir(const std::filesystem::path &dir, const char *name) {
|
||||||
for (auto entry : std::filesystem::directory_iterator(dir)) {
|
for (auto entry : std::filesystem::directory_iterator(dir)) {
|
||||||
auto entryName = entry.path().filename();
|
auto entryName = entry.path().filename();
|
||||||
if (strcasecmp(entryName.c_str(), name) == 0) {
|
if (strcasecmp(entryName.c_str(), name) == 0) {
|
||||||
|
|
@ -711,7 +747,8 @@ static std::optional<std::string> findFileInDir(const std::filesystem::path &dir
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::optional<std::filesystem::path> toRealPath(const std::filesystem::path &inp) {
|
static std::optional<std::filesystem::path>
|
||||||
|
toRealPath(const std::filesystem::path &inp) {
|
||||||
if (inp.empty()) {
|
if (inp.empty()) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
@ -793,11 +830,13 @@ orbis::ErrorCode HostFsDevice::open(orbis::Ref<orbis::File> *file,
|
||||||
error = convertErrno();
|
error = convertErrno();
|
||||||
|
|
||||||
if (auto icaseRealPath = toRealPath(realPath)) {
|
if (auto icaseRealPath = toRealPath(realPath)) {
|
||||||
ORBIS_LOG_WARNING(__FUNCTION__, path, realPath.c_str(), icaseRealPath->c_str());
|
ORBIS_LOG_WARNING(__FUNCTION__, path, realPath.c_str(),
|
||||||
|
icaseRealPath->c_str());
|
||||||
hostFd = ::open(icaseRealPath->c_str(), realFlags, 0777);
|
hostFd = ::open(icaseRealPath->c_str(), realFlags, 0777);
|
||||||
|
|
||||||
if (hostFd < 0) {
|
if (hostFd < 0) {
|
||||||
ORBIS_LOG_ERROR("host_open failed", path, realPath.c_str(), icaseRealPath->c_str(), error);
|
ORBIS_LOG_ERROR("host_open failed", path, realPath.c_str(),
|
||||||
|
icaseRealPath->c_str(), error);
|
||||||
return convertErrno();
|
return convertErrno();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -899,7 +938,8 @@ orbis::ErrorCode HostFsDevice::rename(const char *from, const char *to,
|
||||||
return convertErrorCode(ec);
|
return convertErrorCode(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
orbis::File *createHostFile(int hostFd, orbis::Ref<IoDevice> device, bool alignTruncate) {
|
orbis::File *createHostFile(int hostFd, orbis::Ref<IoDevice> device,
|
||||||
|
bool alignTruncate) {
|
||||||
auto newFile = orbis::knew<HostFile>();
|
auto newFile = orbis::knew<HostFile>();
|
||||||
newFile->hostFd = hostFd;
|
newFile->hostFd = hostFd;
|
||||||
newFile->ops = &hostOps;
|
newFile->ops = &hostOps;
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "orbis/thread/Thread.hpp"
|
#include "orbis/thread/Thread.hpp"
|
||||||
#include "orbis/utils/Logs.hpp"
|
#include "orbis/utils/Logs.hpp"
|
||||||
#include "orbis/utils/Rc.hpp"
|
#include "orbis/utils/Rc.hpp"
|
||||||
|
#include "rx/mem.hpp"
|
||||||
#include <bit>
|
#include <bit>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
|
@ -20,32 +21,6 @@
|
||||||
|
|
||||||
#include <rx/MemoryTable.hpp>
|
#include <rx/MemoryTable.hpp>
|
||||||
|
|
||||||
namespace utils {
|
|
||||||
namespace {
|
|
||||||
void *map(void *address, std::size_t size, int prot, int flags, int fd = -1,
|
|
||||||
off_t offset = 0) {
|
|
||||||
return ::mmap(address, size, prot, flags, fd, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *reserve(std::size_t size) {
|
|
||||||
return map(nullptr, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool reserve(void *address, std::size_t size) {
|
|
||||||
return map(address, size, PROT_NONE,
|
|
||||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED) != MAP_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool protect(void *address, std::size_t size, int prot) {
|
|
||||||
return ::mprotect(address, size, prot) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool unmap(void *address, std::size_t size) {
|
|
||||||
return ::munmap(address, size) == 0;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
} // namespace utils
|
|
||||||
|
|
||||||
static std::mutex g_mtx;
|
static std::mutex g_mtx;
|
||||||
|
|
||||||
std::string rx::vm::mapFlagsToString(std::int32_t flags) {
|
std::string rx::vm::mapFlagsToString(std::int32_t flags) {
|
||||||
|
|
@ -305,7 +280,8 @@ struct Block {
|
||||||
|
|
||||||
void setFlags(std::uint64_t firstPage, std::uint64_t pagesCount,
|
void setFlags(std::uint64_t firstPage, std::uint64_t pagesCount,
|
||||||
std::uint32_t flags, bool noOverwrite) {
|
std::uint32_t flags, bool noOverwrite) {
|
||||||
modifyFlags(firstPage, pagesCount, flags, ~static_cast<std::uint32_t>(0), noOverwrite);
|
modifyFlags(firstPage, pagesCount, flags, ~static_cast<std::uint32_t>(0),
|
||||||
|
noOverwrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addFlags(std::uint64_t firstPage, std::uint64_t pagesCount,
|
void addFlags(std::uint64_t firstPage, std::uint64_t pagesCount,
|
||||||
|
|
@ -681,7 +657,8 @@ static void reserve(std::uint64_t startAddress, std::uint64_t endAddress) {
|
||||||
auto pagesCount = (endAddress - startAddress + (rx::vm::kPageSize - 1)) >>
|
auto pagesCount = (endAddress - startAddress + (rx::vm::kPageSize - 1)) >>
|
||||||
rx::vm::kPageShift;
|
rx::vm::kPageShift;
|
||||||
|
|
||||||
gBlocks[blockIndex - kFirstBlock].setFlags(firstPage, pagesCount, kAllocated, false);
|
gBlocks[blockIndex - kFirstBlock].setFlags(firstPage, pagesCount, kAllocated,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rx::vm::fork(std::uint64_t pid) {
|
void rx::vm::fork(std::uint64_t pid) {
|
||||||
|
|
@ -711,16 +688,16 @@ void rx::vm::fork(std::uint64_t pid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prot & kMapProtCpuAll) {
|
if (prot & kMapProtCpuAll) {
|
||||||
auto mapping = utils::map(nullptr, kPageSize, PROT_WRITE, MAP_SHARED,
|
auto mapping = rx::mem::map(nullptr, kPageSize, PROT_WRITE, MAP_SHARED,
|
||||||
gMemoryShm, address - kMinAddress);
|
gMemoryShm, address - kMinAddress);
|
||||||
assert(mapping != MAP_FAILED);
|
assert(mapping != MAP_FAILED);
|
||||||
|
|
||||||
utils::protect(reinterpret_cast<void *>(address), kPageSize, PROT_READ);
|
rx::mem::protect(reinterpret_cast<void *>(address), kPageSize, PROT_READ);
|
||||||
std::memcpy(mapping, reinterpret_cast<void *>(address), kPageSize);
|
std::memcpy(mapping, reinterpret_cast<void *>(address), kPageSize);
|
||||||
utils::unmap(mapping, kPageSize);
|
rx::mem::unmap(mapping, kPageSize);
|
||||||
utils::unmap(reinterpret_cast<void *>(address), kPageSize);
|
rx::mem::unmap(reinterpret_cast<void *>(address), kPageSize);
|
||||||
|
|
||||||
mapping = utils::map(reinterpret_cast<void *>(address), kPageSize,
|
mapping = rx::mem::map(reinterpret_cast<void *>(address), kPageSize,
|
||||||
prot & kMapProtCpuAll, MAP_FIXED | MAP_SHARED,
|
prot & kMapProtCpuAll, MAP_FIXED | MAP_SHARED,
|
||||||
gMemoryShm, address - kMinAddress);
|
gMemoryShm, address - kMinAddress);
|
||||||
assert(mapping != MAP_FAILED);
|
assert(mapping != MAP_FAILED);
|
||||||
|
|
@ -733,7 +710,7 @@ void rx::vm::fork(std::uint64_t pid) {
|
||||||
void rx::vm::reset() {
|
void rx::vm::reset() {
|
||||||
std::memset(gBlocks, 0, sizeof(gBlocks));
|
std::memset(gBlocks, 0, sizeof(gBlocks));
|
||||||
|
|
||||||
utils::unmap(reinterpret_cast<void *>(kMinAddress),
|
rx::mem::unmap(reinterpret_cast<void *>(kMinAddress),
|
||||||
kMaxAddress - kMinAddress);
|
kMaxAddress - kMinAddress);
|
||||||
if (::ftruncate64(gMemoryShm, 0) < 0) {
|
if (::ftruncate64(gMemoryShm, 0) < 0) {
|
||||||
std::abort();
|
std::abort();
|
||||||
|
|
@ -743,7 +720,7 @@ void rx::vm::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
reserve(0, kMinAddress);
|
reserve(0, kMinAddress);
|
||||||
utils::reserve(reinterpret_cast<void *>(kMinAddress),
|
rx::mem::reserve(reinterpret_cast<void *>(kMinAddress),
|
||||||
kMaxAddress - kMinAddress);
|
kMaxAddress - kMinAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -765,7 +742,7 @@ void rx::vm::initialize() {
|
||||||
|
|
||||||
reserve(0, kMinAddress); // unmapped area
|
reserve(0, kMinAddress); // unmapped area
|
||||||
|
|
||||||
utils::reserve(reinterpret_cast<void *>(kMinAddress),
|
rx::mem::reserve(reinterpret_cast<void *>(kMinAddress),
|
||||||
kMaxAddress - kMinAddress);
|
kMaxAddress - kMinAddress);
|
||||||
|
|
||||||
// orbis::bridge.setUpSharedMemory(kMinAddress, kMemorySize, "/orbis-memory");
|
// orbis::bridge.setUpSharedMemory(kMinAddress, kMemorySize, "/orbis-memory");
|
||||||
|
|
@ -796,6 +773,7 @@ void *rx::vm::map(void *addr, std::uint64_t len, std::int32_t prot,
|
||||||
addr, len, mapProtToString(prot).c_str(),
|
addr, len, mapProtToString(prot).c_str(),
|
||||||
mapFlagsToString(flags).c_str());
|
mapFlagsToString(flags).c_str());
|
||||||
|
|
||||||
|
len = utils::alignUp(len, kPageSize);
|
||||||
auto pagesCount = (len + (kPageSize - 1)) >> kPageShift;
|
auto pagesCount = (len + (kPageSize - 1)) >> kPageShift;
|
||||||
auto hitAddress = reinterpret_cast<std::uint64_t>(addr);
|
auto hitAddress = reinterpret_cast<std::uint64_t>(addr);
|
||||||
|
|
||||||
|
|
@ -820,7 +798,8 @@ void *rx::vm::map(void *addr, std::uint64_t len, std::int32_t prot,
|
||||||
|
|
||||||
flags &= ~kMapFlagsAlignMask;
|
flags &= ~kMapFlagsAlignMask;
|
||||||
|
|
||||||
bool noOverwrite = (flags & (kMapFlagNoOverwrite | kMapFlagFixed)) == (kMapFlagNoOverwrite | kMapFlagFixed);
|
bool noOverwrite = (flags & (kMapFlagNoOverwrite | kMapFlagFixed)) ==
|
||||||
|
(kMapFlagNoOverwrite | kMapFlagFixed);
|
||||||
|
|
||||||
if (hitAddress & (alignment - 1)) {
|
if (hitAddress & (alignment - 1)) {
|
||||||
if (flags & kMapFlagStack) {
|
if (flags & kMapFlagStack) {
|
||||||
|
|
@ -930,7 +909,8 @@ void *rx::vm::map(void *addr, std::uint64_t len, std::int32_t prot,
|
||||||
|
|
||||||
block.setFlags((address & kBlockMask) >> kPageShift, pagesCount,
|
block.setFlags((address & kBlockMask) >> kPageShift, pagesCount,
|
||||||
(prot & (kMapProtCpuAll | kMapProtGpuAll)) | kAllocated |
|
(prot & (kMapProtCpuAll | kMapProtGpuAll)) | kAllocated |
|
||||||
(isShared ? kShared : 0), false);
|
(isShared ? kShared : 0),
|
||||||
|
false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (flags & kMapFlagStack) {
|
if (flags & kMapFlagStack) {
|
||||||
|
|
@ -962,9 +942,9 @@ void *rx::vm::map(void *addr, std::uint64_t len, std::int32_t prot,
|
||||||
return reinterpret_cast<void *>(address);
|
return reinterpret_cast<void *>(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result =
|
auto result = rx::mem::map(reinterpret_cast<void *>(address), len,
|
||||||
utils::map(reinterpret_cast<void *>(address), len, prot & kMapProtCpuAll,
|
prot & kMapProtCpuAll, realFlags, gMemoryShm,
|
||||||
realFlags, gMemoryShm, address - kMinAddress);
|
address - kMinAddress);
|
||||||
|
|
||||||
if (result != MAP_FAILED && isAnon) {
|
if (result != MAP_FAILED && isAnon) {
|
||||||
bool needReprotect = (prot & PROT_WRITE) == 0;
|
bool needReprotect = (prot & PROT_WRITE) == 0;
|
||||||
|
|
@ -990,6 +970,7 @@ void *rx::vm::map(void *addr, std::uint64_t len, std::int32_t prot,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rx::vm::unmap(void *addr, std::uint64_t size) {
|
bool rx::vm::unmap(void *addr, std::uint64_t size) {
|
||||||
|
size = utils::alignUp(size, kPageSize);
|
||||||
auto pages = (size + (kPageSize - 1)) >> kPageShift;
|
auto pages = (size + (kPageSize - 1)) >> kPageShift;
|
||||||
auto address = reinterpret_cast<std::uint64_t>(addr);
|
auto address = reinterpret_cast<std::uint64_t>(addr);
|
||||||
|
|
||||||
|
|
@ -1021,13 +1002,14 @@ bool rx::vm::unmap(void *addr, std::uint64_t size) {
|
||||||
} else {
|
} else {
|
||||||
std::fprintf(stderr, "ignoring mapping %lx-%lx\n", address, address + size);
|
std::fprintf(stderr, "ignoring mapping %lx-%lx\n", address, address + size);
|
||||||
}
|
}
|
||||||
return utils::unmap(addr, size);
|
return rx::mem::unmap(addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rx::vm::protect(void *addr, std::uint64_t size, std::int32_t prot) {
|
bool rx::vm::protect(void *addr, std::uint64_t size, std::int32_t prot) {
|
||||||
std::printf("rx::vm::protect(addr = %p, len = %" PRIu64 ", prot = %s)\n",
|
std::printf("rx::vm::protect(addr = %p, len = %" PRIu64 ", prot = %s)\n",
|
||||||
addr, size, mapProtToString(prot).c_str());
|
addr, size, mapProtToString(prot).c_str());
|
||||||
|
|
||||||
|
size = utils::alignUp(size, kPageSize);
|
||||||
auto pages = (size + (kPageSize - 1)) >> kPageShift;
|
auto pages = (size + (kPageSize - 1)) >> kPageShift;
|
||||||
auto address = reinterpret_cast<std::uint64_t>(addr);
|
auto address = reinterpret_cast<std::uint64_t>(addr);
|
||||||
if (address < kMinAddress || address >= kMaxAddress || size > kMaxAddress ||
|
if (address < kMinAddress || address >= kMaxAddress || size > kMaxAddress ||
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,18 @@ find_package(Git)
|
||||||
|
|
||||||
|
|
||||||
add_library(${PROJECT_NAME} OBJECT
|
add_library(${PROJECT_NAME} OBJECT
|
||||||
|
src/mem.cpp
|
||||||
src/Version.cpp
|
src/Version.cpp
|
||||||
)
|
)
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC include)
|
|
||||||
|
target_include_directories(${PROJECT_NAME}
|
||||||
|
PUBLIC
|
||||||
|
include
|
||||||
|
|
||||||
|
PRIVATE
|
||||||
|
include/${PROJECT_NAME}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
execute_process(COMMAND date +%+4Y%m%d OUTPUT_VARIABLE RAW_VERSION)
|
execute_process(COMMAND date +%+4Y%m%d OUTPUT_VARIABLE RAW_VERSION)
|
||||||
string(STRIP "${RAW_VERSION}" RAW_VERSION)
|
string(STRIP "${RAW_VERSION}" RAW_VERSION)
|
||||||
|
|
|
||||||
13
rx/include/rx/mem.hpp
Normal file
13
rx/include/rx/mem.hpp
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace rx::mem {
|
||||||
|
extern const std::size_t pageSize;
|
||||||
|
void *map(void *address, std::size_t size, int prot, int flags, int fd = -1,
|
||||||
|
std::ptrdiff_t offset = 0);
|
||||||
|
void *reserve(std::size_t size);
|
||||||
|
bool reserve(void *address, std::size_t size);
|
||||||
|
bool protect(void *address, std::size_t size, int prot);
|
||||||
|
bool unmap(void *address, std::size_t size);
|
||||||
|
} // namespace rx::mem
|
||||||
27
rx/src/mem.cpp
Normal file
27
rx/src/mem.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include "mem.hpp"
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
extern const std::size_t rx::mem::pageSize = sysconf(_SC_PAGE_SIZE);
|
||||||
|
|
||||||
|
void *rx::mem::map(void *address, std::size_t size, int prot, int flags,
|
||||||
|
int fd, std::ptrdiff_t offset) {
|
||||||
|
return ::mmap(address, size, prot, flags, fd, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *rx::mem::reserve(std::size_t size) {
|
||||||
|
return map(nullptr, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rx::mem::reserve(void *address, std::size_t size) {
|
||||||
|
return map(address, size, PROT_NONE,
|
||||||
|
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED) != MAP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rx::mem::protect(void *address, std::size_t size, int prot) {
|
||||||
|
return ::mprotect(address, size, prot) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rx::mem::unmap(void *address, std::size_t size) {
|
||||||
|
return ::munmap(address, size) == 0;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue