feat: free up pages from terminated applets

This commit is contained in:
Jacobwasbeast 2025-02-18 13:34:53 -06:00
parent a9854ec30d
commit f2cf73f145
5 changed files with 49 additions and 20 deletions

View File

@ -1,4 +1,5 @@
using Ryujinx.Horizon.Common; using Ryujinx.Horizon.Common;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
namespace Ryujinx.HLE.HOS.Kernel.Memory namespace Ryujinx.HLE.HOS.Kernel.Memory
@ -12,6 +13,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
public ulong EndAddr => Address + Size; public ulong EndAddr => Address + Size;
private readonly ushort[] _pageReferenceCounts; private readonly ushort[] _pageReferenceCounts;
public Dictionary<ulong, List<KPageList>> Regions { get; } = new Dictionary<ulong, List<KPageList>>();
public KMemoryRegionManager(ulong address, ulong size, ulong endAddr) public KMemoryRegionManager(ulong address, ulong size, ulong endAddr)
{ {
@ -25,7 +27,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
_pageHeap.UpdateUsedSize(); _pageHeap.UpdateUsedSize();
} }
public Result AllocatePages(out KPageList pageList, ulong pagesCount) public Result AllocatePages(out KPageList pageList, ulong pagesCount, ulong pid)
{ {
if (pagesCount == 0) if (pagesCount == 0)
{ {
@ -36,7 +38,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
lock (_pageHeap) lock (_pageHeap)
{ {
Result result = AllocatePagesImpl(out pageList, pagesCount, false); Result result = AllocatePagesImpl(out pageList, pagesCount, false, pid);
if (result == Result.Success) if (result == Result.Success)
{ {
@ -71,7 +73,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
} }
} }
private Result AllocatePagesImpl(out KPageList pageList, ulong pagesCount, bool random) private Result AllocatePagesImpl(out KPageList pageList, ulong pagesCount, bool random, ulong pid)
{ {
pageList = new KPageList(); pageList = new KPageList();
@ -109,6 +111,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
} }
} }
if (Regions.ContainsKey(pid))
{
Regions[pid].Add(pageList);
}
else
{
Regions.Add(pid, new List<KPageList>() { pageList });
}
if (pagesCount != 0) if (pagesCount != 0)
{ {
FreePages(pageList); FreePages(pageList);
@ -116,9 +127,22 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
return KernelResult.OutOfMemory; return KernelResult.OutOfMemory;
} }
return Result.Success; return Result.Success;
} }
public void ClearFromPid(ulong pid)
{
if (Regions.TryGetValue(pid, out List<KPageList> pageLists))
{
foreach (KPageList pageList in pageLists)
{
FreePages(pageList);
}
Regions.Remove(pid);
}
}
private ulong AllocatePagesContiguousImpl(ulong pagesCount, ulong alignPages, bool random) private ulong AllocatePagesContiguousImpl(ulong pagesCount, ulong alignPages, bool random)
{ {
int heapIndex = KPageHeap.GetAlignedBlockIndex(pagesCount, alignPages); int heapIndex = KPageHeap.GetAlignedBlockIndex(pagesCount, alignPages);

View File

@ -523,7 +523,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
ulong regionPagesCount, ulong regionPagesCount,
MemoryState state, MemoryState state,
KMemoryPermission permission, KMemoryPermission permission,
out ulong address) out ulong address, ulong pid)
{ {
address = 0; address = 0;
@ -561,7 +561,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
} }
else else
{ {
result = AllocateAndMapPages(address, pagesCount, permission); result = AllocateAndMapPages(address, pagesCount, permission, pid);
} }
if (result != Result.Success) if (result != Result.Success)
@ -575,7 +575,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
return Result.Success; return Result.Success;
} }
public Result MapPages(ulong address, ulong pagesCount, MemoryState state, KMemoryPermission permission) public Result MapPages(ulong address, ulong pagesCount, MemoryState state, KMemoryPermission permission, ulong pid)
{ {
ulong size = pagesCount * PageSize; ulong size = pagesCount * PageSize;
@ -596,7 +596,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
return KernelResult.OutOfResource; return KernelResult.OutOfResource;
} }
Result result = AllocateAndMapPages(address, pagesCount, permission); Result result = AllocateAndMapPages(address, pagesCount, permission,pid);
if (result == Result.Success) if (result == Result.Success)
{ {
@ -607,11 +607,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
} }
} }
private Result AllocateAndMapPages(ulong address, ulong pagesCount, KMemoryPermission permission) private Result AllocateAndMapPages(ulong address, ulong pagesCount, KMemoryPermission permission, ulong pid)
{ {
KMemoryRegionManager region = GetMemoryRegionManager(); KMemoryRegionManager region = GetMemoryRegionManager();
Result result = region.AllocatePages(out KPageList pageList, pagesCount); Result result = region.AllocatePages(out KPageList pageList, pagesCount,pid);
if (result != Result.Success) if (result != Result.Success)
{ {
@ -738,7 +738,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
} }
} }
public Result SetHeapSize(ulong size, out ulong address) public Result SetHeapSize(ulong size, out ulong address, ulong pid)
{ {
address = 0; address = 0;
@ -768,7 +768,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
KMemoryRegionManager region = GetMemoryRegionManager(); KMemoryRegionManager region = GetMemoryRegionManager();
Result result = region.AllocatePages(out KPageList pageList, pagesCount); Result result = region.AllocatePages(out KPageList pageList, pagesCount, pid);
using OnScopeExit _ = new(() => pageList.DecrementPagesReferenceCount(Context.MemoryManager)); using OnScopeExit _ = new(() => pageList.DecrementPagesReferenceCount(Context.MemoryManager));
@ -1305,7 +1305,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
} }
} }
public Result MapPhysicalMemory(ulong address, ulong size) public Result MapPhysicalMemory(ulong address, ulong size, ulong pid)
{ {
ulong endAddr = address + size; ulong endAddr = address + size;
@ -1340,7 +1340,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
KMemoryRegionManager region = GetMemoryRegionManager(); KMemoryRegionManager region = GetMemoryRegionManager();
Result result = region.AllocatePages(out KPageList pageList, remainingPages); Result result = region.AllocatePages(out KPageList pageList, remainingPages, pid);
using OnScopeExit _ = new(() => pageList.DecrementPagesReferenceCount(Context.MemoryManager)); using OnScopeExit _ = new(() => pageList.DecrementPagesReferenceCount(Context.MemoryManager));
@ -2884,7 +2884,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
return pa - DramMemoryMap.DramBase; return pa - DramMemoryMap.DramBase;
} }
protected KMemoryRegionManager GetMemoryRegionManager() public KMemoryRegionManager GetMemoryRegionManager()
{ {
return Context.MemoryManager.MemoryRegions[(int)_memRegion]; return Context.MemoryManager.MemoryRegions[(int)_memRegion];
} }

