Improve kernel events implementation (#430)

* Improve kernel events implementation

* Some cleanup

* Address PR feedback
This commit is contained in:
gdkchan 2018-09-23 15:11:46 -03:00 committed by Thomas Guillemard
parent 54ed9096bd
commit 7de7b559ad
38 changed files with 597 additions and 161 deletions

View file

@ -71,6 +71,8 @@ namespace Ryujinx.HLE.HOS
Withholders = new LinkedList<KThread>(); Withholders = new LinkedList<KThread>();
Scheduler.StartAutoPreemptionThread();
if (!Device.Memory.Allocator.TryAllocate(HidSize, out long HidPA) || if (!Device.Memory.Allocator.TryAllocate(HidSize, out long HidPA) ||
!Device.Memory.Allocator.TryAllocate(FontSize, out long FontPA)) !Device.Memory.Allocator.TryAllocate(FontSize, out long FontPA))
{ {
@ -466,7 +468,7 @@ namespace Ryujinx.HLE.HOS
public void SignalVsync() public void SignalVsync()
{ {
VsyncEvent.Signal(); VsyncEvent.ReadableEvent.Signal();
} }
private Process MakeProcess(Npdm MetaData = null) private Process MakeProcess(Npdm MetaData = null)

View file

@ -73,7 +73,10 @@ namespace Ryujinx.HLE.HOS.Ipc
{ {
int Unknown = ReqReader.ReadInt32(); 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); Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);

View file

@ -15,6 +15,15 @@ namespace Ryujinx.HLE.HOS.Kernel
private bool KeepPreempting; private bool KeepPreempting;
public void StartAutoPreemptionThread()
{
Thread PreemptionThread = new Thread(PreemptCurrentThread);
KeepPreempting = true;
PreemptionThread.Start();
}
public void ContextSwitch() public void ContextSwitch()
{ {
lock (CoreContexts) lock (CoreContexts)

View file

@ -51,7 +51,7 @@ namespace Ryujinx.HLE.HOS.Kernel
return 0; return 0;
} }
KThread MutexOwner = Process.HandleTable.GetData<KThread>(OwnerHandle); KThread MutexOwner = Process.HandleTable.GetObject<KThread>(OwnerHandle);
if (MutexOwner == null) if (MutexOwner == null)
{ {
@ -282,7 +282,7 @@ namespace Ryujinx.HLE.HOS.Kernel
MutexValue &= ~HasListenersMask; MutexValue &= ~HasListenersMask;
KThread MutexOwner = Process.HandleTable.GetData<KThread>(MutexValue); KThread MutexOwner = Process.HandleTable.GetObject<KThread>(MutexValue);
if (MutexOwner != null) if (MutexOwner != null)
{ {

View file

@ -1,38 +1,14 @@
namespace Ryujinx.HLE.HOS.Kernel 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)
public KEvent(Horizon System, string Name = "") : base(System)
{ {
this.Name = Name; ReadableEvent = new KReadableEvent(System, this);
} WritableEvent = new KWritableEvent(this);
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()
{
return Signaled;
} }
} }
} }

View file

@ -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;
}
}
}

View file

@ -1,34 +1,183 @@
using System.Collections.Generic; using System;
namespace Ryujinx.HLE.HOS.Kernel namespace Ryujinx.HLE.HOS.Kernel
{ {
class KProcessHandleTable 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 int OpenHandle(object Obj) public KernelResult GenerateHandle(object Obj, out int Handle)
{ {
return Handles.Add(Obj); 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 T GetData<T>(int Handle) public bool CloseHandle(int Handle)
{ {
return Handles.GetData<T>(Handle); 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 object CloseHandle(int Handle) public T GetObject<T>(int Handle)
{ {
return Handles.Delete(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 ICollection<object> Clear() public KThread GetKThread(int Handle)
{ {
return Handles.Clear(); if (Handle == SelfThreadHandle)
{
return System.Scheduler.GetCurrentThread();
}
else
{
return GetObject<KThread>(Handle);
}
}
public void Destroy()
{
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;
}
}
}
} }
} }
} }

View file

@ -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;
}
}
}

