aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.HLE/HOS')
-rw-r--r--Ryujinx.HLE/HOS/Ipc/IpcMessage.cs123
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs17
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs7
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs7
-rw-r--r--Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs35
-rw-r--r--Ryujinx.HLE/HOS/Services/IpcService.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/ServerBase.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs21
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);