aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs')
-rw-r--r--src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs
new file mode 100644
index 00000000..6d0a1658
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs
@@ -0,0 +1,65 @@
+using Ryujinx.HLE.HOS.Kernel.Common;
+using System;
+
+namespace Ryujinx.HLE.HOS.Kernel.Memory
+{
+ class KMemoryManager
+ {
+ public KMemoryRegionManager[] MemoryRegions { get; }
+
+ public KMemoryManager(MemorySize size, MemoryArrange arrange)
+ {
+ MemoryRegions = KernelInit.GetMemoryRegions(size, arrange);
+ }
+
+ private KMemoryRegionManager GetMemoryRegion(ulong address)
+ {
+ for (int i = 0; i < MemoryRegions.Length; i++)
+ {
+ var region = MemoryRegions[i];
+
+ if (address >= region.Address && address < region.EndAddr)
+ {
+ return region;
+ }
+ }
+
+ return null;
+ }
+
+ public void IncrementPagesReferenceCount(ulong address, ulong pagesCount)
+ {
+ IncrementOrDecrementPagesReferenceCount(address, pagesCount, true);
+ }
+
+ public void DecrementPagesReferenceCount(ulong address, ulong pagesCount)
+ {
+ IncrementOrDecrementPagesReferenceCount(address, pagesCount, false);
+ }
+
+ private void IncrementOrDecrementPagesReferenceCount(ulong address, ulong pagesCount, bool increment)
+ {
+ while (pagesCount != 0)
+ {
+ var region = GetMemoryRegion(address);
+
+ ulong countToProcess = Math.Min(pagesCount, region.GetPageOffsetFromEnd(address));
+
+ lock (region)
+ {
+ if (increment)
+ {
+ region.IncrementPagesReferenceCount(address, countToProcess);
+ }
+ else
+ {
+ region.DecrementPagesReferenceCount(address, countToProcess);
+ }
+ }
+
+ pagesCount -= countToProcess;
+ address += countToProcess * KPageTableBase.PageSize;
+ }
+ }
+ }
+}