View file

@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
namespace Ryujinx.HLE.HOS.Kernel namespace Ryujinx.HLE.HOS.Kernel
{ {
@ -35,12 +34,6 @@ namespace Ryujinx.HLE.HOS.Kernel
{ {
CoreContexts[Core] = new KCoreContext(this, CoreManager); CoreContexts[Core] = new KCoreContext(this, CoreManager);
} }
Thread PreemptionThread = new Thread(PreemptCurrentThread);
KeepPreempting = true;
PreemptionThread.Start();
} }
private void PreemptThreads() private void PreemptThreads()

View file

@ -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();
}
}
}

View file

@ -6,6 +6,7 @@ namespace Ryujinx.HLE.HOS.Kernel
public const int InvalidSize = 101; public const int InvalidSize = 101;
public const int InvalidAddress = 102; public const int InvalidAddress = 102;
public const int OutOfMemory = 104; public const int OutOfMemory = 104;
public const int HandleTableFull = 105;
public const int NoAccessPerm = 106; public const int NoAccessPerm = 106;
public const int InvalidPermission = 108; public const int InvalidPermission = 108;
public const int InvalidMemRange = 110; public const int InvalidMemRange = 110;

View file

@ -0,0 +1,10 @@
namespace Ryujinx.HLE.HOS.Kernel
{
enum KernelResult
{
Success = 0,
HandleTableFull = 0xd201,
InvalidHandle = 0xe401,
InvalidState = 0xfa01
}
}

View file

@ -39,9 +39,6 @@ namespace Ryujinx.HLE.HOS.Kernel
} }
} }
private const uint SelfThreadHandle = 0xffff8000;
private const uint SelfProcessHandle = 0xffff8001;
private static Random Rng; private static Random Rng;
public SvcHandler(Switch Device, Process Process) public SvcHandler(Switch Device, Process Process)
@ -63,12 +60,13 @@ namespace Ryujinx.HLE.HOS.Kernel
{ 0x0e, SvcGetThreadCoreMask }, { 0x0e, SvcGetThreadCoreMask },
{ 0x0f, SvcSetThreadCoreMask }, { 0x0f, SvcSetThreadCoreMask },
{ 0x10, SvcGetCurrentProcessorNumber }, { 0x10, SvcGetCurrentProcessorNumber },
{ 0x12, SvcClearEvent }, { 0x11, SignalEvent64 },
{ 0x12, ClearEvent64 },
{ 0x13, SvcMapSharedMemory }, { 0x13, SvcMapSharedMemory },
{ 0x14, SvcUnmapSharedMemory }, { 0x14, SvcUnmapSharedMemory },
{ 0x15, SvcCreateTransferMemory }, { 0x15, SvcCreateTransferMemory },
{ 0x16, SvcCloseHandle }, { 0x16, SvcCloseHandle },
{ 0x17, SvcResetSignal }, { 0x17, ResetSignal64 },
{ 0x18, SvcWaitSynchronization }, { 0x18, SvcWaitSynchronization },
{ 0x19, SvcCancelSynchronization }, { 0x19, SvcCancelSynchronization },
{ 0x1a, SvcArbitrateLock }, { 0x1a, SvcArbitrateLock },
@ -88,7 +86,8 @@ namespace Ryujinx.HLE.HOS.Kernel
{ 0x32, SvcSetThreadActivity }, { 0x32, SvcSetThreadActivity },
{ 0x33, SvcGetThreadContext3 }, { 0x33, SvcGetThreadContext3 },
{ 0x34, SvcWaitForAddress }, { 0x34, SvcWaitForAddress },
{ 0x35, SvcSignalToAddress } { 0x35, SvcSignalToAddress },
{ 0x45, CreateEvent64 }
}; };
this.Device = Device; this.Device = Device;
@ -123,17 +122,5 @@ namespace Ryujinx.HLE.HOS.Kernel
throw new NotImplementedException($"0x{e.Id:x4}"); 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);
}
}
} }
} }