View File

@ -268,7 +268,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
codeAddress, codeAddress,
codePagesCount, codePagesCount,
MemoryState.CodeStatic, MemoryState.CodeStatic,
KMemoryPermission.None); KMemoryPermission.None, Pid);
if (result != Result.Success) if (result != Result.Success)
{ {
@ -437,7 +437,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
regionPagesCount, regionPagesCount,
MemoryState.ThreadLocal, MemoryState.ThreadLocal,
KMemoryPermission.ReadAndWrite, KMemoryPermission.ReadAndWrite,
out ulong tlsPageVa); out ulong tlsPageVa,Pid);
if (result != Result.Success) if (result != Result.Success)
{ {
@ -607,7 +607,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
regionPagesCount, regionPagesCount,
MemoryState.Stack, MemoryState.Stack,
KMemoryPermission.ReadAndWrite, KMemoryPermission.ReadAndWrite,
out ulong stackBottom); out ulong stackBottom,Pid);
if (result != Result.Success) if (result != Result.Success)
{ {
@ -872,6 +872,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public Result Terminate() public Result Terminate()
{ {
if (Switch.Shared.System.WindowSystem.GetByAruId(Pid) != null)
{
Logger.Info?.Print(LogClass.Service, $"Attempting to terminate a running application window system for PID {Pid}");
MemoryManager.GetMemoryRegionManager().ClearFromPid(Pid);
}
Result result; Result result;
bool shallTerminate = false; bool shallTerminate = false;

View File

@ -897,7 +897,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
KProcess process = KernelStatic.GetCurrentProcess(); KProcess process = KernelStatic.GetCurrentProcess();
return process.MemoryManager.SetHeapSize(size, out address); return process.MemoryManager.SetHeapSize(size, out address, process.Pid);
} }
[Svc(2)] [Svc(2)]
@ -1364,7 +1364,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
KProcess process = KernelStatic.GetCurrentProcess(); KProcess process = KernelStatic.GetCurrentProcess();
return process.MemoryManager.MapPhysicalMemory(address, size); return process.MemoryManager.MapPhysicalMemory(address, size, process.Pid);
} }
[Svc(0x2d)] [Svc(0x2d)]

View File

@ -169,7 +169,7 @@ namespace Ryujinx.HLE.Loaders.Processes
MemoryRegion memoryRegion = kip.UsesSecureMemory ? MemoryRegion.Service : MemoryRegion.Application; MemoryRegion memoryRegion = kip.UsesSecureMemory ? MemoryRegion.Service : MemoryRegion.Application;
KMemoryRegionManager region = context.MemoryManager.MemoryRegions[(int)memoryRegion]; KMemoryRegionManager region = context.MemoryManager.MemoryRegions[(int)memoryRegion];
Result result = region.AllocatePages(out KPageList pageList, (ulong)codePagesCount); Result result = region.AllocatePages(out KPageList pageList, (ulong)codePagesCount, 0);
if (result != Result.Success) if (result != Result.Success)
{ {
Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\"."); Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");