1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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;
}
}
}
}
|