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 System.Collections.Generic;
using System.Diagnostics;
namespace Ryujinx.HLE.HOS.Kernel.Memory
@ -12,6 +13,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
public ulong EndAddr => Address + Size;
private readonly ushort[] _pageReferenceCounts;
public Dictionary<ulong, List<KPageList>> Regions { get; } = new Dictionary<ulong, List<KPageList>>();
public KMemoryRegionManager(ulong address, ulong size, ulong endAddr)
{
@ -25,7 +27,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
_pageHeap.UpdateUsedSize();
}
public Result AllocatePages(out KPageList pageList, ulong pagesCount)
public Result AllocatePages(out KPageList pageList, ulong pagesCount, ulong pid)
{
if (pagesCount == 0)
{
@ -36,7 +38,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
lock (_pageHeap)
{
Result result = AllocatePagesImpl(out pageList, pagesCount, false);
Result result = AllocatePagesImpl(out pageList, pagesCount, false, pid);
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();
@ -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)
{
FreePages(pageList);
@ -116,9 +127,22 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
return KernelResult.OutOfMemory;
}
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)
{
int heapIndex = KPageHeap.GetAlignedBlockIndex(pagesCount, alignPages);

View File

@ -523,7 +523,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
ulong regionPagesCount,
MemoryState state,
KMemoryPermission permission,
out ulong address)
out ulong address, ulong pid)
{
address = 0;
@ -561,7 +561,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
}
else
{
result = AllocateAndMapPages(address, pagesCount, permission);
result = AllocateAndMapPages(address, pagesCount, permission, pid);
}
if (result != Result.Success)
@ -575,7 +575,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
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;
@ -596,7 +596,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
return KernelResult.OutOfResource;
}
Result result = AllocateAndMapPages(address, pagesCount, permission);
Result result = AllocateAndMapPages(address, pagesCount, permission,pid);
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();
Result result = region.AllocatePages(out KPageList pageList, pagesCount);
Result result = region.AllocatePages(out KPageList pageList, pagesCount,pid);
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;
@ -768,7 +768,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
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));
@ -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;
@ -1340,7 +1340,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
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));
@ -2884,7 +2884,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
return pa - DramMemoryMap.DramBase;
}
protected KMemoryRegionManager GetMemoryRegionManager()
public KMemoryRegionManager GetMemoryRegionManager()
{
return Context.MemoryManager.MemoryRegions[(int)_memRegion];
}

View File

@ -268,7 +268,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
codeAddress,
codePagesCount,
MemoryState.CodeStatic,
KMemoryPermission.None);
KMemoryPermission.None, Pid);
if (result != Result.Success)
{
@ -437,7 +437,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
regionPagesCount,
MemoryState.ThreadLocal,
KMemoryPermission.ReadAndWrite,
out ulong tlsPageVa);
out ulong tlsPageVa,Pid);
if (result != Result.Success)
{
@ -607,7 +607,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
regionPagesCount,
MemoryState.Stack,
KMemoryPermission.ReadAndWrite,
out ulong stackBottom);
out ulong stackBottom,Pid);
if (result != Result.Success)
{
@ -872,6 +872,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
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;
bool shallTerminate = false;

View File

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

View File

@ -169,7 +169,7 @@ namespace Ryujinx.HLE.Loaders.Processes
MemoryRegion memoryRegion = kip.UsesSecureMemory ? MemoryRegion.Service : MemoryRegion.Application;
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)
{
Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");