Skip to content

Commit

Permalink
Fixed mmap usage and (re)-implemented most parts of memory_posix.cc
Browse files Browse the repository at this point in the history
  • Loading branch information
guccigang420 committed Oct 4, 2023
1 parent f6b5424 commit 3e18402
Showing 1 changed file with 82 additions and 4 deletions.
86 changes: 82 additions & 4 deletions src/xenia/base/memory_posix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
#include "xenia/base/memory.h"

#include <fcntl.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <unistd.h>
#include <cstddef>
#include <mutex>

#include "xenia/base/math.h"
#include "xenia/base/platform.h"
Expand Down Expand Up @@ -81,12 +83,34 @@ uint32_t ToPosixProtectFlags(PageAccess access) {

bool IsWritableExecutableMemorySupported() { return true; }

struct MappedFileRange {
size_t region_begin;
size_t region_end;
};

std::vector<struct MappedFileRange> mapped_file_ranges;
std::mutex g_mapped_file_ranges_mutex;

void* AllocFixed(void* base_address, size_t length,
AllocationType allocation_type, PageAccess access) {
// mmap does not support reserve / commit, so ignore allocation_type.
uint32_t prot = ToPosixProtectFlags(access);
void* result = mmap(base_address, length, prot,
MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
int flags = MAP_PRIVATE | MAP_ANONYMOUS;

if (base_address != nullptr) {
bool should_protect = allocation_type == AllocationType::kCommit;
if (should_protect) {
if (Protect(base_address, length, access)){
return base_address;
} else {
return nullptr;
}
}
flags |= MAP_FIXED_NOREPLACE;
}

void* result = mmap(base_address, length, prot, flags, -1, 0);

if (result == MAP_FAILED) {
return nullptr;
} else {
Expand All @@ -96,7 +120,34 @@ void* AllocFixed(void* base_address, size_t length,

bool DeallocFixed(void* base_address, size_t length,
DeallocationType deallocation_type) {
return munmap(base_address, length) == 0;
const size_t region_begin = (size_t)base_address;
const size_t region_end = (size_t)base_address + length;

std::lock_guard<std::mutex> guard(g_mapped_file_ranges_mutex);
for (const auto& mapped_range : mapped_file_ranges) {
if (region_begin >= mapped_range.region_begin &&
region_end <= mapped_range.region_end) {

switch(deallocation_type) {
case DeallocationType::kDecommit:
return Protect(base_address, length, PageAccess::kNoAccess);
case DeallocationType::kRelease:
assert_always("Error: Tried to release mapped memory!");
default:
assert_unhandled_case(deallocation_type);
}

}
}

switch(deallocation_type) {
case DeallocationType::kDecommit:
return Protect(base_address, length, PageAccess::kNoAccess);
case DeallocationType::kRelease:
return munmap(base_address, length) == 0;
default:
assert_unhandled_case(deallocation_type);
}
}

bool Protect(void* base_address, size_t length, PageAccess access,
Expand Down Expand Up @@ -178,12 +229,39 @@ void CloseFileMappingHandle(FileMappingHandle handle,
void* MapFileView(FileMappingHandle handle, void* base_address, size_t length,
PageAccess access, size_t file_offset) {
uint32_t prot = ToPosixProtectFlags(access);
return mmap64(base_address, length, prot, MAP_PRIVATE | MAP_ANONYMOUS, handle,

int flags = MAP_SHARED;
if (base_address != nullptr) {
flags |= MAP_FIXED_NOREPLACE;
}

void* result = mmap(base_address, length, prot, flags, handle,
file_offset);

if (result == MAP_FAILED) {
return nullptr;
} else {
std::lock_guard<std::mutex> guard(g_mapped_file_ranges_mutex);
mapped_file_ranges.push_back({(size_t)result, (size_t)result + length});
return result;
}
}

bool UnmapFileView(FileMappingHandle handle, void* base_address,
size_t length) {
std::lock_guard<std::mutex> guard(g_mapped_file_ranges_mutex);
for (auto mapped_range = mapped_file_ranges.begin();
mapped_range != mapped_file_ranges.end();) {
if (mapped_range->region_begin == (size_t)base_address &&
mapped_range->region_end == (size_t)base_address + length) {
mapped_file_ranges.erase(mapped_range);
return munmap(base_address, length) == 0;
} else {
mapped_range++;
}
}
// TODO: Implement partial file unmapping.
assert_always("Error: Partial unmapping of files not yet supported.");
return munmap(base_address, length) == 0;
}

Expand Down

0 comments on commit 3e18402

Please sign in to comment.