View file

@ -276,7 +276,7 @@ namespace Ryujinx.HLE.HOS.Kernel
return; return;
} }
KSharedMemory SharedMemory = Process.HandleTable.GetData<KSharedMemory>(Handle); KSharedMemory SharedMemory = Process.HandleTable.GetObject<KSharedMemory>(Handle);
if (SharedMemory == null) if (SharedMemory == null)
{ {
@ -348,7 +348,7 @@ namespace Ryujinx.HLE.HOS.Kernel
return; return;
} }
KSharedMemory SharedMemory = Process.HandleTable.GetData<KSharedMemory>(Handle); KSharedMemory SharedMemory = Process.HandleTable.GetObject<KSharedMemory>(Handle);
if (SharedMemory == null) if (SharedMemory == null)
{ {
@ -425,9 +425,9 @@ namespace Ryujinx.HLE.HOS.Kernel
KTransferMemory TransferMemory = new KTransferMemory(Position, Size); 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; ThreadState.X1 = (ulong)Handle;
} }

View file

@ -22,20 +22,73 @@ namespace Ryujinx.HLE.HOS.Kernel
Device.System.ExitProcess(Process.ProcessId); 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) private void SvcCloseHandle(AThreadState ThreadState)
{ {
int Handle = (int)ThreadState.X0; 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) if (Obj == null)
{ {
@ -60,24 +113,37 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = 0; 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) KernelResult Result;
//TODO: KProcess support.
if (ReadableEvent != null)
{ {
Event.Reset(); Result = ReadableEvent.ClearIfSignaled();
ThreadState.X0 = 0;
} }
else 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) private void SvcGetSystemTick(AThreadState ThreadState)
@ -96,10 +162,13 @@ namespace Ryujinx.HLE.HOS.Kernel
//actually exists, return error codes otherwise. //actually exists, return error codes otherwise.
KSession Session = new KSession(ServiceFactory.MakeService(System, Name), Name); 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.X0 = 0;
ThreadState.X1 = Handle; ThreadState.X1 = (uint)Handle;
} }
private void SvcSendSyncRequest(AThreadState ThreadState) private void SvcSendSyncRequest(AThreadState ThreadState)
@ -122,7 +191,7 @@ namespace Ryujinx.HLE.HOS.Kernel
byte[] MessageData = Memory.ReadBytes(MessagePtr, Size); byte[] MessageData = Memory.ReadBytes(MessagePtr, Size);
KSession Session = Process.HandleTable.GetData<KSession>(Handle); KSession Session = Process.HandleTable.GetObject<KSession>(Handle);
if (Session != null) if (Session != null)
{ {
@ -206,7 +275,8 @@ namespace Ryujinx.HLE.HOS.Kernel
if (InfoType == 18 || if (InfoType == 18 ||
InfoType == 19 || InfoType == 19 ||
InfoType == 20 || InfoType == 20 ||
InfoType == 21) InfoType == 21 ||
InfoType == 22)
{ {
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue); ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue);
@ -287,5 +357,37 @@ namespace Ryujinx.HLE.HOS.Kernel
ThreadState.X0 = 0; 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;
}
} }
} }

View file

