aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-09-23 15:11:46 -0300
committerThomas Guillemard <thog@protonmail.com>2018-09-23 20:11:46 +0200
commit7de7b559adc1924d3ff31cc58b281f70e468155f (patch)
tree3701e1687f7fc4c4bafdffd5abda1966e6ce320f
parent54ed9096bd4add5cf2ca320123f551f60c06a57f (diff)
Improve kernel events implementation (#430)
* Improve kernel events implementation * Some cleanup * Address PR feedback
-rw-r--r--Ryujinx.HLE/HOS/Horizon.cs6
-rw-r--r--Ryujinx.HLE/HOS/Ipc/IpcHandler.cs5
-rw-r--r--Ryujinx.HLE/HOS/Kernel/HleScheduler.cs9
-rw-r--r--Ryujinx.HLE/HOS/Kernel/KAddressArbiter.cs4
-rw-r--r--Ryujinx.HLE/HOS/Kernel/KEvent.cs36
-rw-r--r--Ryujinx.HLE/HOS/Kernel/KHandleEntry.cs17
-rw-r--r--Ryujinx.HLE/HOS/Kernel/KProcessHandleTable.cs173
-rw-r--r--Ryujinx.HLE/HOS/Kernel/KReadableEvent.cs62
-rw-r--r--Ryujinx.HLE/HOS/Kernel/KScheduler.cs7
-rw-r--r--Ryujinx.HLE/HOS/Kernel/KWritableEvent.cs22
-rw-r--r--Ryujinx.HLE/HOS/Kernel/KernelErr.cs1
-rw-r--r--Ryujinx.HLE/HOS/Kernel/KernelResult.cs10
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SvcHandler.cs23
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SvcMemory.cs8
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SvcSystem.cs138
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SvcThread.cs22
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SvcThreadSync.cs16
-rw-r--r--Ryujinx.HLE/HOS/Process.cs29
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/ICommonStateGetter.cs11
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/IHomeMenuFunctions.cs6
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/ILibraryAppletAccessor.cs8
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/ISelfController.cs8
-rw-r--r--Ryujinx.HLE/HOS/Services/Aud/AudioOut/IAudioOut.cs5
-rw-r--r--Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/IAudioRenderer.cs7
-rw-r--r--Ryujinx.HLE/HOS/Services/Aud/IAudioDevice.cs18
-rw-r--r--Ryujinx.HLE/HOS/Services/Aud/IAudioOutManager.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/IAppletResource.cs6
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs24
-rw-r--r--Ryujinx.HLE/HOS/Services/IpcService.cs7
-rw-r--r--Ryujinx.HLE/HOS/Services/Nfp/IUser.cs16
-rw-r--r--Ryujinx.HLE/HOS/Services/Nifm/IRequest.cs12
-rw-r--r--Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs5
-rw-r--r--Ryujinx.HLE/HOS/Services/Pl/ISharedFontManager.cs7
-rw-r--r--Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs6
-rw-r--r--Ryujinx.HLE/HOS/Services/Vi/IApplicationDisplayService.cs7
-rw-r--r--Ryujinx.HLE/HOS/Services/Vi/IHOSBinderDriver.cs7
-rw-r--r--Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs2
-rw-r--r--Ryujinx.HLE/HOS/SystemState/AppletStateMgr.cs4
38 files changed, 596 insertions, 160 deletions
diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs
index f8ec8914..d52c8af0 100644
--- a/Ryujinx.HLE/HOS/Horizon.cs
+++ b/Ryujinx.HLE/HOS/Horizon.cs
@@ -71,6 +71,8 @@ namespace Ryujinx.HLE.HOS
Withholders = new LinkedList<KThread>();
+ Scheduler.StartAutoPreemptionThread();
+
if (!Device.Memory.Allocator.TryAllocate(HidSize, out long HidPA) ||
!Device.Memory.Allocator.TryAllocate(FontSize, out long FontPA))
{
@@ -212,7 +214,7 @@ namespace Ryujinx.HLE.HOS
}
MainNca.SetBaseNca(PatchNca);
-
+
if (ControlNca != null)
{
ReadControlData(ControlNca);
@@ -466,7 +468,7 @@ namespace Ryujinx.HLE.HOS
public void SignalVsync()
{
- VsyncEvent.Signal();
+ VsyncEvent.ReadableEvent.Signal();
}
private Process MakeProcess(Npdm MetaData = null)
diff --git a/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs b/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs
index 08a4cdb5..fca995c0 100644
--- a/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs
+++ b/Ryujinx.HLE/HOS/Ipc/IpcHandler.cs
@@ -73,7 +73,10 @@ namespace Ryujinx.HLE.HOS.Ipc
{
int Unknown = ReqReader.ReadInt32();
- int Handle = Process.HandleTable.OpenHandle(Session);
+ if (Process.HandleTable.GenerateHandle(Session, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
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)
{
diff --git a/Ryujinx.HLE/HOS/Process.cs b/Ryujinx.HLE/HOS/Process.cs
index f7ec2604..3817f561 100644
--- a/Ryujinx.HLE/HOS/Process.cs
+++ b/Ryujinx.HLE/HOS/Process.cs
@@ -71,7 +71,22 @@ namespace Ryujinx.HLE.HOS
TlsPages = new List<KTlsPageManager>();
- HandleTable = new KProcessHandleTable();
+ int HandleTableSize = 1024;
+
+ if (MetaData != null)
+ {
+ foreach (KernelAccessControlItem Item in MetaData.ACI0.KernelAccessControl.Items)
+ {
+ if (Item.HasHandleTableSize)
+ {
+ HandleTableSize = Item.HandleTableSize;
+
+ break;
+ }
+ }
+ }
+
+ HandleTable = new KProcessHandleTable(Device.System, HandleTableSize);
AppletState = new AppletStateMgr(Device.System);
@@ -139,7 +154,7 @@ namespace Ryujinx.HLE.HOS
return false;
}
- KThread MainThread = HandleTable.GetData<KThread>(Handle);
+ KThread MainThread = HandleTable.GetKThread(Handle);
if (NeedsHbAbi)
{
@@ -190,7 +205,7 @@ namespace Ryujinx.HLE.HOS
Thread.LastPc = EntryPoint;
- int Handle = HandleTable.OpenHandle(Thread);
+ HandleTable.GenerateHandle(Thread, out int Handle);
CpuThread.ThreadState.CntfrqEl0 = TickFreq;
CpuThread.ThreadState.Tpidr = Tpidr;
@@ -427,13 +442,7 @@ namespace Ryujinx.HLE.HOS
Disposed = true;
- foreach (object Obj in HandleTable.Clear())
- {
- if (Obj is KSession Session)
- {
- Session.Dispose();
- }
- }
+ HandleTable.Destroy();
INvDrvServices.UnloadProcess(this);
diff --git a/Ryujinx.HLE/HOS/Services/Am/ICommonStateGetter.cs b/Ryujinx.HLE/HOS/Services/Am/ICommonStateGetter.cs
index 72049d6f..4ea18d32 100644
--- a/Ryujinx.HLE/HOS/Services/Am/ICommonStateGetter.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/ICommonStateGetter.cs
@@ -1,6 +1,7 @@
using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.Logging;
+using System;
using System.Collections.Generic;
using static Ryujinx.HLE.HOS.ErrorCode;
@@ -36,7 +37,10 @@ namespace Ryujinx.HLE.HOS.Services.Am
{
KEvent Event = Context.Process.AppletState.MessageEvent;
- int Handle = Context.Process.HandleTable.OpenHandle(Event);
+ if (Context.Process.HandleTable.GenerateHandle(Event.ReadableEvent, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
@@ -103,7 +107,10 @@ namespace Ryujinx.HLE.HOS.Services.Am
public long GetDefaultDisplayResolutionChangeEvent(ServiceCtx Context)
{
- int Handle = Context.Process.HandleTable.OpenHandle(DisplayResolutionChangeEvent);
+ if (Context.Process.HandleTable.GenerateHandle(DisplayResolutionChangeEvent.ReadableEvent, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
diff --git a/Ryujinx.HLE/HOS/Services/Am/IHomeMenuFunctions.cs b/Ryujinx.HLE/HOS/Services/Am/IHomeMenuFunctions.cs
index 0c271796..a476aff9 100644
--- a/Ryujinx.HLE/HOS/Services/Am/IHomeMenuFunctions.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/IHomeMenuFunctions.cs
@@ -1,6 +1,7 @@
using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.Logging;
+using System;
using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Am
@@ -34,7 +35,10 @@ namespace Ryujinx.HLE.HOS.Services.Am
public long GetPopFromGeneralChannelEvent(ServiceCtx Context)
{
- int Handle = Context.Process.HandleTable.OpenHandle(ChannelEvent);
+ if (Context.Process.HandleTable.GenerateHandle(ChannelEvent.ReadableEvent, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
diff --git a/Ryujinx.HLE/HOS/Services/Am/ILibraryAppletAccessor.cs b/Ryujinx.HLE/HOS/Services/Am/ILibraryAppletAccessor.cs
index a9de3ebd..07b8d971 100644
--- a/Ryujinx.HLE/HOS/Services/Am/ILibraryAppletAccessor.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/ILibraryAppletAccessor.cs
@@ -1,6 +1,7 @@
using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.Logging;
+using System;
using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Am
@@ -29,9 +30,12 @@ namespace Ryujinx.HLE.HOS.Services.Am
public long GetAppletStateChangedEvent(ServiceCtx Context)
{
- StateChangedEvent.Signal();
+ StateChangedEvent.ReadableEvent.Signal();
- int Handle = Context.Process.HandleTable.OpenHandle(StateChangedEvent);
+ if (Context.Process.HandleTable.GenerateHandle(StateChangedEvent.ReadableEvent, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
diff --git a/Ryujinx.HLE/HOS/Services/Am/ISelfController.cs b/Ryujinx.HLE/HOS/Services/Am/ISelfController.cs
index fe882273..2c1d0c3b 100644
--- a/Ryujinx.HLE/HOS/Services/Am/ISelfController.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/ISelfController.cs
@@ -1,6 +1,7 @@
using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.Logging;
+using System;
using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Am
@@ -57,9 +58,12 @@ namespace Ryujinx.HLE.HOS.Services.Am
public long GetLibraryAppletLaunchableEvent(ServiceCtx Context)
{
- LaunchableEvent.Signal();
+ LaunchableEvent.ReadableEvent.Signal();
- int Handle = Context.Process.HandleTable.OpenHandle(LaunchableEvent);
+ if (Context.Process.HandleTable.GenerateHandle(LaunchableEvent.ReadableEvent, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
diff --git a/Ryujinx.HLE/HOS/Services/Aud/AudioOut/IAudioOut.cs b/Ryujinx.HLE/HOS/Services/Aud/AudioOut/IAudioOut.cs
index 2b0b5293..cd3d6e49 100644
--- a/Ryujinx.HLE/HOS/Services/Aud/AudioOut/IAudioOut.cs
+++ b/Ryujinx.HLE/HOS/Services/Aud/AudioOut/IAudioOut.cs
@@ -67,7 +67,10 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioOut
public long RegisterBufferEvent(ServiceCtx Context)
{
- int Handle = Context.Process.HandleTable.OpenHandle(ReleaseEvent);
+ if (Context.Process.HandleTable.GenerateHandle(ReleaseEvent.ReadableEvent, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
diff --git a/Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/IAudioRenderer.cs b/Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/IAudioRenderer.cs
index ae85bf01..85f82622 100644
--- a/Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/IAudioRenderer.cs
+++ b/Ryujinx.HLE/HOS/Services/Aud/AudioRenderer/IAudioRenderer.cs
@@ -72,7 +72,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
private void AudioCallback()
{
- UpdateEvent.Signal();
+ UpdateEvent.ReadableEvent.Signal();
}
private static T[] CreateArray<T>(int Size) where T : new()
@@ -218,7 +218,10 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
public long QuerySystemEvent(ServiceCtx Context)
{
- int Handle = Context.Process.HandleTable.OpenHandle(UpdateEvent);
+ if (Context.Process.HandleTable.GenerateHandle(UpdateEvent.ReadableEvent, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
diff --git a/Ryujinx.HLE/HOS/Services/Aud/IAudioDevice.cs b/Ryujinx.HLE/HOS/Services/Aud/IAudioDevice.cs
index adecc721..a1a228ed 100644
--- a/Ryujinx.HLE/HOS/Services/Aud/IAudioDevice.cs
+++ b/Ryujinx.HLE/HOS/Services/Aud/IAudioDevice.cs
@@ -2,6 +2,7 @@ using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.HLE.Logging;
+using System;
using System.Collections.Generic;
using System.Text;
@@ -35,7 +36,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud
SystemEvent = new KEvent(System);
//TODO: We shouldn't be signaling this here.
- SystemEvent.Signal();
+ SystemEvent.ReadableEvent.Signal();
}
public long ListAudioDeviceName(ServiceCtx Context)
@@ -107,7 +108,10 @@ namespace Ryujinx.HLE.HOS.Services.Aud
public long QueryAudioDeviceSystemEvent(ServiceCtx Context)
{
- int Handle = Context.Process.HandleTable.OpenHandle(SystemEvent);
+ if (Context.Process.HandleTable.GenerateHandle(SystemEvent.ReadableEvent, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
@@ -200,7 +204,10 @@ namespace Ryujinx.HLE.HOS.Services.Aud
public long QueryAudioDeviceInputEvent(ServiceCtx Context)
{
- int Handle = Context.Process.HandleTable.OpenHandle(SystemEvent);
+ if (Context.Process.HandleTable.GenerateHandle(SystemEvent.ReadableEvent, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
@@ -211,7 +218,10 @@ namespace Ryujinx.HLE.HOS.Services.Aud
public long QueryAudioDeviceOutputEvent(ServiceCtx Context)
{
- int Handle = Context.Process.HandleTable.OpenHandle(SystemEvent);
+ if (Context.Process.HandleTable.GenerateHandle(SystemEvent.ReadableEvent, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
diff --git a/Ryujinx.HLE/HOS/Services/Aud/IAudioOutManager.cs b/Ryujinx.HLE/HOS/Services/Aud/IAudioOutManager.cs
index ef9250d9..44b856cd 100644
--- a/Ryujinx.HLE/HOS/Services/Aud/IAudioOutManager.cs
+++ b/Ryujinx.HLE/HOS/Services/Aud/IAudioOutManager.cs
@@ -150,7 +150,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud
ReleaseCallback Callback = () =>
{
- ReleaseEvent.Signal();
+ ReleaseEvent.ReadableEvent.Signal();
};
IAalOutput AudioOut = Context.Device.AudioOut;
diff --git a/Ryujinx.HLE/HOS/Services/Hid/IAppletResource.cs b/Ryujinx.HLE/HOS/Services/Hid/IAppletResource.cs
index 012ccb40..89a17acf 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/IAppletResource.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/IAppletResource.cs
@@ -1,5 +1,6 @@
using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel;
+using System;
using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Hid
@@ -24,7 +25,10 @@ namespace Ryujinx.HLE.HOS.Services.Hid
public long GetSharedMemoryHandle(ServiceCtx Context)
{
- int Handle = Context.Process.HandleTable.OpenHandle(HidSharedMem);
+ if (Context.Process.HandleTable.GenerateHandle(HidSharedMem, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
diff --git a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs
index b42f76fa..e88ca7e4 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs
@@ -2,7 +2,6 @@ using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.Input;
using Ryujinx.HLE.Logging;
-using Ryujinx.HLE.Utilities;
using System;
using System.Collections.Generic;
@@ -219,7 +218,10 @@ namespace Ryujinx.HLE.HOS.Services.Hid
{
long XpadId = Context.RequestData.ReadInt64();
- XpadIdEventHandle = Context.Process.HandleTable.OpenHandle(XpadIdEvent);
+ if (Context.Process.HandleTable.GenerateHandle(XpadIdEvent, out XpadIdEventHandle) == 0)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(XpadIdEventHandle);
@@ -411,7 +413,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
SixAxisSensorFusionEnabled = Context.RequestData.ReadBoolean();
int SixAxisSensorHandle = Context.RequestData.ReadInt32();
long AppletResourceUserId = Context.RequestData.ReadInt64();
-
+
Context.Device.Log.PrintStub(LogClass.ServiceHid, $"Stubbed. AppletResourceUserId: {AppletResourceUserId} - " +
$"SixAxisSensorHandle: {SixAxisSensorHandle} - " +
$"SixAxisSensorFusionEnabled: {SixAxisSensorFusionEnabled}");
@@ -619,7 +621,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// IsSixAxisSensorAtRest(nn::hid::SixAxisSensorHandle, nn::applet::AppletResourceUserId) -> bool IsAsRest
public long IsSixAxisSensorAtRest(ServiceCtx Context)
- {
+ {
int SixAxisSensorHandle = Context.RequestData.ReadInt32();
long AppletResourceUserId = Context.RequestData.ReadInt64();
@@ -712,7 +714,10 @@ namespace Ryujinx.HLE.HOS.Services.Hid
int NpadId = Context.RequestData.ReadInt32();
long NpadStyleSet = Context.RequestData.ReadInt64();
- int Handle = Context.Process.HandleTable.OpenHandle(NpadStyleSetUpdateEvent);
+ if (Context.Process.HandleTable.GenerateHandle(NpadStyleSetUpdateEvent, out int Handle) == 0)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
@@ -1135,7 +1140,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
{
int ConsoleSixAxisSensorHandle = Context.RequestData.ReadInt32();
long AppletResourceUserId = Context.RequestData.ReadInt64();
-
+
Context.Device.Log.PrintStub(LogClass.ServiceHid, $"Stubbed. AppletResourceUserId: {AppletResourceUserId} - " +
$"ConsoleSixAxisSensorHandle: {ConsoleSixAxisSensorHandle}");
@@ -1351,7 +1356,10 @@ namespace Ryujinx.HLE.HOS.Services.Hid
{
int PalmaConnectionHandle = Context.RequestData.ReadInt32();
- int Handle = Context.Process.HandleTable.OpenHandle(PalmaOperationCompleteEvent);
+ if (Context.Process.HandleTable.GenerateHandle(PalmaOperationCompleteEvent, out int Handle) == 0)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
@@ -1393,7 +1401,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
int PalmaConnectionHandle = Context.RequestData.ReadInt32();
long FrModeType = Context.RequestData.ReadInt64();
- Context.Device.Log.PrintStub(LogClass.ServiceHid, $"Stubbed. PalmaConnectionHandle: {PalmaConnectionHandle} - " +
+ Context.Device.Log.PrintStub(LogClass.ServiceHid, $"Stubbed. PalmaConnectionHandle: {PalmaConnectionHandle} - " +
$"FrModeType: {FrModeType}");
return 0;
diff --git a/Ryujinx.HLE/HOS/Services/IpcService.cs b/Ryujinx.HLE/HOS/Services/IpcService.cs
index 8e487d55..e9d82000 100644
--- a/Ryujinx.HLE/HOS/Services/IpcService.cs
+++ b/Ryujinx.HLE/HOS/Services/IpcService.cs
@@ -132,7 +132,10 @@ namespace Ryujinx.HLE.HOS.Services
{
KSession Session = new KSession(Obj, Context.Session.ServiceName);
- int Handle = Context.Process.HandleTable.OpenHandle(Session);
+ if (Context.Process.HandleTable.GenerateHandle(Session, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
}
@@ -146,7 +149,7 @@ namespace Ryujinx.HLE.HOS.Services
{
int Handle = Context.Request.HandleDesc.ToMove[Index];
- KSession Session = Context.Process.HandleTable.GetData<KSession>(Handle);
+ KSession Session = Context.Process.HandleTable.GetObject<KSession>(Handle);
return Session?.Service is T ? (T)Session.Service : null;
}
diff --git a/Ryujinx.HLE/HOS/Services/Nfp/IUser.cs b/Ryujinx.HLE/HOS/Services/Nfp/IUser.cs
index 33f73967..72a385d2 100644
--- a/Ryujinx.HLE/HOS/Services/Nfp/IUser.cs
+++ b/Ryujinx.HLE/HOS/Services/Nfp/IUser.cs
@@ -2,6 +2,7 @@
using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.Input;
using Ryujinx.HLE.Logging;
+using System;
using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Nfp
@@ -55,7 +56,10 @@ namespace Ryujinx.HLE.HOS.Services.Nfp
{
Context.Device.Log.PrintStub(LogClass.ServiceNfp, "Stubbed.");
- int Handle = Context.Process.HandleTable.OpenHandle(ActivateEvent);
+ if (Context.Process.HandleTable.GenerateHandle(ActivateEvent.ReadableEvent, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);;
@@ -66,7 +70,10 @@ namespace Ryujinx.HLE.HOS.Services.Nfp
{
Context.Device.Log.PrintStub(LogClass.ServiceNfp, "Stubbed.");
- int Handle = Context.Process.HandleTable.OpenHandle(DeactivateEvent);
+ if (Context.Process.HandleTable.GenerateHandle(DeactivateEvent.ReadableEvent, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
@@ -104,7 +111,10 @@ namespace Ryujinx.HLE.HOS.Services.Nfp
{
Context.Device.Log.PrintStub(LogClass.ServiceNfp, "Stubbed.");
- int Handle = Context.Process.HandleTable.OpenHandle(AvailabilityChangeEvent);
+ if (Context.Process.HandleTable.GenerateHandle(AvailabilityChangeEvent.ReadableEvent, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
diff --git a/Ryujinx.HLE/HOS/Services/Nifm/IRequest.cs b/Ryujinx.HLE/HOS/Services/Nifm/IRequest.cs
index 3f4df719..9b501d7c 100644
--- a/Ryujinx.HLE/HOS/Services/Nifm/IRequest.cs
+++ b/Ryujinx.HLE/HOS/Services/Nifm/IRequest.cs
@@ -1,6 +1,7 @@
using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.Logging;
+using System;
using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Nifm
@@ -48,8 +49,15 @@ namespace Ryujinx.HLE.HOS.Services.Nifm
public long GetSystemEventReadableHandles(ServiceCtx Context)
{
- int Handle0 = Context.Process.HandleTable.OpenHandle(Event0);
- int Handle1 = Context.Process.HandleTable.OpenHandle(Event1);
+ if (Context.Process.HandleTable.GenerateHandle(Event0.ReadableEvent, out int Handle0) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
+
+ if (Context.Process.HandleTable.GenerateHandle(Event1.ReadableEvent, out int Handle1) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle0, Handle1);
diff --git a/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs b/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs
index 7d558992..96de8cab 100644
--- a/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs
+++ b/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs
@@ -123,7 +123,10 @@ namespace Ryujinx.HLE.HOS.Services.Nv
int EventId = Context.RequestData.ReadInt32();
//TODO: Use Fd/EventId, different channels have different events.
- int Handle = Context.Process.HandleTable.OpenHandle(Event);
+ if (Context.Process.HandleTable.GenerateHandle(Event.ReadableEvent, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
diff --git a/Ryujinx.HLE/HOS/Services/Pl/ISharedFontManager.cs b/Ryujinx.HLE/HOS/Services/Pl/ISharedFontManager.cs
index 92821217..d73adc0e 100644
--- a/Ryujinx.HLE/HOS/Services/Pl/ISharedFontManager.cs
+++ b/Ryujinx.HLE/HOS/Services/Pl/ISharedFontManager.cs
@@ -1,5 +1,7 @@
using Ryujinx.HLE.HOS.Font;
using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel;
+using System;
using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Pl
@@ -65,7 +67,10 @@ namespace Ryujinx.HLE.HOS.Services.Pl
{
Context.Device.System.Font.EnsureInitialized();
- int Handle = Context.Process.HandleTable.OpenHandle(Context.Device.System.FontSharedMem);
+ if (Context.Process.HandleTable.GenerateHandle(Context.Device.System.FontSharedMem, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
diff --git a/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs b/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs
index c56d65db..0c26b7d9 100644
--- a/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs
+++ b/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs
@@ -1,5 +1,6 @@
using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel;
+using System;
using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Sm
@@ -59,7 +60,10 @@ namespace Ryujinx.HLE.HOS.Services.Sm
KSession Session = new KSession(ServiceFactory.MakeService(Context.Device.System, Name), Name);
- int Handle = Context.Process.HandleTable.OpenHandle(Session);
+ if (Context.Process.HandleTable.GenerateHandle(Session, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
diff --git a/Ryujinx.HLE/HOS/Services/Vi/IApplicationDisplayService.cs b/Ryujinx.HLE/HOS/Services/Vi/IApplicationDisplayService.cs
index 54238279..33a1dee9 100644
--- a/Ryujinx.HLE/HOS/Services/Vi/IApplicationDisplayService.cs
+++ b/Ryujinx.HLE/HOS/Services/Vi/IApplicationDisplayService.cs
@@ -1,6 +1,8 @@
using ChocolArm64.Memory;
using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel;
using System.Collections.Generic;
+using System;
using System.IO;
using System.Text;
@@ -178,7 +180,10 @@ namespace Ryujinx.HLE.HOS.Services.Vi
{
string Name = GetDisplayName(Context);
- int Handle = Context.Process.HandleTable.OpenHandle(Context.Device.System.VsyncEvent);
+ if (Context.Process.HandleTable.GenerateHandle(Context.Device.System.VsyncEvent.ReadableEvent, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
diff --git a/Ryujinx.HLE/HOS/Services/Vi/IHOSBinderDriver.cs b/Ryujinx.HLE/HOS/Services/Vi/IHOSBinderDriver.cs
index d47fc30a..09a37b0f 100644
--- a/Ryujinx.HLE/HOS/Services/Vi/IHOSBinderDriver.cs
+++ b/Ryujinx.HLE/HOS/Services/Vi/IHOSBinderDriver.cs
@@ -29,7 +29,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
BinderEvent = new KEvent(System);
- BinderEvent.Signal();
+ BinderEvent.ReadableEvent.Signal();
Flinger = new NvFlinger(Renderer, BinderEvent);
}
@@ -77,7 +77,10 @@ namespace Ryujinx.HLE.HOS.Services.Vi
int Id = Context.RequestData.ReadInt32();
uint Unk = Context.RequestData.ReadUInt32();
- int Handle = Context.Process.HandleTable.OpenHandle(BinderEvent);
+ if (Context.Process.HandleTable.GenerateHandle(BinderEvent.ReadableEvent, out int Handle) != KernelResult.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
diff --git a/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs b/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs
index dcdf5d17..c5f38211 100644
--- a/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs
+++ b/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs
@@ -338,7 +338,7 @@ namespace Ryujinx.HLE.HOS.Services.Android
{
BufferQueue[Slot].State = BufferState.Free;
- BinderEvent.Signal();
+ BinderEvent.ReadableEvent.Signal();
WaitBufferFree.Set();
}
diff --git a/Ryujinx.HLE/HOS/SystemState/AppletStateMgr.cs b/Ryujinx.HLE/HOS/SystemState/AppletStateMgr.cs
index b537b06a..274892c0 100644
--- a/Ryujinx.HLE/HOS/SystemState/AppletStateMgr.cs
+++ b/Ryujinx.HLE/HOS/SystemState/AppletStateMgr.cs
@@ -32,14 +32,14 @@ namespace Ryujinx.HLE.HOS.SystemState
{
Messages.Enqueue(Message);
- MessageEvent.Signal();
+ MessageEvent.ReadableEvent.Signal();
}
public bool TryDequeueMessage(out MessageInfo Message)
{
if (Messages.Count < 2)
{
- MessageEvent.Reset();
+ MessageEvent.ReadableEvent.Clear();
}
return Messages.TryDequeue(out Message);