Merge pull request #4281 from eljackjoestar-cmd/codex/reserve-direct-memory

perf(libkernel): commit Windows direct backing when mapped
This commit is contained in:
Dean 2026-10-12 23:49:42 +13:00 committed by GitHub
commit 7cb5238d53
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 37 additions and 1 deletions

View File

@ -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);

View File

@ -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];

View File

@ -291,6 +291,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;
@ -1834,6 +1862,7 @@ int main() {
CheckCheckedReleaseDirectMemory();
CheckAudioCoprocessorProtection();
CheckDirectMemoryFollowsPhysicalPages();
CheckSparseDirectMemoryBacking();
CheckReleaseDirectMemoryClearsMappings();
CheckReleaseDirectMemoryRejectsInvalidRanges();
CheckFixedMappingReplacesPartialOverlap();

View File

@ -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)) and the host `std::shared_mutex` objects in [Recompiler.cpp](../../core/shader/recompiler/Recompiler.cpp) are locked once when created. A new host `std::shared_mutex` used on Windows needs the same.
### 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: