mirror of
https://git.743378673.xyz/MeloNX/MeloNX.git
synced 2025-07-29 09:57:09 +02:00
Move solution and projects to src
This commit is contained in:
parent
cd124bda58
commit
cee7121058
3466 changed files with 55 additions and 55 deletions
242
src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryRegionManager.cs
Normal file
242
src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryRegionManager.cs
Normal file
|
@ -0,0 +1,242 @@
|
|||
using Ryujinx.Horizon.Common;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||
{
|
||||
class KMemoryRegionManager
|
||||
{
|
||||
private readonly KPageHeap _pageHeap;
|
||||
|
||||
public ulong Address { get; }
|
||||
public ulong Size { get; }
|
||||
public ulong EndAddr => Address + Size;
|
||||
|
||||
private readonly ushort[] _pageReferenceCounts;
|
||||
|
||||
public KMemoryRegionManager(ulong address, ulong size, ulong endAddr)
|
||||
{
|
||||
Address = address;
|
||||
Size = size;
|
||||
|
||||
_pageReferenceCounts = new ushort[size / KPageTableBase.PageSize];
|
||||
|
||||
_pageHeap = new KPageHeap(address, size);
|
||||
_pageHeap.Free(address, size / KPageTableBase.PageSize);
|
||||
_pageHeap.UpdateUsedSize();
|
||||
}
|
||||
|
||||
public Result AllocatePages(out KPageList pageList, ulong pagesCount)
|
||||
{
|
||||
if (pagesCount == 0)
|
||||
{
|
||||
pageList = new KPageList();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
lock (_pageHeap)
|
||||
{
|
||||
Result result = AllocatePagesImpl(out pageList, pagesCount, false);
|
||||
|
||||
if (result == Result.Success)
|
||||
{
|
||||
foreach (var node in pageList)
|
||||
{
|
||||
IncrementPagesReferenceCount(node.Address, node.PagesCount);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public ulong AllocatePagesContiguous(KernelContext context, ulong pagesCount, bool backwards)
|
||||
{
|
||||
if (pagesCount == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
lock (_pageHeap)
|
||||
{
|
||||
ulong address = AllocatePagesContiguousImpl(pagesCount, 1, backwards);
|
||||
|
||||
if (address != 0)
|
||||
{
|
||||
IncrementPagesReferenceCount(address, pagesCount);
|
||||
context.CommitMemory(address - DramMemoryMap.DramBase, pagesCount * KPageTableBase.PageSize);
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
}
|
||||
|
||||
private Result AllocatePagesImpl(out KPageList pageList, ulong pagesCount, bool random)
|
||||
{
|
||||
pageList = new KPageList();
|
||||
|
||||
int heapIndex = KPageHeap.GetBlockIndex(pagesCount);
|
||||
|
||||
if (heapIndex < 0)
|
||||
{
|
||||
return KernelResult.OutOfMemory;
|
||||
}
|
||||
|
||||
for (int index = heapIndex; index >= 0; index--)
|
||||
{
|
||||
ulong pagesPerAlloc = KPageHeap.GetBlockPagesCount(index);
|
||||
|
||||
while (pagesCount >= pagesPerAlloc)
|
||||
{
|
||||
ulong allocatedBlock = _pageHeap.AllocateBlock(index, random);
|
||||
|
||||
if (allocatedBlock == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Result result = pageList.AddRange(allocatedBlock, pagesPerAlloc);
|
||||
|
||||
if (result != Result.Success)
|
||||
{
|
||||
FreePages(pageList);
|
||||
_pageHeap.Free(allocatedBlock, pagesPerAlloc);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
pagesCount -= pagesPerAlloc;
|
||||
}
|
||||
}
|
||||
|
||||
if (pagesCount != 0)
|
||||
{
|
||||
FreePages(pageList);
|
||||
|
||||
return KernelResult.OutOfMemory;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private ulong AllocatePagesContiguousImpl(ulong pagesCount, ulong alignPages, bool random)
|
||||
{
|
||||
int heapIndex = KPageHeap.GetAlignedBlockIndex(pagesCount, alignPages);
|
||||
|
||||
ulong allocatedBlock = _pageHeap.AllocateBlock(heapIndex, random);
|
||||
|
||||
if (allocatedBlock == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ulong allocatedPages = KPageHeap.GetBlockPagesCount(heapIndex);
|
||||
|
||||
if (allocatedPages > pagesCount)
|
||||
{
|
||||
_pageHeap.Free(allocatedBlock + pagesCount * KPageTableBase.PageSize, allocatedPages - pagesCount);
|
||||
}
|
||||
|
||||
return allocatedBlock;
|
||||
}
|
||||
|
||||
public void FreePage(ulong address)
|
||||
{
|
||||
lock (_pageHeap)
|
||||
{
|
||||
_pageHeap.Free(address, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void FreePages(KPageList pageList)
|
||||
{
|
||||
lock (_pageHeap)
|
||||
{
|
||||
foreach (KPageNode pageNode in pageList)
|
||||
{
|
||||
_pageHeap.Free(pageNode.Address, pageNode.PagesCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void FreePages(ulong address, ulong pagesCount)
|
||||
{
|
||||
lock (_pageHeap)
|
||||
{
|
||||
_pageHeap.Free(address, pagesCount);
|
||||
}
|
||||
}
|
||||
|
||||
public ulong GetFreePages()
|
||||
{
|
||||
lock (_pageHeap)
|
||||
{
|
||||
return _pageHeap.GetFreePagesCount();
|
||||
}
|
||||
}
|
||||
|
||||
public void IncrementPagesReferenceCount(ulong address, ulong pagesCount)
|
||||
{
|
||||
ulong index = GetPageOffset(address);
|
||||
ulong endIndex = index + pagesCount;
|
||||
|
||||
while (index < endIndex)
|
||||
{
|
||||
ushort referenceCount = ++_pageReferenceCounts[index];
|
||||
Debug.Assert(referenceCount >= 1);
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
public void DecrementPagesReferenceCount(ulong address, ulong pagesCount)
|
||||
{
|
||||
ulong index = GetPageOffset(address);
|
||||
ulong endIndex = index + pagesCount;
|
||||
|
||||
ulong freeBaseIndex = 0;
|
||||
ulong freePagesCount = 0;
|
||||
|
||||
while (index < endIndex)
|
||||
{
|
||||
Debug.Assert(_pageReferenceCounts[index] > 0);
|
||||
ushort referenceCount = --_pageReferenceCounts[index];
|
||||
|
||||
if (referenceCount == 0)
|
||||
{
|
||||
if (freePagesCount != 0)
|
||||
{
|
||||
freePagesCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
freeBaseIndex = index;
|
||||
freePagesCount = 1;
|
||||
}
|
||||
}
|
||||
else if (freePagesCount != 0)
|
||||
{
|
||||
FreePages(Address + freeBaseIndex * KPageTableBase.PageSize, freePagesCount);
|
||||
freePagesCount = 0;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (freePagesCount != 0)
|
||||
{
|
||||
FreePages(Address + freeBaseIndex * KPageTableBase.PageSize, freePagesCount);
|
||||
}
|
||||
}
|
||||
|
||||
public ulong GetPageOffset(ulong address)
|
||||
{
|
||||
return (address - Address) / KPageTableBase.PageSize;
|
||||
}
|
||||
|
||||
public ulong GetPageOffsetFromEnd(ulong address)
|
||||
{
|
||||
return (EndAddr - address) / KPageTableBase.PageSize;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue