diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-09-23 15:11:46 -0300 |
|---|---|---|
| committer | Thomas Guillemard <thog@protonmail.com> | 2018-09-23 20:11:46 +0200 |
| commit | 7de7b559adc1924d3ff31cc58b281f70e468155f (patch) | |
| tree | 3701e1687f7fc4c4bafdffd5abda1966e6ce320f /Ryujinx.HLE/HOS/Kernel | |
| parent | 54ed9096bd4add5cf2ca320123f551f60c06a57f (diff) | |
Improve kernel events implementation (#430)
* Improve kernel events implementation
* Some cleanup
* Address PR feedback
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel')
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/HleScheduler.cs | 9 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/KAddressArbiter.cs | 4 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/KEvent.cs | 36 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/KHandleEntry.cs | 17 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/KProcessHandleTable.cs | 173 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/KReadableEvent.cs | 62 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/KScheduler.cs | 7 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/KWritableEvent.cs | 22 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/KernelErr.cs | 1 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/KernelResult.cs | 10 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/SvcHandler.cs | 23 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/SvcMemory.cs | 8 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/SvcSystem.cs | 138 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/SvcThread.cs | 22 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/SvcThreadSync.cs | 16 |
15 files changed, 441 insertions, 107 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/HleScheduler.cs b/Ryujinx.HLE/HOS/Kernel/HleScheduler.cs index 42caeca2..e0cb158c 100644 --- a/Ryujinx.HLE/HOS/Kernel/HleScheduler.cs +++ b/Ryujinx.HLE/HOS/Kernel/HleScheduler.cs @@ -15,6 +15,15 @@ namespace Ryujinx.HLE.HOS.Kernel private bool KeepPreempting; + public void StartAutoPreemptionThread() + { + Thread PreemptionThread = new Thread(PreemptCurrentThread); + + KeepPreempting = true; + + PreemptionThread.Start(); + } + public void ContextSwitch() { lock (CoreContexts) diff --git a/Ryujinx.HLE/HOS/Kernel/KAddressArbiter.cs b/Ryujinx.HLE/HOS/Kernel/KAddressArbiter.cs index f2156a5c..73309e1e 100644 --- a/Ryujinx.HLE/HOS/Kernel/KAddressArbiter.cs +++ b/Ryujinx.HLE/HOS/Kernel/KAddressArbiter.cs @@ -51,7 +51,7 @@ namespace Ryujinx.HLE.HOS.Kernel return 0; } - KThread MutexOwner = Process.HandleTable.GetData<KThread>(OwnerHandle); + KThread MutexOwner = Process.HandleTable.GetObject<KThread>(OwnerHandle); if (MutexOwner == null) { @@ -282,7 +282,7 @@ namespace Ryujinx.HLE.HOS.Kernel MutexValue &= ~HasListenersMask; - KThread MutexOwner = Process.HandleTable.GetData<KThread>(MutexValue); + KThread MutexOwner = Process.HandleTable.GetObject<KThread>(MutexValue); if (MutexOwner != null) { diff --git a/Ryujinx.HLE/HOS/Kernel/KEvent.cs b/Ryujinx.HLE/HOS/Kernel/KEvent.cs index 1a865aa2..106d1b40 100644 --- a/Ryujinx.HLE/HOS/Kernel/KEvent.cs +++ b/Ryujinx.HLE/HOS/Kernel/KEvent.cs @@ -1,38 +1,14 @@ namespace Ryujinx.HLE.HOS.Kernel { - class KEvent : KSynchronizationObject + class KEvent { - private bool Signaled; + public KReadableEvent ReadableEvent { get; private set; } + public KWritableEvent WritableEvent { get; private set; } - public string Name { get; private set; } - - public KEvent(Horizon System, string Name = "") : base(System) - { - this.Name = Name; - } - - public override void Signal() - { - System.CriticalSectionLock.Lock(); - - if (!Signaled) - { - Signaled = true; - - base.Signal(); - } - - System.CriticalSectionLock.Unlock(); - } - - public void Reset() - { - Signaled = false; - } - - public override bool IsSignaled() + public KEvent(Horizon System) { - return Signaled; + ReadableEvent = new KReadableEvent(System, this); + WritableEvent = new KWritableEvent(this); } } }
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/KHandleEntry.cs b/Ryujinx.HLE/HOS/Kernel/KHandleEntry.cs new file mode 100644 index 00000000..9863a374 --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/KHandleEntry.cs @@ -0,0 +1,17 @@ +namespace Ryujinx.HLE.HOS.Kernel +{ + class KHandleEntry + { + public KHandleEntry Next { get; set; } + + public int Index { get; private set; } + + public ushort HandleId { get; set; } + public object Obj { get; set; } + + public KHandleEntry(int Index) + { + this.Index = Index; + } + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/KProcessHandleTable.cs b/Ryujinx.HLE/HOS/Kernel/KProcessHandleTable.cs index db0eaa44..682f08d4 100644 --- a/Ryujinx.HLE/HOS/Kernel/KProcessHandleTable.cs +++ b/Ryujinx.HLE/HOS/Kernel/KProcessHandleTable.cs @@ -1,34 +1,183 @@ -using System.Collections.Generic; +using System; namespace Ryujinx.HLE.HOS.Kernel { class KProcessHandleTable { - private IdDictionary Handles; + private const int SelfThreadHandle = (0x1ffff << 15) | 0; + private const int SelfProcessHandle = (0x1ffff << 15) | 1; - public KProcessHandleTable() + private Horizon System; + + private KHandleEntry[] Table; + + private KHandleEntry TableHead; + private KHandleEntry NextFreeEntry; + + private int ActiveSlotsCount; + + private int Size; + + private ushort IdCounter; + + private object LockObj; + + public KProcessHandleTable(Horizon System, int Size = 1024) { - Handles = new IdDictionary(); + this.System = System; + this.Size = Size; + + IdCounter = 1; + + Table = new KHandleEntry[Size]; + + TableHead = new KHandleEntry(0); + + KHandleEntry Entry = TableHead; + + for (int Index = 0; Index < Size; Index++) + { + Table[Index] = Entry; + + Entry.Next = new KHandleEntry(Index + 1); + + Entry = Entry.Next; + } + + Table[Size - 1].Next = null; + + NextFreeEntry = TableHead; + + LockObj = new object(); + } + + public KernelResult GenerateHandle(object Obj, out int Handle) + { + Handle = 0; + + lock (LockObj) + { + if (ActiveSlotsCount >= Size) + { + return KernelResult.HandleTableFull; + } + + KHandleEntry Entry = NextFreeEntry; + + NextFreeEntry = Entry.Next; + + Entry.Obj = Obj; + Entry.HandleId = IdCounter; + + ActiveSlotsCount++; + + Handle = (int)((IdCounter << 15) & (uint)0xffff8000) | Entry.Index; + + if ((short)(IdCounter + 1) >= 0) + { + IdCounter++; + } + else + { + IdCounter = 1; + } + } + + return KernelResult.Success; } - public int OpenHandle(object Obj) + public bool CloseHandle(int Handle) { - return Handles.Add(Obj); + if ((Handle >> 30) != 0 || + Handle == SelfThreadHandle || + Handle == SelfProcessHandle) + { + return false; + } + + int Index = (Handle >> 0) & 0x7fff; + int HandleId = (Handle >> 15); + + bool Result = false; + + lock (LockObj) + { + if (HandleId != 0 && Index < Size) + { + KHandleEntry Entry = Table[Index]; + + if (Entry.Obj != null && Entry.HandleId == HandleId) + { + Entry.Obj = null; + Entry.Next = NextFreeEntry; + + NextFreeEntry = Entry; + + ActiveSlotsCount--; + + Result = true; + } + } + } + + return Result; } - public T GetData<T>(int Handle) + public T GetObject<T>(int Handle) { - return Handles.GetData<T>(Handle); + int Index = (Handle >> 0) & 0x7fff; + int HandleId = (Handle >> 15); + + lock (LockObj) + { + if ((Handle >> 30) == 0 && HandleId != 0) + { + KHandleEntry Entry = Table[Index]; + + if (Entry.HandleId == HandleId && Entry.Obj is T Obj) + { + return Obj; + } + } + } + + return default(T); } - public object CloseHandle(int Handle) + public KThread GetKThread(int Handle) { - return Handles.Delete(Handle); + if (Handle == SelfThreadHandle) + { + return System.Scheduler.GetCurrentThread(); + } + else + { + return GetObject<KThread>(Handle); + } } - public ICollection<object> Clear() + public void Destroy() { - return Handles.Clear(); + lock (LockObj) + { + for (int Index = 0; Index < Size; Index++) + { + KHandleEntry Entry = Table[Index]; + + if (Entry.Obj != null) + { + if (Entry.Obj is IDisposable DisposableObj) + { + DisposableObj.Dispose(); + } + + Entry.Obj = null; + Entry.Next = NextFreeEntry; + + NextFreeEntry = Entry; + } + } + } } } }
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/KReadableEvent.cs b/Ryujinx.HLE/HOS/Kernel/KReadableEvent.cs new file mode 100644 index 00000000..d43fe824 --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/KReadableEvent.cs @@ -0,0 +1,62 @@ +namespace Ryujinx.HLE.HOS.Kernel +{ + class KReadableEvent : KSynchronizationObject + { + private KEvent Parent; + + private bool Signaled; + + public KReadableEvent(Horizon System, KEvent Parent) : base(System) + { + this.Parent = Parent; + } + + public override void Signal() + { + System.CriticalSectionLock.Lock(); + + if (!Signaled) + { + Signaled = true; + + base.Signal(); + } + + System.CriticalSectionLock.Unlock(); + } + + public KernelResult Clear() + { + Signaled = false; + + return KernelResult.Success; + } + + public KernelResult ClearIfSignaled() + { + KernelResult Result; + + System.CriticalSectionLock.Lock(); + + if (Signaled) + { + Signaled = false; + + Result = KernelResult.Success; + } + else + { + Result = KernelResult.InvalidState; + } + + System.CriticalSectionLock.Unlock(); + + return Result; + } + + public override bool IsSignaled() + { + return Signaled; + } + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/KScheduler.cs b/Ryujinx.HLE/HOS/Kernel/KScheduler.cs index f6382d05..3cfda419 100644 --- a/Ryujinx.HLE/HOS/Kernel/KScheduler.cs +++ b/Ryujinx.HLE/HOS/Kernel/KScheduler.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; namespace Ryujinx.HLE.HOS.Kernel { @@ -35,12 +34,6 @@ namespace Ryujinx.HLE.HOS.Kernel { CoreContexts[Core] = new KCoreContext(this, CoreManager); } - - Thread PreemptionThread = new Thread(PreemptCurrentThread); - - KeepPreempting = true; - - PreemptionThread.Start(); } private void PreemptThreads() diff --git a/Ryujinx.HLE/HOS/Kernel/KWritableEvent.cs b/Ryujinx.HLE/HOS/Kernel/KWritableEvent.cs new file mode 100644 index 00000000..1721ed00 --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/KWritableEvent.cs @@ -0,0 +1,22 @@ +namespace Ryujinx.HLE.HOS.Kernel +{ + class KWritableEvent + { + private KEvent Parent; + + public KWritableEvent(KEvent Parent) + { + this.Parent = Parent; + } + + public void Signal() + { + Parent.ReadableEvent.Signal(); + } + + public KernelResult Clear() + { + return Parent.ReadableEvent.Clear(); + } + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/KernelErr.cs b/Ryujinx.HLE/HOS/Kernel/KernelErr.cs index 0749f3fd..e0b196f4 100644 --- a/Ryujinx.HLE/HOS/Kernel/KernelErr.cs +++ b/Ryujinx.HLE/HOS/Kernel/KernelErr.cs @@ -6,6 +6,7 @@ namespace Ryujinx.HLE.HOS.Kernel public const int InvalidSize = 101; public const int InvalidAddress = 102; public const int OutOfMemory = 104; + public const int HandleTableFull = 105; public const int NoAccessPerm = 106; public const int InvalidPermission = 108; public const int InvalidMemRange = 110; diff --git a/Ryujinx.HLE/HOS/Kernel/KernelResult.cs b/Ryujinx.HLE/HOS/Kernel/KernelResult.cs new file mode 100644 index 00000000..d9cbfc67 --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/KernelResult.cs @@ -0,0 +1,10 @@ +namespace Ryujinx.HLE.HOS.Kernel +{ + enum KernelResult + { + Success = 0, + HandleTableFull = 0xd201, + InvalidHandle = 0xe401, + InvalidState = 0xfa01 + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SvcHandler.cs b/Ryujinx.HLE/HOS/Kernel/SvcHandler.cs index a12a0ba0..b678037b 100644 --- a/Ryujinx.HLE/HOS/Kernel/SvcHandler.cs +++ b/Ryujinx.HLE/HOS/Kernel/SvcHandler.cs @@ -39,9 +39,6 @@ namespace Ryujinx.HLE.HOS.Kernel } } - private const uint SelfThreadHandle = 0xffff8000; - private const uint SelfProcessHandle = 0xffff8001; - private static Random Rng; public SvcHandler(Switch Device, Process Process) @@ -63,12 +60,13 @@ namespace Ryujinx.HLE.HOS.Kernel { 0x0e, SvcGetThreadCoreMask }, { 0x0f, SvcSetThreadCoreMask }, { 0x10, SvcGetCurrentProcessorNumber }, - { 0x12, SvcClearEvent }, + { 0x11, SignalEvent64 }, + { 0x12, ClearEvent64 }, { 0x13, SvcMapSharedMemory }, { 0x14, SvcUnmapSharedMemory }, { 0x15, SvcCreateTransferMemory }, { 0x16, SvcCloseHandle }, - { 0x17, SvcResetSignal }, + { 0x17, ResetSignal64 }, { 0x18, SvcWaitSynchronization }, { 0x19, SvcCancelSynchronization }, { 0x1a, SvcArbitrateLock }, @@ -88,7 +86,8 @@ namespace Ryujinx.HLE.HOS.Kernel { 0x32, SvcSetThreadActivity }, { 0x33, SvcGetThreadContext3 }, { 0x34, SvcWaitForAddress }, - { 0x35, SvcSignalToAddress } + { 0x35, SvcSignalToAddress }, + { 0x45, CreateEvent64 } }; this.Device = Device; @@ -123,17 +122,5 @@ namespace Ryujinx.HLE.HOS.Kernel throw new NotImplementedException($"0x{e.Id:x4}"); } } - - private KThread GetThread(long Tpidr, int Handle) - { - if ((uint)Handle == SelfThreadHandle) - { - return Process.GetThread(Tpidr); - } - else - { - return Process.HandleTable.GetData<KThread>(Handle); - } - } } }
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SvcMemory.cs b/Ryujinx.HLE/HOS/Kernel/SvcMemory.cs index b9e71b18..e3c0cf5b 100644 --- a/Ryujinx.HLE/HOS/Kernel/SvcMemory.cs +++ b/Ryujinx.HLE/HOS/Kernel/SvcMemory.cs @@ -276,7 +276,7 @@ namespace Ryujinx.HLE.HOS.Kernel return; } - KSharedMemory SharedMemory = Process.HandleTable.GetData<KSharedMemory>(Handle); + KSharedMemory SharedMemory = Process.HandleTable.GetObject<KSharedMemory>(Handle); if (SharedMemory == null) { @@ -348,7 +348,7 @@ namespace Ryujinx.HLE.HOS.Kernel return; } - KSharedMemory SharedMemory = Process.HandleTable.GetData<KSharedMemory>(Handle); + KSharedMemory SharedMemory = Process.HandleTable.GetObject<KSharedMemory>(Handle); if (SharedMemory == null) { @@ -425,9 +425,9 @@ namespace Ryujinx.HLE.HOS.Kernel KTransferMemory TransferMemory = new KTransferMemory(Position, Size); - int Handle = Process.HandleTable.OpenHandle(TransferMemory); + KernelResult Result = Process.HandleTable.GenerateHandle(TransferMemory, out int Handle); - ThreadState.X0 = 0; + ThreadState.X0 = (uint)Result; ThreadState.X1 = (ulong)Handle; } diff --git a/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs b/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs index 60ccf7f7..8bcea550 100644 --- a/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs +++ b/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs @@ -22,20 +22,73 @@ namespace Ryujinx.HLE.HOS.Kernel Device.System.ExitProcess(Process.ProcessId); } - private void SvcClearEvent(AThreadState ThreadState) + private void SignalEvent64(AThreadState ThreadState) { - int Handle = (int)ThreadState.X0; + ThreadState.X0 = (ulong)SignalEvent((int)ThreadState.X0); + } - //TODO: Implement events. + private KernelResult SignalEvent(int Handle) + { + KWritableEvent WritableEvent = Process.HandleTable.GetObject<KWritableEvent>(Handle); - ThreadState.X0 = 0; + KernelResult Result; + + if (WritableEvent != null) + { + WritableEvent.Signal(); + + Result = KernelResult.Success; + } + else + { + Result = KernelResult.InvalidHandle; + } + + if (Result != KernelResult.Success) + { + Device.Log.PrintWarning(LogClass.KernelSvc, "Operation failed with error: " + Result + "!"); + } + + return Result; + } + + private void ClearEvent64(AThreadState ThreadState) + { + ThreadState.X0 = (ulong)ClearEvent((int)ThreadState.X0); + } + + private KernelResult ClearEvent(int Handle) + { + KernelResult Result; + + KWritableEvent WritableEvent = Process.HandleTable.GetObject<KWritableEvent>(Handle); + + if (WritableEvent == null) + { + KReadableEvent ReadableEvent = Process.HandleTable.GetObject<KReadableEvent>(Handle); + + Result = ReadableEvent?.Clear() ?? KernelResult.InvalidHandle; + } + else + { + Result = WritableEvent.Clear(); + } + + if (Result != KernelResult.Success) + { + Device.Log.PrintWarning(LogClass.KernelSvc, "Operation failed with error: " + Result + "!"); + } + + return Result; } private void SvcCloseHandle(AThreadState ThreadState) { int Handle = (int)ThreadState.X0; - object Obj = Process.HandleTable.CloseHandle(Handle); + object Obj = Process.HandleTable.GetObject<object>(Handle); + + Process.HandleTable.CloseHandle(Handle); if (Obj == null) { @@ -60,24 +113,37 @@ namespace Ryujinx.HLE.HOS.Kernel ThreadState.X0 = 0; } - private void SvcResetSignal(AThreadState ThreadState) + private void ResetSignal64(AThreadState ThreadState) { - int Handle = (int)ThreadState.X0; + ThreadState.X0 = (ulong)ResetSignal((int)ThreadState.X0); + } - KEvent Event = Process.HandleTable.GetData<KEvent>(Handle); + private KernelResult ResetSignal(int Handle) + { + KReadableEvent ReadableEvent = Process.HandleTable.GetObject<KReadableEvent>(Handle); - if (Event != null) - { - Event.Reset(); + KernelResult Result; - ThreadState.X0 = 0; + //TODO: KProcess support. + if (ReadableEvent != null) + { + Result = ReadableEvent.ClearIfSignaled(); } else { - Device.Log.PrintWarning(LogClass.KernelSvc, $"Invalid event handle 0x{Handle:x8}!"); + Result = KernelResult.InvalidHandle; + } - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); + if (Result == KernelResult.InvalidState) + { + Device.Log.PrintDebug(LogClass.KernelSvc, "Operation failed with error: " + Result + "!"); + } + else if (Result != KernelResult.Success) + { + Device.Log.PrintWarning(LogClass.KernelSvc, "Operation failed with error: " + Result + "!"); } + + return Result; } private void SvcGetSystemTick(AThreadState ThreadState) @@ -96,10 +162,13 @@ namespace Ryujinx.HLE.HOS.Kernel //actually exists, return error codes otherwise. KSession Session = new KSession(ServiceFactory.MakeService(System, Name), Name); - ulong Handle = (ulong)Process.HandleTable.OpenHandle(Session); + if (Process.HandleTable.GenerateHandle(Session, out int Handle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } ThreadState.X0 = 0; - ThreadState.X1 = Handle; + ThreadState.X1 = (uint)Handle; } private void SvcSendSyncRequest(AThreadState ThreadState) @@ -122,7 +191,7 @@ namespace Ryujinx.HLE.HOS.Kernel byte[] MessageData = Memory.ReadBytes(MessagePtr, Size); - KSession Session = Process.HandleTable.GetData<KSession>(Handle); + KSession Session = Process.HandleTable.GetObject<KSession>(Handle); if (Session != null) { @@ -206,7 +275,8 @@ namespace Ryujinx.HLE.HOS.Kernel if (InfoType == 18 || InfoType == 19 || InfoType == 20 || - InfoType == 21) + InfoType == 21 || + InfoType == 22) { ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue); @@ -287,5 +357,37 @@ namespace Ryujinx.HLE.HOS.Kernel ThreadState.X0 = 0; } + + private void CreateEvent64(AThreadState State) + { + KernelResult Result = CreateEvent(out int WEventHandle, out int REventHandle); + + State.X0 = (ulong)Result; + State.X1 = (ulong)WEventHandle; + State.X2 = (ulong)REventHandle; + } + + private KernelResult CreateEvent(out int WEventHandle, out int REventHandle) + { + KEvent Event = new KEvent(System); + + KernelResult Result = Process.HandleTable.GenerateHandle(Event.WritableEvent, out WEventHandle); + + if (Result == KernelResult.Success) + { + Result = Process.HandleTable.GenerateHandle(Event.ReadableEvent, out REventHandle); + + if (Result != KernelResult.Success) + { + Process.HandleTable.CloseHandle(WEventHandle); + } + } + else + { + REventHandle = 0; + } + + return Result; + } } } diff --git a/Ryujinx.HLE/HOS/Kernel/SvcThread.cs b/Ryujinx.HLE/HOS/Kernel/SvcThread.cs index dc296b06..d9273e23 100644 --- a/Ryujinx.HLE/HOS/Kernel/SvcThread.cs +++ b/Ryujinx.HLE/HOS/Kernel/SvcThread.cs @@ -53,7 +53,7 @@ namespace Ryujinx.HLE.HOS.Kernel { int Handle = (int)ThreadState.X0; - KThread Thread = Process.HandleTable.GetData<KThread>(Handle); + KThread Thread = Process.HandleTable.GetObject<KThread>(Handle); if (Thread != null) { @@ -112,7 +112,7 @@ namespace Ryujinx.HLE.HOS.Kernel { int Handle = (int)ThreadState.X1; - KThread Thread = GetThread(ThreadState.Tpidr, Handle); + KThread Thread = Process.HandleTable.GetKThread(Handle); if (Thread != null) { @@ -138,7 +138,7 @@ namespace Ryujinx.HLE.HOS.Kernel //TODO: NPDM check. - KThread Thread = GetThread(ThreadState.Tpidr, Handle); + KThread Thread = Process.HandleTable.GetKThread(Handle); if (Thread == null) { @@ -160,7 +160,7 @@ namespace Ryujinx.HLE.HOS.Kernel Device.Log.PrintDebug(LogClass.KernelSvc, "Handle = 0x" + Handle.ToString("x8")); - KThread Thread = GetThread(ThreadState.Tpidr, Handle); + KThread Thread = Process.HandleTable.GetKThread(Handle); if (Thread != null) { @@ -178,12 +178,12 @@ namespace Ryujinx.HLE.HOS.Kernel private void SvcSetThreadCoreMask(AThreadState ThreadState) { - int ThreadHandle = (int)ThreadState.X0; + int Handle = (int)ThreadState.X0; int PrefferedCore = (int)ThreadState.X1; long AffinityMask = (long)ThreadState.X2; Device.Log.PrintDebug(LogClass.KernelSvc, - "ThreadHandle = 0x" + ThreadHandle .ToString("x8") + ", " + + "Handle = 0x" + Handle .ToString("x8") + ", " + "PrefferedCore = 0x" + PrefferedCore.ToString("x8") + ", " + "AffinityMask = 0x" + AffinityMask .ToString("x16")); @@ -219,11 +219,11 @@ namespace Ryujinx.HLE.HOS.Kernel } } - KThread Thread = GetThread(ThreadState.Tpidr, ThreadHandle); + KThread Thread = Process.HandleTable.GetKThread(Handle); if (Thread == null) { - Device.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{ThreadHandle:x8}!"); + Device.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!"); ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); @@ -249,7 +249,7 @@ namespace Ryujinx.HLE.HOS.Kernel { int Handle = (int)ThreadState.X1; - KThread Thread = GetThread(ThreadState.Tpidr, Handle); + KThread Thread = Process.HandleTable.GetKThread(Handle); if (Thread != null) { @@ -269,7 +269,7 @@ namespace Ryujinx.HLE.HOS.Kernel int Handle = (int)ThreadState.X0; bool Pause = (int)ThreadState.X1 == 1; - KThread Thread = Process.HandleTable.GetData<KThread>(Handle); + KThread Thread = Process.HandleTable.GetObject<KThread>(Handle); if (Thread == null) { @@ -304,7 +304,7 @@ namespace Ryujinx.HLE.HOS.Kernel long Position = (long)ThreadState.X0; int Handle = (int)ThreadState.X1; - KThread Thread = Process.HandleTable.GetData<KThread>(Handle); + KThread Thread = Process.HandleTable.GetObject<KThread>(Handle); if (Thread == null) { diff --git a/Ryujinx.HLE/HOS/Kernel/SvcThreadSync.cs b/Ryujinx.HLE/HOS/Kernel/SvcThreadSync.cs index 868e0172..db9f6fb4 100644 --- a/Ryujinx.HLE/HOS/Kernel/SvcThreadSync.cs +++ b/Ryujinx.HLE/HOS/Kernel/SvcThreadSync.cs @@ -1,5 +1,6 @@ using ChocolArm64.State; using Ryujinx.HLE.Logging; +using System.Collections.Generic; using static Ryujinx.HLE.HOS.ErrorCode; @@ -25,22 +26,27 @@ namespace Ryujinx.HLE.HOS.Kernel return; } - KSynchronizationObject[] SyncObjs = new KSynchronizationObject[HandlesCount]; + List<KSynchronizationObject> SyncObjs = new List<KSynchronizationObject>(); for (int Index = 0; Index < HandlesCount; Index++) { int Handle = Memory.ReadInt32(HandlesPtr + Index * 4); - KSynchronizationObject SyncObj = Process.HandleTable.GetData<KSynchronizationObject>(Handle); + KSynchronizationObject SyncObj = Process.HandleTable.GetObject<KSynchronizationObject>(Handle); - SyncObjs[Index] = SyncObj; + if (SyncObj == null) + { + break; + } + + SyncObjs.Add(SyncObj); } int HndIndex = (int)ThreadState.X1; ulong High = ThreadState.X1 & (0xffffffffUL << 32); - long Result = System.Synchronization.WaitFor(SyncObjs, Timeout, ref HndIndex); + long Result = System.Synchronization.WaitFor(SyncObjs.ToArray(), Timeout, ref HndIndex); if (Result != 0) { @@ -65,7 +71,7 @@ namespace Ryujinx.HLE.HOS.Kernel Device.Log.PrintDebug(LogClass.KernelSvc, "ThreadHandle = 0x" + ThreadHandle.ToString("x8")); - KThread Thread = Process.HandleTable.GetData<KThread>(ThreadHandle); + KThread Thread = Process.HandleTable.GetKThread(ThreadHandle); if (Thread == null) { |
