perf(libkernel): commit Windows direct backing when mapped
This commit is contained in:
parent
d146ec1b66
commit
9873fae1ef
|
|
@ -82,6 +82,9 @@ public:
|
|||
split(cursor + done, pageBytes);
|
||||
void* page = reinterpret_cast<void*>(cursor + done);
|
||||
if (!map(section, GetCurrentProcess(), page, offset + done, pageBytes, MEM_REPLACE_PLACEHOLDER, PAGE_EXECUTE_READWRITE, nullptr, 0)) fail("map shared guest page");
|
||||
MEMORY_BASIC_INFORMATION memory{};
|
||||
if (VirtualQuery(page, &memory, sizeof(memory)) != sizeof(memory)) fail("query shared guest page");
|
||||
if (memory.State == MEM_RESERVE && !VirtualAlloc(page, pageBytes, MEM_COMMIT, PAGE_EXECUTE_READWRITE)) fail("commit shared guest page");
|
||||
DWORD previous;
|
||||
if (!VirtualProtect(page, pageBytes, protection, &previous)) fail("protect shared guest page");
|
||||
const auto key = std::make_pair(reinterpret_cast<std::uintptr_t>(section), offset + done);
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ public:
|
|||
#ifdef _WIN32
|
||||
static_cast<void>(start);
|
||||
const auto size = static_cast<std::uint64_t>(bytes);
|
||||
section = CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_EXECUTE_READWRITE, static_cast<DWORD>(size >> 32), static_cast<DWORD>(size), nullptr);
|
||||
section = CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_EXECUTE_READWRITE | SEC_RESERVE, static_cast<DWORD>(size >> 32), static_cast<DWORD>(size), nullptr);
|
||||
if (!section) {
|
||||
const auto error = static_cast<int>(GetLastError());
|
||||
char message[96];
|
||||
|
|
|
|||
|
|
@ -289,6 +289,34 @@ static void CheckDirectMemoryFollowsPhysicalPages() {
|
|||
Require(sceKernelReleaseDirectMemory(again, page * 2) == 0);
|
||||
}
|
||||
|
||||
static void CheckSparseDirectMemoryBacking() {
|
||||
constexpr std::size_t page = 0x4000;
|
||||
constexpr std::size_t size = 256u * 1024u * 1024u;
|
||||
std::int64_t physical = 0;
|
||||
Require(sceKernelAllocateDirectMemory(0, 0x7fffffffffll, size, 0, 0, &physical) == 0);
|
||||
void* first = nullptr;
|
||||
void* last = nullptr;
|
||||
Require(sceKernelMapDirectMemory(&first, page, 3, 0, physical, 0) == 0);
|
||||
Require(sceKernelMapDirectMemory(&last, page, 3, 0, physical + size - page, 0) == 0);
|
||||
auto* firstBytes = static_cast<unsigned char*>(first);
|
||||
auto* lastBytes = static_cast<unsigned char*>(last);
|
||||
Require(firstBytes[0] == 0 && firstBytes[page - 1] == 0 && lastBytes[0] == 0 && lastBytes[page - 1] == 0);
|
||||
firstBytes[0] = 17;
|
||||
lastBytes[page - 1] = 29;
|
||||
void* alias = nullptr;
|
||||
Require(sceKernelMapDirectMemory(&alias, page, 3, 0, physical + size - page, 0) == 0);
|
||||
auto* aliasBytes = static_cast<unsigned char*>(alias);
|
||||
Require(aliasBytes[page - 1] == 29 && aliasBytes[0] == 0);
|
||||
aliasBytes[page - 1] = 41;
|
||||
Require(lastBytes[page - 1] == 41 && firstBytes[0] == 17);
|
||||
Require(sceKernelMunmap(last, page) == 0 && sceKernelMunmap(alias, page) == 0);
|
||||
last = nullptr;
|
||||
Require(sceKernelMapDirectMemory(&last, page, 3, 0, physical + size - page, 0) == 0);
|
||||
Require(static_cast<unsigned char*>(last)[page - 1] == 41);
|
||||
Require(sceKernelMunmap(first, page) == 0 && sceKernelMunmap(last, page) == 0);
|
||||
Require(sceKernelReleaseDirectMemory(physical, size) == 0);
|
||||
}
|
||||
|
||||
static void CheckReleaseDirectMemoryClearsMappings() {
|
||||
constexpr std::size_t page = 0x4000;
|
||||
std::int64_t phys = 0;
|
||||
|
|
@ -1715,6 +1743,7 @@ int main() {
|
|||
CheckCheckedReleaseDirectMemory();
|
||||
CheckAudioCoprocessorProtection();
|
||||
CheckDirectMemoryFollowsPhysicalPages();
|
||||
CheckSparseDirectMemoryBacking();
|
||||
CheckReleaseDirectMemoryClearsMappings();
|
||||
CheckReleaseDirectMemoryRejectsInvalidRanges();
|
||||
CheckFixedMappingReplacesPartialOverlap();
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@
|
|||
- libwinpthread-1.dll
|
||||
- winpthreads initializes a statically initialized rwlock on its first lock and fails a concurrent first lock with `EINVAL`, which `std::shared_mutex` and `std::shared_timed_mutex` ignore, so that lock does not exclude. Guest rwlocks ([Pthread.hpp](../../core/libs/prx/libkernel/Pthread/include/Pthread.hpp)) are locked once when created. The host `std::shared_mutex` objects in [Recompiler.cpp](../../core/shader/recompiler/Recompiler.cpp) and [GuestWriteWatch.cpp](../../core/libs/prx/libc/src/GuestWriteWatch.cpp) are not, and can still race on their first contended use.
|
||||
|
||||
### Direct memory
|
||||
|
||||
- Windows direct-memory backing reserves a paging-file section and commits each mapped guest page before setting its protection. Committed physical contents remain in the section across unmap/remap and are released when the backing and its remaining views are destroyed; commitment is not recovered merely by unmapping a page. Linux retains its existing backing. Peak gameplay memory and Windows versions other than the tested host remain unverified.
|
||||
|
||||
### Silent stubs
|
||||
|
||||
Throughout the project, every function at every stage either **does exactly what it's supposed to or throws an exception**. Everywhere... except:
|
||||
|
|
|
|||
Loading…
Reference in New Issue