Skip to content

Commit

Permalink
Common: Allow non-file mappings in SharedMemoryMappingArea
Browse files Browse the repository at this point in the history
  • Loading branch information
TellowKrinkle committed Oct 7, 2024
1 parent f36db1d commit 6c262b8
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 14 deletions.
2 changes: 1 addition & 1 deletion common/HostSys.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ namespace PageFaultHandler
class SharedMemoryMappingArea
{
public:
static std::unique_ptr<SharedMemoryMappingArea> Create(size_t size);
static std::unique_ptr<SharedMemoryMappingArea> Create(size_t size, bool jit = false);

~SharedMemoryMappingArea();

Expand Down
32 changes: 24 additions & 8 deletions common/Linux/LnxHostSys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,16 @@ SharedMemoryMappingArea::~SharedMemoryMappingArea()
}


std::unique_ptr<SharedMemoryMappingArea> SharedMemoryMappingArea::Create(size_t size)
std::unique_ptr<SharedMemoryMappingArea> SharedMemoryMappingArea::Create(size_t size, bool jit)
{
pxAssertRel(Common::IsAlignedPow2(size, __pagesize), "Size is page aligned");

void* alloc = mmap(nullptr, size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
uint flags = MAP_ANONYMOUS | MAP_PRIVATE;
#ifdef __APPLE__
if (jit)
flags |= MAP_JIT;
#endif
void* alloc = mmap(nullptr, size, PROT_NONE, flags, -1, 0);
if (alloc == MAP_FAILED)
return nullptr;

Expand All @@ -216,15 +221,26 @@ u8* SharedMemoryMappingArea::Map(void* file_handle, size_t file_offset, void* ma
{
pxAssert(static_cast<u8*>(map_base) >= m_base_ptr && static_cast<u8*>(map_base) < (m_base_ptr + m_size));

// MAP_FIXED is okay here, since we've reserved the entire region, and *want* to overwrite the mapping.
const uint lnxmode = LinuxProt(mode);
void* const ptr = mmap(map_base, map_size, lnxmode, MAP_SHARED | MAP_FIXED,
static_cast<int>(reinterpret_cast<intptr_t>(file_handle)), static_cast<off_t>(file_offset));
if (ptr == MAP_FAILED)
return nullptr;
if (file_handle)
{
const int fd = static_cast<int>(reinterpret_cast<intptr_t>(file_handle));
// MAP_FIXED is okay here, since we've reserved the entire region, and *want* to overwrite the mapping.
void* const ptr = mmap(map_base, map_size, lnxmode, MAP_SHARED | MAP_FIXED, fd, static_cast<off_t>(file_offset));
if (ptr == MAP_FAILED)
return nullptr;
}
else
{
// macOS doesn't seem to allow MAP_JIT with MAP_FIXED
// So we do the MAP_JIT in the allocation, and just mprotect here
// Note that this will only work the first time for a given region
if (mprotect(map_base, map_size, lnxmode) < 0)
return nullptr;
}

m_num_mappings++;
return static_cast<u8*>(ptr);
return static_cast<u8*>(map_base);
}

bool SharedMemoryMappingArea::Unmap(void* map_base, size_t map_size)
Expand Down
21 changes: 16 additions & 5 deletions common/Windows/WinHostSys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ SharedMemoryMappingArea::PlaceholderMap::iterator SharedMemoryMappingArea::FindP
return m_placeholder_ranges.end();
}

std::unique_ptr<SharedMemoryMappingArea> SharedMemoryMappingArea::Create(size_t size)
std::unique_ptr<SharedMemoryMappingArea> SharedMemoryMappingArea::Create(size_t size, bool jit)
{
pxAssertRel(Common::IsAlignedPow2(size, __pagesize), "Size is page aligned");

Expand Down Expand Up @@ -241,11 +241,22 @@ u8* SharedMemoryMappingArea::Map(void* file_handle, size_t file_offset, void* ma
}

// actually do the mapping, replacing the placeholder on the range
if (!MapViewOfFile3(static_cast<HANDLE>(file_handle), GetCurrentProcess(),
map_base, file_offset, map_size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, nullptr, 0))
if (file_handle)
{
Console.Error("(SharedMemoryMappingArea) MapViewOfFile3() failed: %u", GetLastError());
return nullptr;
if (!MapViewOfFile3(static_cast<HANDLE>(file_handle), GetCurrentProcess(),
map_base, file_offset, map_size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, nullptr, 0))
{
Console.Error("(SharedMemoryMappingArea) MapViewOfFile3() failed: %u", GetLastError());
return nullptr;
}
}
else
{
if (!VirtualAlloc2(GetCurrentProcess(), map_base, map_size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, nullptr, 0))
{
Console.Error("(SharedMemoryMappingArea) VirtualAlloc2() failed: %u", GetLastError());
return nullptr;
}
}

const DWORD prot = ConvertToWinApi(mode);
Expand Down

0 comments on commit 6c262b8

Please sign in to comment.