@ -53,7 +53,7 @@ namespace Ryujinx.HLE.HOS.Kernel
{ {
int Handle = (int)ThreadState.X0; int Handle = (int)ThreadState.X0;
KThread Thread = Process.HandleTable.GetData<KThread>(Handle); KThread Thread = Process.HandleTable.GetObject<KThread>(Handle);
if (Thread != null) if (Thread != null)
{ {
@ -112,7 +112,7 @@ namespace Ryujinx.HLE.HOS.Kernel
{ {
int Handle = (int)ThreadState.X1; int Handle = (int)ThreadState.X1;
KThread Thread = GetThread(ThreadState.Tpidr, Handle); KThread Thread = Process.HandleTable.GetKThread(Handle);
if (Thread != null) if (Thread != null)
{ {
@ -138,7 +138,7 @@ namespace Ryujinx.HLE.HOS.Kernel
//TODO: NPDM check. //TODO: NPDM check.
KThread Thread = GetThread(ThreadState.Tpidr, Handle); KThread Thread = Process.HandleTable.GetKThread(Handle);
if (Thread == null) if (Thread == null)
{ {
@ -160,7 +160,7 @@ namespace Ryujinx.HLE.HOS.Kernel
Device.Log.PrintDebug(LogClass.KernelSvc, "Handle = 0x" + Handle.ToString("x8")); 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) if (Thread != null)
{ {
@ -178,12 +178,12 @@ namespace Ryujinx.HLE.HOS.Kernel
private void SvcSetThreadCoreMask(AThreadState ThreadState) private void SvcSetThreadCoreMask(AThreadState ThreadState)
{ {
int ThreadHandle = (int)ThreadState.X0; int Handle = (int)ThreadState.X0;
int PrefferedCore = (int)ThreadState.X1; int PrefferedCore = (int)ThreadState.X1;
long AffinityMask = (long)ThreadState.X2; long AffinityMask = (long)ThreadState.X2;
Device.Log.PrintDebug(LogClass.KernelSvc, Device.Log.PrintDebug(LogClass.KernelSvc,
"ThreadHandle = 0x" + ThreadHandle .ToString("x8") + ", " + "Handle = 0x" + Handle .ToString("x8") + ", " +
"PrefferedCore = 0x" + PrefferedCore.ToString("x8") + ", " + "PrefferedCore = 0x" + PrefferedCore.ToString("x8") + ", " +
"AffinityMask = 0x" + AffinityMask .ToString("x16")); "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) 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); ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
@ -249,7 +249,7 @@ namespace Ryujinx.HLE.HOS.Kernel
{ {
int Handle = (int)ThreadState.X1; int Handle = (int)ThreadState.X1;
KThread Thread = GetThread(ThreadState.Tpidr, Handle); KThread Thread = Process.HandleTable.GetKThread(Handle);
if (Thread != null) if (Thread != null)
{ {
@ -269,7 +269,7 @@ namespace Ryujinx.HLE.HOS.Kernel
int Handle = (int)ThreadState.X0; int Handle = (int)ThreadState.X0;
bool Pause = (int)ThreadState.X1 == 1; bool Pause = (int)ThreadState.X1 == 1;
KThread Thread = Process.HandleTable.GetData<KThread>(Handle); KThread Thread = Process.HandleTable.GetObject<KThread>(Handle);
if (Thread == null) if (Thread == null)
{ {
@ -304,7 +304,7 @@ namespace Ryujinx.HLE.HOS.Kernel
long Position = (long)ThreadState.X0; long Position = (long)ThreadState.X0;
int Handle = (int)ThreadState.X1; int Handle = (int)ThreadState.X1;
KThread Thread = Process.HandleTable.GetData<KThread>(Handle); KThread Thread = Process.HandleTable.GetObject<KThread>(Handle);
if (Thread == null) if (Thread == null)
{ {

View file

@ -1,5 +1,6 @@
using ChocolArm64.State; using ChocolArm64.State;
using Ryujinx.HLE.Logging; using Ryujinx.HLE.Logging;
using System.Collections.Generic;
using static Ryujinx.HLE.HOS.ErrorCode; using static Ryujinx.HLE.HOS.ErrorCode;
@ -25,22 +26,27 @@ namespace Ryujinx.HLE.HOS.Kernel
return; return;
} }
KSynchronizationObject[] SyncObjs = new KSynchronizationObject[HandlesCount]; List<KSynchronizationObject> SyncObjs = new List<KSynchronizationObject>();
for (int Index = 0; Index < HandlesCount; Index++) for (int Index = 0; Index < HandlesCount; Index++)
{ {
int Handle = Memory.ReadInt32(HandlesPtr + Index * 4); 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; int HndIndex = (int)ThreadState.X1;
ulong High = ThreadState.X1 & (0xffffffffUL << 32); 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) if (Result != 0)
{ {
@ -65,7 +71,7 @@ namespace Ryujinx.HLE.HOS.Kernel
Device.Log.PrintDebug(LogClass.KernelSvc, "ThreadHandle = 0x" + ThreadHandle.ToString("x8")); 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) if (Thread == null)
{ {

View file

@ -71,7 +71,22 @@ namespace Ryujinx.HLE.HOS
TlsPages = new List<KTlsPageManager>(); 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); AppletState = new AppletStateMgr(Device.System);
@ -139,7 +154,7 @@ namespace Ryujinx.HLE.HOS
return false; return false;
} }
KThread MainThread = HandleTable.GetData<KThread>(Handle); KThread MainThread = HandleTable.GetKThread(Handle);
if (NeedsHbAbi) if (NeedsHbAbi)
{ {
@ -190,7 +205,7 @@ namespace Ryujinx.HLE.HOS
Thread.LastPc = EntryPoint; Thread.LastPc = EntryPoint;
int Handle = HandleTable.OpenHandle(Thread); HandleTable.GenerateHandle(Thread, out int Handle);
CpuThread.ThreadState.CntfrqEl0 = TickFreq; CpuThread.ThreadState.CntfrqEl0 = TickFreq;
CpuThread.ThreadState.Tpidr = Tpidr; CpuThread.ThreadState.Tpidr = Tpidr;
@ -427,13 +442,7 @@ namespace Ryujinx.HLE.HOS
Disposed = true; Disposed = true;
foreach (object Obj in HandleTable.Clear()) HandleTable.Destroy();
{
if (Obj is KSession Session)
{
Session.Dispose();
}
}
INvDrvServices.UnloadProcess(this); INvDrvServices.UnloadProcess(this);

View file

@ -1,6 +1,7 @@
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.Logging; using Ryujinx.HLE.Logging;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using static Ryujinx.HLE.HOS.ErrorCode; using static Ryujinx.HLE.HOS.ErrorCode;
@ -36,7 +37,10 @@ namespace Ryujinx.HLE.HOS.Services.Am
{ {
KEvent Event = Context.Process.AppletState.MessageEvent; 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
@ -103,7 +107,10 @@ namespace Ryujinx.HLE.HOS.Services.Am
public long GetDefaultDisplayResolutionChangeEvent(ServiceCtx Context) 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);

View file

@ -1,6 +1,7 @@
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.Logging; using Ryujinx.HLE.Logging;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Am namespace Ryujinx.HLE.HOS.Services.Am
@ -34,7 +35,10 @@ namespace Ryujinx.HLE.HOS.Services.Am
public long GetPopFromGeneralChannelEvent(ServiceCtx Context) 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);

View file

@ -1,6 +1,7 @@
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.Logging; using Ryujinx.HLE.Logging;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Am namespace Ryujinx.HLE.HOS.Services.Am
@ -29,9 +30,12 @@ namespace Ryujinx.HLE.HOS.Services.Am
public long GetAppletStateChangedEvent(ServiceCtx Context) 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);

View file

@ -1,6 +1,7 @@
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.Logging; using Ryujinx.HLE.Logging;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Am namespace Ryujinx.HLE.HOS.Services.Am
@ -57,9 +58,12 @@ namespace Ryujinx.HLE.HOS.Services.Am
public long GetLibraryAppletLaunchableEvent(ServiceCtx Context) 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);

View file

@ -67,7 +67,10 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioOut
public long RegisterBufferEvent(ServiceCtx Context) 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);

View file

@ -72,7 +72,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
private void AudioCallback() private void AudioCallback()
{ {
UpdateEvent.Signal(); UpdateEvent.ReadableEvent.Signal();
} }
private static T[] CreateArray<T>(int Size) where T : new() 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) 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);

View file

@ -2,6 +2,7 @@ using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.HLE.Logging; using Ryujinx.HLE.Logging;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
@ -35,7 +36,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud
SystemEvent = new KEvent(System); SystemEvent = new KEvent(System);
//TODO: We shouldn't be signaling this here. //TODO: We shouldn't be signaling this here.
SystemEvent.Signal(); SystemEvent.ReadableEvent.Signal();
} }
public long ListAudioDeviceName(ServiceCtx Context) public long ListAudioDeviceName(ServiceCtx Context)
@ -107,7 +108,10 @@ namespace Ryujinx.HLE.HOS.Services.Aud
public long QueryAudioDeviceSystemEvent(ServiceCtx Context) 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
@ -200,7 +204,10 @@ namespace Ryujinx.HLE.HOS.Services.Aud
public long QueryAudioDeviceInputEvent(ServiceCtx Context) 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
@ -211,7 +218,10 @@ namespace Ryujinx.HLE.HOS.Services.Aud
public long QueryAudioDeviceOutputEvent(ServiceCtx Context) 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);

View file

@ -150,7 +150,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud
ReleaseCallback Callback = () => ReleaseCallback Callback = () =>
{ {
ReleaseEvent.Signal(); ReleaseEvent.ReadableEvent.Signal();
}; };
IAalOutput AudioOut = Context.Device.AudioOut; IAalOutput AudioOut = Context.Device.AudioOut;

View file

@ -1,5 +1,6 @@
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Hid namespace Ryujinx.HLE.HOS.Services.Hid
@ -24,7 +25,10 @@ namespace Ryujinx.HLE.HOS.Services.Hid
public long GetSharedMemoryHandle(ServiceCtx Context) 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);

View file

@ -2,7 +2,6 @@ using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.Input; using Ryujinx.HLE.Input;
using Ryujinx.HLE.Logging; using Ryujinx.HLE.Logging;
using Ryujinx.HLE.Utilities;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -219,7 +218,10 @@ namespace Ryujinx.HLE.HOS.Services.Hid
{ {
long XpadId = Context.RequestData.ReadInt64(); 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(XpadIdEventHandle);
@ -712,7 +714,10 @@ namespace Ryujinx.HLE.HOS.Services.Hid
int NpadId = Context.RequestData.ReadInt32(); int NpadId = Context.RequestData.ReadInt32();
long NpadStyleSet = Context.RequestData.ReadInt64(); 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
@ -1351,7 +1356,10 @@ namespace Ryujinx.HLE.HOS.Services.Hid
{ {
int PalmaConnectionHandle = Context.RequestData.ReadInt32(); 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);

View file

@ -132,7 +132,10 @@ namespace Ryujinx.HLE.HOS.Services
{ {
KSession Session = new KSession(Obj, Context.Session.ServiceName); 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); Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
} }
@ -146,7 +149,7 @@ namespace Ryujinx.HLE.HOS.Services
{ {
int Handle = Context.Request.HandleDesc.ToMove[Index]; 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; return Session?.Service is T ? (T)Session.Service : null;
} }

View file

@ -2,6 +2,7 @@
using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.Input; using Ryujinx.HLE.Input;
using Ryujinx.HLE.Logging; using Ryujinx.HLE.Logging;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Nfp namespace Ryujinx.HLE.HOS.Services.Nfp
@ -55,7 +56,10 @@ namespace Ryujinx.HLE.HOS.Services.Nfp
{ {
Context.Device.Log.PrintStub(LogClass.ServiceNfp, "Stubbed."); 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);; Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);;
@ -66,7 +70,10 @@ namespace Ryujinx.HLE.HOS.Services.Nfp
{ {
Context.Device.Log.PrintStub(LogClass.ServiceNfp, "Stubbed."); 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
@ -104,7 +111,10 @@ namespace Ryujinx.HLE.HOS.Services.Nfp
{ {
Context.Device.Log.PrintStub(LogClass.ServiceNfp, "Stubbed."); 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);

View file

@ -1,6 +1,7 @@
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.Logging; using Ryujinx.HLE.Logging;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Nifm namespace Ryujinx.HLE.HOS.Services.Nifm
@ -48,8 +49,15 @@ namespace Ryujinx.HLE.HOS.Services.Nifm
public long GetSystemEventReadableHandles(ServiceCtx Context) public long GetSystemEventReadableHandles(ServiceCtx Context)
{ {
int Handle0 = Context.Process.HandleTable.OpenHandle(Event0); if (Context.Process.HandleTable.GenerateHandle(Event0.ReadableEvent, out int Handle0) != KernelResult.Success)
int Handle1 = Context.Process.HandleTable.OpenHandle(Event1); {
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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle0, Handle1);

View file

@ -123,7 +123,10 @@ namespace Ryujinx.HLE.HOS.Services.Nv
int EventId = Context.RequestData.ReadInt32(); int EventId = Context.RequestData.ReadInt32();
//TODO: Use Fd/EventId, different channels have different events. //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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);

View file

@ -1,5 +1,7 @@
using Ryujinx.HLE.HOS.Font; using Ryujinx.HLE.HOS.Font;
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Pl namespace Ryujinx.HLE.HOS.Services.Pl
@ -65,7 +67,10 @@ namespace Ryujinx.HLE.HOS.Services.Pl
{ {
Context.Device.System.Font.EnsureInitialized(); 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);

View file

@ -1,5 +1,6 @@
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Sm 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); 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); Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);

View file

@ -1,6 +1,8 @@
using ChocolArm64.Memory; using ChocolArm64.Memory;
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel;
using System.Collections.Generic; using System.Collections.Generic;
using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
@ -178,7 +180,10 @@ namespace Ryujinx.HLE.HOS.Services.Vi
{ {
string Name = GetDisplayName(Context); 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); Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);

View file

@ -29,7 +29,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
BinderEvent = new KEvent(System); BinderEvent = new KEvent(System);
BinderEvent.Signal(); BinderEvent.ReadableEvent.Signal();
Flinger = new NvFlinger(Renderer, BinderEvent); Flinger = new NvFlinger(Renderer, BinderEvent);
} }
@ -77,7 +77,10 @@ namespace Ryujinx.HLE.HOS.Services.Vi
int Id = Context.RequestData.ReadInt32(); int Id = Context.RequestData.ReadInt32();
uint Unk = Context.RequestData.ReadUInt32(); 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); Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);

View file

@ -338,7 +338,7 @@ namespace Ryujinx.HLE.HOS.Services.Android
{ {
BufferQueue[Slot].State = BufferState.Free; BufferQueue[Slot].State = BufferState.Free;
BinderEvent.Signal(); BinderEvent.ReadableEvent.Signal();
WaitBufferFree.Set(); WaitBufferFree.Set();
} }

View file

@ -32,14 +32,14 @@ namespace Ryujinx.HLE.HOS.SystemState
{ {
Messages.Enqueue(Message); Messages.Enqueue(Message);
MessageEvent.Signal(); MessageEvent.ReadableEvent.Signal();
} }
public bool TryDequeueMessage(out MessageInfo Message) public bool TryDequeueMessage(out MessageInfo Message)
{ {
if (Messages.Count < 2) if (Messages.Count < 2)
{ {
MessageEvent.Reset(); MessageEvent.ReadableEvent.Clear();
} }
return Messages.TryDequeue(out Message); return Messages.TryDequeue(out Message);