fix: reliability improvements in WinServer/IPC subsystems
This commit is contained in:
@@ -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
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user