fix: reliability improvements in WinServer/IPC subsystems

This commit is contained in:
2026-05-14 15:31:28 +02:00
parent eac8feb62c
commit 1561ee1160
3 changed files with 15 additions and 19 deletions
+3 -3
View File
@@ -142,7 +142,7 @@ namespace WinServer {
FillSurfaceLocked(snapshot, w, h, InitialWindowPixel); FillSurfaceLocked(snapshot, w, h, InitialWindowPixel);
uint64_t userVa = 0; uint64_t userVa = 0;
if (Ipc::MapSurfaceForPid(live, ownerPid, ownerPml4, heapNext, userVa) != 0) { if (Ipc::MapSurfaceForPid(live, ownerPid, ownerPml4, heapNext, userVa, false) != 0) {
Ipc::ReleaseMailbox(mailbox, true, true); Ipc::ReleaseMailbox(mailbox, true, true);
Ipc::ReleaseSurface(snapshot); Ipc::ReleaseSurface(snapshot);
Ipc::ReleaseSurface(live); Ipc::ReleaseSurface(live);
@@ -242,7 +242,7 @@ namespace WinServer {
if (!slot.used || slot.snapshotSurface == nullptr) return 0; if (!slot.used || slot.snapshotSurface == nullptr) return 0;
uint64_t outVa = 0; uint64_t outVa = 0;
if (Ipc::MapSurfaceForPid(slot.snapshotSurface, callerPid, callerPml4, heapNext, outVa) != 0) { if (Ipc::MapSurfaceForPid(slot.snapshotSurface, callerPid, callerPml4, heapNext, outVa, false) != 0) {
return 0; return 0;
} }
return outVa; return outVa;
@@ -294,7 +294,7 @@ namespace WinServer {
Ipc::RetainSurface(newSnapshot); Ipc::RetainSurface(newSnapshot);
uint64_t newOwnerVa = 0; uint64_t newOwnerVa = 0;
if (Ipc::MapSurfaceForPid(newLive, callerPid, ownerPml4, heapNext, newOwnerVa) != 0) { if (Ipc::MapSurfaceForPid(newLive, callerPid, ownerPml4, heapNext, newOwnerVa, false) != 0) {
Ipc::ReleaseSurface(newSnapshot); Ipc::ReleaseSurface(newSnapshot);
Ipc::ReleaseSurface(newLive); Ipc::ReleaseSurface(newLive);
return -1; return -1;
+10 -15
View File
@@ -1806,7 +1806,8 @@ namespace Ipc {
return 0; return 0;
} }
int MapSurfaceForPid(Surface* surface, int pid, uint64_t pml4Phys, uint64_t& heapNext, uint64_t& outVa) { int MapSurfaceForPid(Surface* surface, int pid, uint64_t pml4Phys, uint64_t& heapNext,
uint64_t& outVa, bool reserveGrowthRange) {
if (surface == nullptr) return -1; if (surface == nullptr) return -1;
int slot = SlotForPid(pid); int slot = SlotForPid(pid);
@@ -1862,20 +1863,14 @@ namespace Ipc {
g_surfaceMaps[slot][mapIdx].numPages = numPages; g_surfaceMaps[slot][mapIdx].numPages = numPages;
surface->refs++; // inlined RetainRawObject — we already hold surface->lock surface->refs++; // inlined RetainRawObject — we already hold surface->lock
// Reserve the full surface address-range cap, not just the currently // Generic IPC surfaces can grow in place through ResizeSurface(), so
// mapped pages. ResizeSurface can grow this surface up to // their mapping must reserve the maximum VA range that a later grow
// MaxSurfacePages, and its grow path extends the existing VA range // can populate. Window-server surfaces are replaced rather than grown
// in-place by mapping new pages at baseVa + p*0x1000 for p beyond the // in place, so callers can opt out and avoid burning 32 MiB of process
// original size. If we only bumped heapNext by numPages*0x1000, any // VA on every window map/remap during a long desktop session.
// subsequent mapping (another surface, heap allocation, etc.) would uint32_t reservedPages = reserveGrowthRange ? MaxSurfacePages : numPages;
// sit at baseVa + numPages*0x1000 -- and a later grow would silently if (reservedPages < numPages) reservedPages = numPages;
// overwrite its PTEs. Reserving MaxSurfacePages*0x1000 (32 MiB) of heapNext += (uint64_t)reservedPages * 0x1000ULL;
// VA per mapping is cheap: 47-bit user VA gives 128 TiB of headroom,
// and at most MaxSurfaceMapsPerProcess (64) mappings per process
// means at most 2 GiB of reserved VA per process. Page tables are
// only populated for pages actually mapped; unused VA in the
// reservation costs nothing beyond the address-space slot.
heapNext += (uint64_t)MaxSurfacePages * 0x1000ULL;
outVa = baseVa; outVa = baseVa;
surface->lock.Release(); surface->lock.Release();
return 0; return 0;
+2 -1
View File
@@ -135,7 +135,8 @@ namespace Ipc {
uint32_t fillPixel); uint32_t fillPixel);
uint64_t MapSurfaceHandle(int handle); uint64_t MapSurfaceHandle(int handle);
int ResizeSurfaceHandle(int handle, uint64_t newSize); int ResizeSurfaceHandle(int handle, uint64_t newSize);
int MapSurfaceForPid(Surface* surface, int pid, uint64_t pml4Phys, uint64_t& heapNext, uint64_t& outVa); int MapSurfaceForPid(Surface* surface, int pid, uint64_t pml4Phys, uint64_t& heapNext,
uint64_t& outVa, bool reserveGrowthRange = true);
int UnmapSurfaceForPid(Surface* surface, int pid, uint64_t pml4Phys); int UnmapSurfaceForPid(Surface* surface, int pid, uint64_t pml4Phys);
ProcessObject* GetProcessObject(int pid); ProcessObject* GetProcessObject(int pid);