Ryujinx-uplift/Ryujinx.HLE/HOS/Kernel/Memory/KPageList.cs
gdkchan 08831eecf7
IPC refactor part 3+4: New server HIPC message processor (#4188)
* IPC refactor part 3 + 4: New server HIPC message processor with source generator based serialization

* Make types match on calls to AlignUp/AlignDown

* Formatting

* Address some PR feedback

* Move BitfieldExtensions to Ryujinx.Common.Utilities and consolidate implementations

* Rename Reader/Writer to SpanReader/SpanWriter and move to Ryujinx.Common.Memory

* Implement EventType

* Address more PR feedback

* Log request processing errors since they are not normal

* Rename waitable to multiwait and add missing lock

* PR feedback

* Ac_K PR feedback
2023-01-04 23:15:45 +01:00

97 lines
2.6 KiB
C#

using Ryujinx.Horizon.Common;
using System.Collections;
using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Kernel.Memory
{
class KPageList : IEnumerable<KPageNode>
{
public LinkedList<KPageNode> Nodes { get; }
public KPageList()
{
Nodes = new LinkedList<KPageNode>();
}
public Result AddRange(ulong address, ulong pagesCount)
{
if (pagesCount != 0)
{
if (Nodes.Last != null)
{
KPageNode lastNode = Nodes.Last.Value;
if (lastNode.Address + lastNode.PagesCount * KPageTableBase.PageSize == address)
{
address = lastNode.Address;
pagesCount += lastNode.PagesCount;
Nodes.RemoveLast();
}
}
Nodes.AddLast(new KPageNode(address, pagesCount));
}
return Result.Success;
}
public ulong GetPagesCount()
{
ulong sum = 0;
foreach (KPageNode node in Nodes)
{
sum += node.PagesCount;
}
return sum;
}
public bool IsEqual(KPageList other)
{
LinkedListNode<KPageNode> thisNode = Nodes.First;
LinkedListNode<KPageNode> otherNode = other.Nodes.First;
while (thisNode != null && otherNode != null)
{
if (thisNode.Value.Address != otherNode.Value.Address ||
thisNode.Value.PagesCount != otherNode.Value.PagesCount)
{
return false;
}
thisNode = thisNode.Next;
otherNode = otherNode.Next;
}
return thisNode == null && otherNode == null;
}
public void IncrementPagesReferenceCount(KMemoryManager manager)
{
foreach (var node in this)
{
manager.IncrementPagesReferenceCount(node.Address, node.PagesCount);
}
}
public void DecrementPagesReferenceCount(KMemoryManager manager)
{
foreach (var node in this)
{
manager.DecrementPagesReferenceCount(node.Address, node.PagesCount);
}
}
public IEnumerator<KPageNode> GetEnumerator()
{
return Nodes.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}