diff --git a/rpcs3/util/vm.hpp b/rpcs3/util/vm.hpp index f779ca86f4..0999941fcc 100644 --- a/rpcs3/util/vm.hpp +++ b/rpcs3/util/vm.hpp @@ -65,13 +65,13 @@ namespace utils ~shm(); // Map shared memory - u8* map(void* ptr, protection prot = protection::rw) const; + u8* map(void* ptr, protection prot = protection::rw, bool cow = false) const; // Attempt to map shared memory fix fixed pointer - u8* try_map(void* ptr, protection prot = protection::rw) const; + u8* try_map(void* ptr, protection prot = protection::rw, bool cow = false) const; // Map shared memory over reserved memory region, which is unsafe (non-atomic) under Win32 - u8* map_critical(void* ptr, protection prot = protection::rw); + u8* map_critical(void* ptr, protection prot = protection::rw, bool cow = false); // Map shared memory into its own storage (not mapped by default) u8* map_self(protection prot = protection::rw); diff --git a/rpcs3/util/vm_native.cpp b/rpcs3/util/vm_native.cpp index 7fdfd27e38..74f080656f 100644 --- a/rpcs3/util/vm_native.cpp +++ b/rpcs3/util/vm_native.cpp @@ -337,7 +337,7 @@ namespace utils #endif } - u8* shm::map(void* ptr, protection prot) const + u8* shm::map(void* ptr, protection prot, bool cow) const { #ifdef _WIN32 DWORD access = FILE_MAP_WRITE; @@ -353,6 +353,11 @@ namespace utils break; } + if (cow) + { + access |= FILE_MAP_COPY; + } + if (auto ret = static_cast(::MapViewOfFileEx(m_handle, access, 0, 0, m_size, ptr))) { if (prot != protection::rw && prot != protection::wx) @@ -374,7 +379,7 @@ namespace utils if (ptr64) { - const auto result = ::mmap(reinterpret_cast(ptr64), m_size, +prot, MAP_SHARED | MAP_FIXED, m_file, 0); + const auto result = ::mmap(reinterpret_cast(ptr64), m_size, +prot, (cow ? MAP_PRIVATE : MAP_SHARED) | MAP_FIXED, m_file, 0); return reinterpret_cast(result); } @@ -383,7 +388,7 @@ namespace utils const u64 res64 = reinterpret_cast(::mmap(reinterpret_cast(ptr64), m_size + 0xf000, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0)); const u64 aligned = utils::align(res64, 0x10000); - const auto result = ::mmap(reinterpret_cast(aligned), m_size, +prot, MAP_SHARED | MAP_FIXED, m_file, 0); + const auto result = ::mmap(reinterpret_cast(aligned), m_size, +prot, (cow ? MAP_PRIVATE : MAP_SHARED) | MAP_FIXED, m_file, 0); // Now cleanup remnants if (aligned > res64) @@ -401,15 +406,15 @@ namespace utils #endif } - u8* shm::try_map(void* ptr, protection prot) const + u8* shm::try_map(void* ptr, protection prot, bool cow) const { // Non-null pointer shall be specified const auto target = ensure(reinterpret_cast(reinterpret_cast(ptr) & -0x10000)); #ifdef _WIN32 - return this->map(target, prot); + return this->map(target, prot, cow); #else - const auto result = reinterpret_cast(::mmap(reinterpret_cast(target), m_size, +prot, MAP_SHARED, m_file, 0)); + const auto result = reinterpret_cast(::mmap(reinterpret_cast(target), m_size, +prot, (cow ? MAP_PRIVATE : MAP_SHARED), m_file, 0)); if (result == reinterpret_cast(UINT64_MAX)) { @@ -420,7 +425,7 @@ namespace utils #endif } - u8* shm::map_critical(void* ptr, protection prot) + u8* shm::map_critical(void* ptr, protection prot, bool cow) { const auto target = reinterpret_cast(reinterpret_cast(ptr) & -0x10000); @@ -445,7 +450,7 @@ namespace utils } #endif - return this->map(target, prot); + return this->map(target, prot, cow); } u8* shm::map_self(protection prot)