1010#include " xenia/base/memory.h"
1111
1212#include < fcntl.h>
13+ #include < semaphore.h>
1314#include < sys/mman.h>
1415#include < unistd.h>
1516#include < cstddef>
17+ #include < mutex>
1618
1719#include " xenia/base/math.h"
1820#include " xenia/base/platform.h"
@@ -81,12 +83,45 @@ uint32_t ToPosixProtectFlags(PageAccess access) {
8183
8284bool IsWritableExecutableMemorySupported () { return true ; }
8385
86+ struct MappedFileRange {
87+ size_t region_begin;
88+ size_t region_end;
89+ };
90+
91+ std::vector<struct MappedFileRange > mapped_file_ranges;
92+ std::mutex g_mapped_file_ranges_mutex;
93+
8494void * AllocFixed (void * base_address, size_t length,
8595 AllocationType allocation_type, PageAccess access) {
8696 // mmap does not support reserve / commit, so ignore allocation_type.
8797 uint32_t prot = ToPosixProtectFlags (access);
88- void * result = mmap (base_address, length, prot,
89- MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1 , 0 );
98+
99+ const size_t region_begin = (size_t )base_address;
100+ const size_t region_end = (size_t )base_address + length;
101+
102+ std::lock_guard<std::mutex> guard (g_mapped_file_ranges_mutex);
103+ for (const auto & mapped_range : mapped_file_ranges) {
104+ // Check if the allocation is within this range...
105+ if (region_begin >= mapped_range.region_begin &&
106+ region_end <= mapped_range.region_end ) {
107+ bool should_protect = (((uint8_t )allocation_type & 2 ) == 2 );
108+
109+ if (should_protect) {
110+ if (Protect (base_address, length, access)) {
111+ return base_address;
112+ }
113+ } else if ((((uint8_t )allocation_type & 1 ) == 1 )) {
114+ return base_address;
115+ }
116+ }
117+ }
118+
119+ int flags = MAP_PRIVATE | MAP_ANONYMOUS;
120+ if (base_address != nullptr ) {
121+ flags |= MAP_FIXED_NOREPLACE;
122+ }
123+ void * result = mmap (base_address, length, prot, flags, -1 , 0 );
124+
90125 if (result == MAP_FAILED) {
91126 return nullptr ;
92127 } else {
@@ -96,6 +131,17 @@ void* AllocFixed(void* base_address, size_t length,
96131
97132bool DeallocFixed (void * base_address, size_t length,
98133 DeallocationType deallocation_type) {
134+ const size_t region_begin = (size_t )base_address;
135+ const size_t region_end = (size_t )base_address + length;
136+
137+ std::lock_guard<std::mutex> guard (g_mapped_file_ranges_mutex);
138+ for (const auto & mapped_range : mapped_file_ranges) {
139+ if (region_begin >= mapped_range.region_begin &&
140+ region_end <= mapped_range.region_end ) {
141+ return Protect (base_address, length, PageAccess::kNoAccess );
142+ }
143+ }
144+
99145 return munmap (base_address, length) == 0 ;
100146}
101147
@@ -178,12 +224,39 @@ void CloseFileMappingHandle(FileMappingHandle handle,
178224void * MapFileView (FileMappingHandle handle, void * base_address, size_t length,
179225 PageAccess access, size_t file_offset) {
180226 uint32_t prot = ToPosixProtectFlags (access);
181- return mmap64 (base_address, length, prot, MAP_PRIVATE | MAP_ANONYMOUS, handle,
227+
228+ int flags = MAP_SHARED;
229+ if (base_address != nullptr ) {
230+ flags |= MAP_FIXED_NOREPLACE;
231+ }
232+
233+ void * result = mmap (base_address, length, prot, flags, handle,
182234 file_offset);
235+
236+ if (result == MAP_FAILED) {
237+ return nullptr ;
238+ } else {
239+ std::lock_guard<std::mutex> guard (g_mapped_file_ranges_mutex);
240+ mapped_file_ranges.push_back ({(size_t )result, (size_t )result + length});
241+ return result;
242+ }
183243}
184244
185245bool UnmapFileView (FileMappingHandle handle, void * base_address,
186246 size_t length) {
247+ std::lock_guard<std::mutex> guard (g_mapped_file_ranges_mutex);
248+ for (auto mapped_range = mapped_file_ranges.begin ();
249+ mapped_range != mapped_file_ranges.end ();) {
250+ if (mapped_range->region_begin == (size_t )base_address &&
251+ mapped_range->region_end == (size_t )base_address + length) {
252+ mapped_file_ranges.erase (mapped_range);
253+ return munmap (base_address, length) == 0 ;
254+ } else {
255+ mapped_range++;
256+ }
257+ }
258+ // TODO: Implement partial file unmapping.
259+ assert_always (" Error: Partial unmapping of files not yet supported." );
187260 return munmap (base_address, length) == 0 ;
188261}
189262
0 commit comments