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
This commit is contained in:
parent
c6a139a6e7
commit
08831eecf7
213 changed files with 9762 additions and 1010 deletions
|
@ -1,5 +1,6 @@
|
|||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||
using Ryujinx.Horizon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -24,14 +25,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
_arbiterThreads = new List<KThread>();
|
||||
}
|
||||
|
||||
public KernelResult ArbitrateLock(int ownerHandle, ulong mutexAddress, int requesterHandle)
|
||||
public Result ArbitrateLock(int ownerHandle, ulong mutexAddress, int requesterHandle)
|
||||
{
|
||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||
|
||||
_context.CriticalSection.Enter();
|
||||
|
||||
currentThread.SignaledObj = null;
|
||||
currentThread.ObjSyncResult = KernelResult.Success;
|
||||
currentThread.ObjSyncResult = Result.Success;
|
||||
|
||||
KProcess currentProcess = KernelStatic.GetCurrentProcess();
|
||||
|
||||
|
@ -46,7 +47,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
{
|
||||
_context.CriticalSection.Leave();
|
||||
|
||||
return 0;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
KThread mutexOwner = currentProcess.HandleTable.GetObject<KThread>(ownerHandle);
|
||||
|
@ -78,7 +79,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
return currentThread.ObjSyncResult;
|
||||
}
|
||||
|
||||
public KernelResult ArbitrateUnlock(ulong mutexAddress)
|
||||
public Result ArbitrateUnlock(ulong mutexAddress)
|
||||
{
|
||||
_context.CriticalSection.Enter();
|
||||
|
||||
|
@ -86,14 +87,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
(int mutexValue, KThread newOwnerThread) = MutexUnlock(currentThread, mutexAddress);
|
||||
|
||||
KernelResult result = KernelResult.Success;
|
||||
Result result = Result.Success;
|
||||
|
||||
if (!KernelTransfer.KernelToUser(mutexAddress, mutexValue))
|
||||
{
|
||||
result = KernelResult.InvalidMemState;
|
||||
}
|
||||
|
||||
if (result != KernelResult.Success && newOwnerThread != null)
|
||||
if (result != Result.Success && newOwnerThread != null)
|
||||
{
|
||||
newOwnerThread.SignaledObj = null;
|
||||
newOwnerThread.ObjSyncResult = result;
|
||||
|
@ -104,7 +105,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
return result;
|
||||
}
|
||||
|
||||
public KernelResult WaitProcessWideKeyAtomic(ulong mutexAddress, ulong condVarAddress, int threadHandle, long timeout)
|
||||
public Result WaitProcessWideKeyAtomic(ulong mutexAddress, ulong condVarAddress, int threadHandle, long timeout)
|
||||
{
|
||||
_context.CriticalSection.Enter();
|
||||
|
||||
|
@ -185,7 +186,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
}
|
||||
|
||||
newOwnerThread.SignaledObj = null;
|
||||
newOwnerThread.ObjSyncResult = KernelResult.Success;
|
||||
newOwnerThread.ObjSyncResult = Result.Success;
|
||||
|
||||
newOwnerThread.ReleaseAndResume();
|
||||
}
|
||||
|
@ -247,7 +248,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
{
|
||||
// We now own the mutex.
|
||||
requester.SignaledObj = null;
|
||||
requester.ObjSyncResult = KernelResult.Success;
|
||||
requester.ObjSyncResult = Result.Success;
|
||||
|
||||
requester.ReleaseAndResume();
|
||||
|
||||
|
@ -273,7 +274,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
}
|
||||
}
|
||||
|
||||
public KernelResult WaitForAddressIfEqual(ulong address, int value, long timeout)
|
||||
public Result WaitForAddressIfEqual(ulong address, int value, long timeout)
|
||||
{
|
||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||
|
||||
|
@ -344,7 +345,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
return KernelResult.InvalidState;
|
||||
}
|
||||
|
||||
public KernelResult WaitForAddressIfLessThan(ulong address, int value, bool shouldDecrement, long timeout)
|
||||
public Result WaitForAddressIfLessThan(ulong address, int value, bool shouldDecrement, long timeout)
|
||||
{
|
||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||
|
||||
|
@ -422,7 +423,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
return KernelResult.InvalidState;
|
||||
}
|
||||
|
||||
public KernelResult Signal(ulong address, int count)
|
||||
public Result Signal(ulong address, int count)
|
||||
{
|
||||
_context.CriticalSection.Enter();
|
||||
|
||||
|
@ -430,10 +431,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
_context.CriticalSection.Leave();
|
||||
|
||||
return KernelResult.Success;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public KernelResult SignalAndIncrementIfEqual(ulong address, int value, int count)
|
||||
public Result SignalAndIncrementIfEqual(ulong address, int value, int count)
|
||||
{
|
||||
_context.CriticalSection.Enter();
|
||||
|
||||
|
@ -467,10 +468,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
_context.CriticalSection.Leave();
|
||||
|
||||
return KernelResult.Success;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public KernelResult SignalAndModifyIfEqual(ulong address, int value, int count)
|
||||
public Result SignalAndModifyIfEqual(ulong address, int value, int count)
|
||||
{
|
||||
_context.CriticalSection.Enter();
|
||||
|
||||
|
@ -539,7 +540,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
_context.CriticalSection.Leave();
|
||||
|
||||
return KernelResult.Success;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private void WakeArbiterThreads(ulong address, int count)
|
||||
|
@ -547,7 +548,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
static void RemoveArbiterThread(KThread thread)
|
||||
{
|
||||
thread.SignaledObj = null;
|
||||
thread.ObjSyncResult = KernelResult.Success;
|
||||
thread.ObjSyncResult = Result.Success;
|
||||
|
||||
thread.ReleaseAndResume();
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
using Ryujinx.Horizon.Common;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||
{
|
||||
|
@ -27,16 +28,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
KernelContext.CriticalSection.Leave();
|
||||
}
|
||||
|
||||
public KernelResult Clear()
|
||||
public Result Clear()
|
||||
{
|
||||
_signaled = false;
|
||||
|
||||
return KernelResult.Success;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public KernelResult ClearIfSignaled()
|
||||
public Result ClearIfSignaled()
|
||||
{
|
||||
KernelResult result;
|
||||
Result result;
|
||||
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
||||
|
@ -44,7 +45,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
{
|
||||
_signaled = false;
|
||||
|
||||
result = KernelResult.Success;
|
||||
result = Result.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
using Ryujinx.Horizon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
@ -13,11 +14,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
_context = context;
|
||||
}
|
||||
|
||||
public KernelResult WaitFor(Span<KSynchronizationObject> syncObjs, long timeout, out int handleIndex)
|
||||
public Result WaitFor(Span<KSynchronizationObject> syncObjs, long timeout, out int handleIndex)
|
||||
{
|
||||
handleIndex = 0;
|
||||
|
||||
KernelResult result = KernelResult.TimedOut;
|
||||
Result result = KernelResult.TimedOut;
|
||||
|
||||
_context.CriticalSection.Enter();
|
||||
|
||||
|
@ -33,7 +34,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
_context.CriticalSection.Leave();
|
||||
|
||||
return KernelResult.Success;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
if (timeout == 0)
|
||||
|
@ -122,7 +123,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
if ((thread.SchedFlags & ThreadSchedState.LowMask) == ThreadSchedState.Paused)
|
||||
{
|
||||
thread.SignaledObj = syncObj;
|
||||
thread.ObjSyncResult = KernelResult.Success;
|
||||
thread.ObjSyncResult = Result.Success;
|
||||
|
||||
thread.Reschedule(ThreadSchedState.Running);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ using Ryujinx.Cpu;
|
|||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||
using Ryujinx.HLE.HOS.Kernel.SupervisorCall;
|
||||
using Ryujinx.Horizon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
@ -79,7 +80,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
private ThreadSchedState _forcePauseFlags;
|
||||
private ThreadSchedState _forcePausePermissionFlags;
|
||||
|
||||
public KernelResult ObjSyncResult { get; set; }
|
||||
public Result ObjSyncResult { get; set; }
|
||||
|
||||
public int BasePriority { get; set; }
|
||||
public int PreferredCore { get; set; }
|
||||
|
@ -130,7 +131,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
_activityOperationLock = new object();
|
||||
}
|
||||
|
||||
public KernelResult Initialize(
|
||||
public Result Initialize(
|
||||
ulong entrypoint,
|
||||
ulong argsPtr,
|
||||
ulong stackTop,
|
||||
|
@ -145,8 +146,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
throw new ArgumentException($"Invalid thread type \"{type}\".");
|
||||
}
|
||||
|
||||
ThreadContext = new KThreadContext();
|
||||
|
||||
PreferredCore = cpuCore;
|
||||
AffinityMask |= 1UL << cpuCore;
|
||||
|
||||
|
@ -166,7 +165,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
if (type == ThreadType.User)
|
||||
{
|
||||
if (owner.AllocateThreadLocalStorage(out _tlsAddress) != KernelResult.Success)
|
||||
if (owner.AllocateThreadLocalStorage(out _tlsAddress) != Result.Success)
|
||||
{
|
||||
return KernelResult.OutOfMemory;
|
||||
}
|
||||
|
@ -194,6 +193,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
Context = owner?.CreateExecutionContext() ?? new ProcessExecutionContext();
|
||||
|
||||
ThreadContext = new KThreadContext(Context);
|
||||
|
||||
Context.IsAarch32 = !is64Bits;
|
||||
|
||||
Context.SetX(0, argsPtr);
|
||||
|
@ -230,7 +231,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
{
|
||||
KernelContext.CriticalSection.Leave();
|
||||
|
||||
return KernelResult.Success;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
_forcePauseFlags |= ThreadSchedState.ProcessPauseFlag;
|
||||
|
@ -241,10 +242,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
}
|
||||
}
|
||||
|
||||
return KernelResult.Success;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public KernelResult Start()
|
||||
public Result Start()
|
||||
{
|
||||
if (!KernelContext.KernelInitialized)
|
||||
{
|
||||
|
@ -260,7 +261,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
KernelContext.CriticalSection.Leave();
|
||||
}
|
||||
|
||||
KernelResult result = KernelResult.ThreadTerminating;
|
||||
Result result = KernelResult.ThreadTerminating;
|
||||
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
||||
|
@ -287,7 +288,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
StartHostThread();
|
||||
|
||||
result = KernelResult.Success;
|
||||
result = Result.Success;
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
@ -465,7 +466,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
return -1;
|
||||
}
|
||||
|
||||
public KernelResult Sleep(long timeout)
|
||||
public Result Sleep(long timeout)
|
||||
{
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
||||
|
@ -490,7 +491,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
KernelContext.TimeManager.UnscheduleFutureInvocation(this);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public void SetPriority(int priority)
|
||||
|
@ -534,11 +535,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
}
|
||||
}
|
||||
|
||||
public KernelResult SetActivity(bool pause)
|
||||
public Result SetActivity(bool pause)
|
||||
{
|
||||
lock (_activityOperationLock)
|
||||
{
|
||||
KernelResult result = KernelResult.Success;
|
||||
Result result = Result.Success;
|
||||
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
||||
|
@ -581,7 +582,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
|
||||
KernelContext.CriticalSection.Leave();
|
||||
|
||||
if (result == KernelResult.Success && pause)
|
||||
if (result == Result.Success && pause)
|
||||
{
|
||||
bool isThreadRunning = true;
|
||||
|
||||
|
@ -628,7 +629,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
}
|
||||
}
|
||||
|
||||
public KernelResult GetThreadContext3(out ThreadContext context)
|
||||
public Result GetThreadContext3(out ThreadContext context)
|
||||
{
|
||||
context = default;
|
||||
|
||||
|
@ -651,7 +652,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
KernelContext.CriticalSection.Leave();
|
||||
}
|
||||
|
||||
return KernelResult.Success;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private static uint GetPsr(IExecutionContext context)
|
||||
|
@ -739,7 +740,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
KernelContext.CriticalSection.Leave();
|
||||
}
|
||||
|
||||
public KernelResult SetCoreAndAffinityMask(int newCore, ulong newAffinityMask)
|
||||
public Result SetCoreAndAffinityMask(int newCore, ulong newAffinityMask)
|
||||
{
|
||||
lock (_activityOperationLock)
|
||||
{
|
||||
|
@ -838,7 +839,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
KernelContext.CriticalSection.Leave();
|
||||
}
|
||||
|
||||
return KernelResult.Success;
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1259,6 +1260,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
if (_customThreadStart != null)
|
||||
{
|
||||
_customThreadStart();
|
||||
|
||||
// Ensure that anything trying to join the HLE thread is unblocked.
|
||||
Exit();
|
||||
HandlePostSyscall();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1304,7 +1309,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
{
|
||||
Owner?.RemoveThread(this);
|
||||
|
||||
if (_tlsAddress != 0 && Owner.FreeThreadLocalStorage(_tlsAddress) != KernelResult.Success)
|
||||
if (_tlsAddress != 0 && Owner.FreeThreadLocalStorage(_tlsAddress) != Result.Success)
|
||||
{
|
||||
throw new InvalidOperationException("Unexpected failure freeing thread local storage.");
|
||||
}
|
||||
|
|
|
@ -1,11 +1,25 @@
|
|||
using System.Threading;
|
||||
using Ryujinx.Cpu;
|
||||
using Ryujinx.Horizon.Common;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||
{
|
||||
class KThreadContext
|
||||
class KThreadContext : IThreadContext
|
||||
{
|
||||
private readonly IExecutionContext _context;
|
||||
|
||||
public bool Running => _context.Running;
|
||||
public ulong TlsAddress => (ulong)_context.TpidrroEl0;
|
||||
|
||||
public ulong GetX(int index) => _context.GetX(index);
|
||||
|
||||
private int _locked;
|
||||
|
||||
public KThreadContext(IExecutionContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public bool Lock()
|
||||
{
|
||||
return Interlocked.Exchange(ref _locked, 1) == 0;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
using Ryujinx.Horizon.Common;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||
{
|
||||
|
@ -16,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||
_parent.ReadableEvent.Signal();
|
||||
}
|
||||
|
||||
public KernelResult Clear()
|
||||
public Result Clear()
|
||||
{
|
||||
return _parent.ReadableEvent.Clear();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue