diff options
Diffstat (limited to 'Ryujinx.HLE/HOS')
| -rw-r--r-- | Ryujinx.HLE/HOS/Ipc/IpcMessage.cs | 123 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs | 17 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs | 7 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs | 7 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs | 35 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Services/IpcService.cs | 2 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Services/ServerBase.cs | 2 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs | 21 |
8 files changed, 126 insertions, 88 deletions
diff --git a/Ryujinx.HLE/HOS/Ipc/IpcMessage.cs b/Ryujinx.HLE/HOS/Ipc/IpcMessage.cs index 394bf888..21630c42 100644 --- a/Ryujinx.HLE/HOS/Ipc/IpcMessage.cs +++ b/Ryujinx.HLE/HOS/Ipc/IpcMessage.cs @@ -27,98 +27,103 @@ namespace Ryujinx.HLE.HOS.Ipc public IpcMessage() { - PtrBuff = new List<IpcPtrBuffDesc>(); - SendBuff = new List<IpcBuffDesc>(); - ReceiveBuff = new List<IpcBuffDesc>(); - ExchangeBuff = new List<IpcBuffDesc>(); - RecvListBuff = new List<IpcRecvListBuffDesc>(); + PtrBuff = new List<IpcPtrBuffDesc>(0); + SendBuff = new List<IpcBuffDesc>(0); + ReceiveBuff = new List<IpcBuffDesc>(0); + ExchangeBuff = new List<IpcBuffDesc>(0); + RecvListBuff = new List<IpcRecvListBuffDesc>(0); - ObjectIds = new List<int>(); + ObjectIds = new List<int>(0); } - public IpcMessage(ReadOnlySpan<byte> data, long cmdPtr) : this() + public IpcMessage(ReadOnlySpan<byte> data, long cmdPtr) { using (RecyclableMemoryStream ms = MemoryStreamManager.Shared.GetStream(data)) { BinaryReader reader = new BinaryReader(ms); - Initialize(reader, cmdPtr); - } - } + int word0 = reader.ReadInt32(); + int word1 = reader.ReadInt32(); - private void Initialize(BinaryReader reader, long cmdPtr) - { - int word0 = reader.ReadInt32(); - int word1 = reader.ReadInt32(); + Type = (IpcMessageType)(word0 & 0xffff); - Type = (IpcMessageType)(word0 & 0xffff); + int ptrBuffCount = (word0 >> 16) & 0xf; + int sendBuffCount = (word0 >> 20) & 0xf; + int recvBuffCount = (word0 >> 24) & 0xf; + int xchgBuffCount = (word0 >> 28) & 0xf; - int ptrBuffCount = (word0 >> 16) & 0xf; - int sendBuffCount = (word0 >> 20) & 0xf; - int recvBuffCount = (word0 >> 24) & 0xf; - int xchgBuffCount = (word0 >> 28) & 0xf; + int rawDataSize = (word1 >> 0) & 0x3ff; + int recvListFlags = (word1 >> 10) & 0xf; + bool hndDescEnable = ((word1 >> 31) & 0x1) != 0; - int rawDataSize = (word1 >> 0) & 0x3ff; - int recvListFlags = (word1 >> 10) & 0xf; - bool hndDescEnable = ((word1 >> 31) & 0x1) != 0; + if (hndDescEnable) + { + HandleDesc = new IpcHandleDesc(reader); + } - if (hndDescEnable) - { - HandleDesc = new IpcHandleDesc(reader); - } + PtrBuff = new List<IpcPtrBuffDesc>(ptrBuffCount); - for (int index = 0; index < ptrBuffCount; index++) - { - PtrBuff.Add(new IpcPtrBuffDesc(reader)); - } + for (int index = 0; index < ptrBuffCount; index++) + { + PtrBuff.Add(new IpcPtrBuffDesc(reader)); + } - void ReadBuff(List<IpcBuffDesc> buff, int count) - { - for (int index = 0; index < count; index++) + static List<IpcBuffDesc> ReadBuff(BinaryReader reader, int count) { - buff.Add(new IpcBuffDesc(reader)); + List<IpcBuffDesc> buff = new List<IpcBuffDesc>(count); + + for (int index = 0; index < count; index++) + { + buff.Add(new IpcBuffDesc(reader)); + } + + return buff; } - } - ReadBuff(SendBuff, sendBuffCount); - ReadBuff(ReceiveBuff, recvBuffCount); - ReadBuff(ExchangeBuff, xchgBuffCount); + SendBuff = ReadBuff(reader, sendBuffCount); + ReceiveBuff = ReadBuff(reader, recvBuffCount); + ExchangeBuff = ReadBuff(reader, xchgBuffCount); - rawDataSize *= 4; + rawDataSize *= 4; - long recvListPos = reader.BaseStream.Position + rawDataSize; + long recvListPos = reader.BaseStream.Position + rawDataSize; // Only CMIF has the padding requirements. if (Type < IpcMessageType.TipcCloseSession) { long pad0 = GetPadSize16(reader.BaseStream.Position + cmdPtr); - if (rawDataSize != 0) - { - rawDataSize -= (int)pad0; + if (rawDataSize != 0) + { + rawDataSize -= (int)pad0; + } + + reader.BaseStream.Seek(pad0, SeekOrigin.Current); } - reader.BaseStream.Seek(pad0, SeekOrigin.Current); - } + int recvListCount = recvListFlags - 2; - int recvListCount = recvListFlags - 2; + if (recvListCount == 0) + { + recvListCount = 1; + } + else if (recvListCount < 0) + { + recvListCount = 0; + } - if (recvListCount == 0) - { - recvListCount = 1; - } - else if (recvListCount < 0) - { - recvListCount = 0; - } + RawData = reader.ReadBytes(rawDataSize); - RawData = reader.ReadBytes(rawDataSize); + reader.BaseStream.Seek(recvListPos, SeekOrigin.Begin); - reader.BaseStream.Seek(recvListPos, SeekOrigin.Begin); + RecvListBuff = new List<IpcRecvListBuffDesc>(recvListCount); - for (int index = 0; index < recvListCount; index++) - { - RecvListBuff.Add(new IpcRecvListBuffDesc(reader.ReadUInt64())); + for (int index = 0; index < recvListCount; index++) + { + RecvListBuff.Add(new IpcRecvListBuffDesc(reader.ReadUInt64())); + } + + ObjectIds = new List<int>(0); } } diff --git a/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs b/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs index 1af171b9..c0cd9ce9 100644 --- a/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs +++ b/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs @@ -71,7 +71,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Common { lock (_context.CriticalSection.Lock) { - _waitingObjects.RemoveAll(x => x.Object == schedulerObj); + for (int index = _waitingObjects.Count - 1; index >= 0; index--) + { + if (_waitingObjects[index].Object == schedulerObj) + { + _waitingObjects.RemoveAt(index); + } + } } } @@ -105,16 +111,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Common } else { - while (Interlocked.Read(ref _enforceWakeupFromSpinWait) != 1 && PerformanceCounter.ElapsedTicks <= next.TimePoint) + while (Interlocked.Read(ref _enforceWakeupFromSpinWait) != 1 && PerformanceCounter.ElapsedTicks < next.TimePoint) { + // Our time is close - don't let SpinWait go off and potentially Thread.Sleep(). if (spinWait.NextSpinWillYield) { Thread.Yield(); spinWait.Reset(); } - - spinWait.SpinOnce(); + else + { + spinWait.SpinOnce(); + } } spinWait.Reset(); diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs index c6467208..3163c348 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs @@ -9,6 +9,7 @@ using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.Horizon.Common; using System; +using System.Buffers; using System.Threading; namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall @@ -553,7 +554,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall KProcess currentProcess = KernelStatic.GetCurrentProcess(); - KSynchronizationObject[] syncObjs = handles.Length == 0 ? Array.Empty<KSynchronizationObject>() : new KSynchronizationObject[handles.Length]; + KSynchronizationObject[] syncObjsArray = ArrayPool<KSynchronizationObject>.Shared.Rent(handles.Length); + + Span<KSynchronizationObject> syncObjs = syncObjsArray.AsSpan(0, handles.Length); for (int index = 0; index < handles.Length; index++) { @@ -606,6 +609,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall } } + ArrayPool<KSynchronizationObject>.Shared.Return(syncObjsArray); + return result; } diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs index 973d5f6a..d42f9003 100644 --- a/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs +++ b/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs @@ -1,6 +1,7 @@ using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.Horizon.Common; using System; +using System.Buffers; using System.Collections.Generic; namespace Ryujinx.HLE.HOS.Kernel.Threading @@ -59,7 +60,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading } else { - LinkedListNode<KThread>[] syncNodes = syncObjs.Length == 0 ? Array.Empty<LinkedListNode<KThread>>() : new LinkedListNode<KThread>[syncObjs.Length]; + LinkedListNode<KThread>[] syncNodesArray = ArrayPool<LinkedListNode<KThread>>.Shared.Rent(syncObjs.Length); + + Span<LinkedListNode<KThread>> syncNodes = syncNodesArray.AsSpan(0, syncObjs.Length); for (int index = 0; index < syncObjs.Length; index++) { @@ -101,6 +104,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading handleIndex = index; } } + + ArrayPool<LinkedListNode<KThread>>.Shared.Return(syncNodesArray); } _context.CriticalSection.Leave(); diff --git a/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs b/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs index 81321046..a137c413 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs @@ -1,4 +1,5 @@ using Ryujinx.Common.Logging; +using Ryujinx.Common.Memory; using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.Horizon.Common; @@ -68,25 +69,29 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer ReadOnlyMemory<byte> input = context.Memory.GetSpan(inputPosition, (int)inputSize).ToArray(); - Memory<byte> output = new byte[outputSize]; - Memory<byte> performanceOutput = new byte[performanceOutputSize]; + using (IMemoryOwner<byte> outputOwner = ByteMemoryPool.Shared.RentCleared(outputSize)) + using (IMemoryOwner<byte> performanceOutputOwner = ByteMemoryPool.Shared.RentCleared(performanceOutputSize)) + { + Memory<byte> output = outputOwner.Memory; + Memory<byte> performanceOutput = performanceOutputOwner.Memory; - using MemoryHandle outputHandle = output.Pin(); - using MemoryHandle performanceOutputHandle = performanceOutput.Pin(); + using MemoryHandle outputHandle = output.Pin(); + using MemoryHandle performanceOutputHandle = performanceOutput.Pin(); - ResultCode result = _impl.RequestUpdate(output, performanceOutput, input); + ResultCode result = _impl.RequestUpdate(output, performanceOutput, input); - if (result == ResultCode.Success) - { - context.Memory.Write(outputPosition, output.Span); - context.Memory.Write(performanceOutputPosition, performanceOutput.Span); - } - else - { - Logger.Error?.Print(LogClass.ServiceAudio, $"Error while processing renderer update: 0x{(int)result:X}"); - } + if (result == ResultCode.Success) + { + context.Memory.Write(outputPosition, output.Span); + context.Memory.Write(performanceOutputPosition, performanceOutput.Span); + } + else + { + Logger.Error?.Print(LogClass.ServiceAudio, $"Error while processing renderer update: 0x{(int)result:X}"); + } - return result; + return result; + } } [CommandCmif(5)] diff --git a/Ryujinx.HLE/HOS/Services/IpcService.cs b/Ryujinx.HLE/HOS/Services/IpcService.cs index f42fd0e2..048a68a9 100644 --- a/Ryujinx.HLE/HOS/Services/IpcService.cs +++ b/Ryujinx.HLE/HOS/Services/IpcService.cs @@ -76,6 +76,8 @@ namespace Ryujinx.HLE.HOS.Services context.RequestData.BaseStream.Seek(0x10 + dataPayloadSize, SeekOrigin.Begin); + context.Request.ObjectIds.EnsureCapacity(inputObjCount); + for (int index = 0; index < inputObjCount; index++) { context.Request.ObjectIds.Add(context.RequestData.ReadInt32()); diff --git a/Ryujinx.HLE/HOS/Services/ServerBase.cs b/Ryujinx.HLE/HOS/Services/ServerBase.cs index 762b4fa4..b994679a 100644 --- a/Ryujinx.HLE/HOS/Services/ServerBase.cs +++ b/Ryujinx.HLE/HOS/Services/ServerBase.cs @@ -217,6 +217,8 @@ namespace Ryujinx.HLE.HOS.Services if (noReceive) { + response.PtrBuff.EnsureCapacity(request.RecvListBuff.Count); + for (int i = 0; i < request.RecvListBuff.Count; i++) { ulong size = (ulong)BinaryPrimitives.ReadInt16LittleEndian(request.RawData.AsSpan(sizesOffset + i * 2, 2)); diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs index 0724c83e..42fc2761 100644 --- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs +++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs @@ -1,7 +1,9 @@ -using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.Common.Memory; +using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.Horizon.Common; using System; +using System.Buffers; namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { @@ -83,16 +85,19 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger ReadOnlySpan<byte> inputParcel = context.Memory.GetSpan(dataPos, (int)dataSize); - Span<byte> outputParcel = new Span<byte>(new byte[replySize]); + using (IMemoryOwner<byte> outputParcelOwner = ByteMemoryPool.Shared.RentCleared(replySize)) + { + Span<byte> outputParcel = outputParcelOwner.Memory.Span; + + ResultCode result = OnTransact(binderId, code, flags, inputParcel, outputParcel); - ResultCode result = OnTransact(binderId, code, flags, inputParcel, outputParcel); + if (result == ResultCode.Success) + { + context.Memory.Write(replyPos, outputParcel); + } - if (result == ResultCode.Success) - { - context.Memory.Write(replyPos, outputParcel); + return result; } - - return result; } protected abstract ResultCode AdjustRefcount(int binderId, int addVal, int type); |
