From 9b94662b4bb2ebf846e1baf45ba8097fcd7da684 Mon Sep 17 00:00:00 2001 From: jhorv <38920027+jhorv@users.noreply.github.com> Date: Sun, 21 Apr 2024 15:34:04 -0400 Subject: [PATCH] implement `MemoryManagerHostTracked.GetReadOnlySequence()` (#6695) * implement `MemoryManagerHostTracked.GetReadOnlySequence()`, fixes crashes on game starts on MacOS * whitespace fixes * whitespace fixes * add missing call to `SignalMemoryTracking()` * adjust call to `SignalMemoryTracking()`` * don't use GetPhysicalAddressMemory() * add newline for consistency --- .../Jit/MemoryManagerHostTracked.cs | 64 +++++++++++++++++++ src/Ryujinx.Memory/NativeMemoryManager.cs | 5 ++ 2 files changed, 69 insertions(+) diff --git a/src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs b/src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs index 0acb57be42..663d0aeb15 100644 --- a/src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs +++ b/src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs @@ -85,6 +85,70 @@ namespace Ryujinx.Cpu.Jit _addressSpace = new(Tracking, backingMemory, _nativePageTable, useProtectionMirrors); } + public override ReadOnlySequence GetReadOnlySequence(ulong va, int size, bool tracked = false) + { + if (size == 0) + { + return ReadOnlySequence.Empty; + } + + try + { + if (tracked) + { + SignalMemoryTracking(va, (ulong)size, false); + } + else + { + AssertValidAddressAndSize(va, (ulong)size); + } + + ulong endVa = va + (ulong)size; + int offset = 0; + + BytesReadOnlySequenceSegment first = null, last = null; + + while (va < endVa) + { + (MemoryBlock memory, ulong rangeOffset, ulong copySize) = GetMemoryOffsetAndSize(va, (ulong)(size - offset)); + + Memory physicalMemory = memory.GetMemory(rangeOffset, (int)copySize); + + if (first is null) + { + first = last = new BytesReadOnlySequenceSegment(physicalMemory); + } + else + { + if (last.IsContiguousWith(physicalMemory, out nuint contiguousStart, out int contiguousSize)) + { + Memory contiguousPhysicalMemory = new NativeMemoryManager(contiguousStart, contiguousSize).Memory; + + last.Replace(contiguousPhysicalMemory); + } + else + { + last = last.Append(physicalMemory); + } + } + + va += copySize; + offset += (int)copySize; + } + + return new ReadOnlySequence(first, 0, last, (int)(size - last.RunningIndex)); + } + catch (InvalidMemoryRegionException) + { + if (_invalidAccessHandler == null || !_invalidAccessHandler(va)) + { + throw; + } + + return ReadOnlySequence.Empty; + } + } + /// public void Map(ulong va, ulong pa, ulong size, MemoryMapFlags flags) { diff --git a/src/Ryujinx.Memory/NativeMemoryManager.cs b/src/Ryujinx.Memory/NativeMemoryManager.cs index 9ca6329382..cb8d5c243d 100644 --- a/src/Ryujinx.Memory/NativeMemoryManager.cs +++ b/src/Ryujinx.Memory/NativeMemoryManager.cs @@ -8,6 +8,11 @@ namespace Ryujinx.Memory private readonly T* _pointer; private readonly int _length; + public NativeMemoryManager(nuint pointer, int length) + : this((T*)pointer, length) + { + } + public NativeMemoryManager(T* pointer, int length) { _pointer = pointer;