aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-04-18 23:52:23 -0300
committergdkchan <gab.dark.100@gmail.com>2018-04-18 23:52:36 -0300
commitb9af34f3dd1e7f5e38b038f182c9fd4a791fdfea (patch)
treee86e7941f5d2871ed2d9bd702b38997c86fb2af8
parente9a96e3522ee7620b525d210915a0e45510ea528 (diff)
[HLE/Kernel] Somewhat improved sync primitives
-rw-r--r--Ryujinx.Core/OsHle/AppletStateMgr.cs6
-rw-r--r--Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs154
-rw-r--r--Ryujinx.Core/OsHle/Handles/KSynchronizationObject.cs6
-rw-r--r--Ryujinx.Core/OsHle/Handles/KThread.cs6
-rw-r--r--Ryujinx.Core/OsHle/Horizon.cs15
-rw-r--r--Ryujinx.Core/OsHle/Kernel/ConditionVariable.cs (renamed from Ryujinx.Core/OsHle/CondVar.cs)81
-rw-r--r--Ryujinx.Core/OsHle/Kernel/KernelErr.cs (renamed from Ryujinx.Core/OsHle/KernelErr.cs)2
-rw-r--r--Ryujinx.Core/OsHle/Kernel/MutualExclusion.cs91
-rw-r--r--Ryujinx.Core/OsHle/Kernel/SvcHandler.cs (renamed from Ryujinx.Core/OsHle/Svc/SvcHandler.cs)9
-rw-r--r--Ryujinx.Core/OsHle/Kernel/SvcMemory.cs (renamed from Ryujinx.Core/OsHle/Svc/SvcMemory.cs)8
-rw-r--r--Ryujinx.Core/OsHle/Kernel/SvcSystem.cs (renamed from Ryujinx.Core/OsHle/Svc/SvcSystem.cs)6
-rw-r--r--Ryujinx.Core/OsHle/Kernel/SvcThread.cs (renamed from Ryujinx.Core/OsHle/Svc/SvcThread.cs)88
-rw-r--r--Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs120
-rw-r--r--Ryujinx.Core/OsHle/Mutex.cs122
-rw-r--r--Ryujinx.Core/OsHle/Process.cs39
-rw-r--r--Ryujinx.Core/OsHle/Services/Aud/IAudioOutManager.cs2
-rw-r--r--Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs2
-rw-r--r--Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs2
-rw-r--r--Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs85
-rw-r--r--Ryujinx/Ui/GLScreen.cs1
20 files changed, 405 insertions, 440 deletions
diff --git a/Ryujinx.Core/OsHle/AppletStateMgr.cs b/Ryujinx.Core/OsHle/AppletStateMgr.cs
index 25f56c63..2199f43e 100644
--- a/Ryujinx.Core/OsHle/AppletStateMgr.cs
+++ b/Ryujinx.Core/OsHle/AppletStateMgr.cs
@@ -22,7 +22,7 @@ namespace Ryujinx.Core.OsHle
public void SetFocus(bool IsFocused)
{
- FocusState = IsFocused
+ FocusState = IsFocused
? FocusState.InFocus
: FocusState.OutOfFocus;
@@ -33,14 +33,14 @@ namespace Ryujinx.Core.OsHle
{
Messages.Enqueue(Message);
- MessageEvent.Handle.Set();
+ MessageEvent.WaitEvent.Set();
}
public bool TryDequeueMessage(out MessageInfo Message)
{
if (Messages.Count < 2)
{
- MessageEvent.Handle.Reset();
+ MessageEvent.WaitEvent.Reset();
}
return Messages.TryDequeue(out Message);
diff --git a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
index 7ba78b3f..238febd0 100644
--- a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
+++ b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
@@ -7,6 +7,8 @@ namespace Ryujinx.Core.OsHle.Handles
{
class KProcessScheduler : IDisposable
{
+ private const int LowestPriority = 0x40;
+
private class SchedulerThread : IDisposable
{
public KThread Thread { get; private set; }
@@ -51,7 +53,7 @@ namespace Ryujinx.Core.OsHle.Handles
}
}
- public SchedulerThread Pop(int MinPriority = 0x40)
+ public SchedulerThread Pop(int MinPriority = LowestPriority)
{
lock (Threads)
{
@@ -130,68 +132,47 @@ namespace Ryujinx.Core.OsHle.Handles
return;
}
- if (!ActiveProcessors.Contains(Thread.ProcessorId))
+ if (ActiveProcessors.Add(Thread.ProcessorId))
{
- ActiveProcessors.Add(Thread.ProcessorId);
-
Thread.Thread.Execute();
- Logging.Debug(LogClass.KernelScheduler, $"{GetDbgThreadInfo(Thread)} running.");
+ PrintDbgThreadInfo(Thread, "running.");
}
else
{
WaitingToRun[Thread.ProcessorId].Push(SchedThread);
- Logging.Debug(LogClass.KernelScheduler, $"{GetDbgThreadInfo(SchedThread.Thread)} waiting to run.");
+ PrintDbgThreadInfo(Thread, "waiting to run.");
}
}
}
- public void Suspend(int ProcessorId)
+ public void RemoveThread(KThread Thread)
{
+ PrintDbgThreadInfo(Thread, "exited.");
+
lock (SchedLock)
{
- SchedulerThread SchedThread = WaitingToRun[ProcessorId].Pop();
+ SchedulerThread NewThread = WaitingToRun[Thread.ProcessorId].Pop();
- if (SchedThread != null)
- {
- RunThread(SchedThread);
- }
- else
+ if (NewThread == null)
{
- ActiveProcessors.Remove(ProcessorId);
- }
- }
- }
+ Logging.Debug(LogClass.KernelScheduler, $"Nothing to run on core {Thread.ProcessorId}!");
- public void Resume(KThread CurrThread)
- {
- SchedulerThread SchedThread;
-
- Logging.Debug(LogClass.KernelScheduler, $"{GetDbgThreadInfo(CurrThread)} entering ipc delay wait state.");
-
- lock (SchedLock)
- {
- if (!AllThreads.TryGetValue(CurrThread, out SchedThread))
- {
- Logging.Error(LogClass.KernelScheduler, $"{GetDbgThreadInfo(CurrThread)} was not found on the scheduler queue!");
+ ActiveProcessors.Remove(Thread.ProcessorId);
return;
}
- }
- TryResumingExecution(SchedThread);
+ RunThread(NewThread);
+ }
}
- public bool WaitForSignal(KThread Thread, int Timeout = -1)
+ public void Suspend(int ProcessorId)
{
- SchedulerThread SchedThread;
-
- Logging.Debug(LogClass.KernelScheduler, $"{GetDbgThreadInfo(Thread)} entering signal wait state.");
-
lock (SchedLock)
{
- SchedThread = WaitingToRun[Thread.ProcessorId].Pop();
+ SchedulerThread SchedThread = WaitingToRun[ProcessorId].Pop();
if (SchedThread != null)
{
@@ -199,88 +180,67 @@ namespace Ryujinx.Core.OsHle.Handles
}
else
{
- ActiveProcessors.Remove(Thread.ProcessorId);
- }
-
- if (!AllThreads.TryGetValue(Thread, out SchedThread))
- {
- Logging.Error(LogClass.KernelScheduler, $"{GetDbgThreadInfo(Thread)} was not found on the scheduler queue!");
+ Logging.Debug(LogClass.KernelScheduler, $"Nothing to run on core {ProcessorId}!");
- return false;
+ ActiveProcessors.Remove(ProcessorId);
}
}
-
- bool Result;
-
- if (Timeout >= 0)
- {
- Logging.Debug(LogClass.KernelScheduler, $"{GetDbgThreadInfo(Thread)} has wait timeout of {Timeout}ms.");
-
- Result = SchedThread.WaitEvent.WaitOne(Timeout);
- }
- else
- {
- Result = SchedThread.WaitEvent.WaitOne();
- }
-
- TryResumingExecution(SchedThread);
-
- return Result;
}
- private void TryResumingExecution(SchedulerThread SchedThread)
+ public void Yield(KThread Thread)
{
- KThread Thread = SchedThread.Thread;
+ PrintDbgThreadInfo(Thread, "yielded execution.");
lock (SchedLock)
{
- if (ActiveProcessors.Add(Thread.ProcessorId))
+ SchedulerThread SchedThread = WaitingToRun[Thread.ProcessorId].Pop(Thread.Priority);
+
+ if (SchedThread == null)
{
- Logging.Debug(LogClass.KernelScheduler, $"{GetDbgThreadInfo(Thread)} resuming execution...");
+ PrintDbgThreadInfo(Thread, "resumed because theres nothing better to run.");
return;
}
- WaitingToRun[Thread.ProcessorId].Push(SchedThread);
+ RunThread(SchedThread);
}
- SchedThread.WaitEvent.WaitOne();
-
- Logging.Debug(LogClass.KernelScheduler, $"{GetDbgThreadInfo(Thread)} resuming execution...");
+ Resume(Thread);
}
- public void Yield(KThread Thread)
+ public void Resume(KThread Thread)
{
SchedulerThread SchedThread;
- Logging.Debug(LogClass.KernelScheduler, $"{GetDbgThreadInfo(Thread)} yielded execution.");
-
- lock (SchedLock)
+ if (!AllThreads.TryGetValue(Thread, out SchedThread))
{
- SchedThread = WaitingToRun[Thread.ProcessorId].Pop(Thread.Priority);
+ throw new InvalidOperationException();
+ }
- if (SchedThread == null)
- {
- Logging.Debug(LogClass.KernelScheduler, $"{GetDbgThreadInfo(Thread)} resumed because theres nothing better to run.");
+ TryResumingExecution(SchedThread);
+ }
- return;
- }
-
- RunThread(SchedThread);
+ private void TryResumingExecution(SchedulerThread SchedThread)
+ {
+ KThread Thread = SchedThread.Thread;
- if (!AllThreads.TryGetValue(Thread, out SchedThread))
+ lock (SchedLock)
+ {
+ if (ActiveProcessors.Add(Thread.ProcessorId))
{
- Logging.Error(LogClass.KernelScheduler, $"{GetDbgThreadInfo(Thread)} was not found on the scheduler queue!");
+ PrintDbgThreadInfo(Thread, "resuming execution...");
return;
}
+ PrintDbgThreadInfo(Thread, "entering wait state...");
+
WaitingToRun[Thread.ProcessorId].Push(SchedThread);
}
SchedThread.WaitEvent.WaitOne();
- Logging.Debug(LogClass.KernelScheduler, $"{GetDbgThreadInfo(Thread)} resuming execution...");
+ PrintDbgThreadInfo(Thread, "resuming execution...");
}
private void RunThread(SchedulerThread SchedThread)
@@ -291,32 +251,16 @@ namespace Ryujinx.Core.OsHle.Handles
}
else
{
- Logging.Debug(LogClass.KernelScheduler, $"{GetDbgThreadInfo(SchedThread.Thread)} running.");
- }
- }
-
- public void Signal(params KThread[] Threads)
- {
- lock (SchedLock)
- {
- foreach (KThread Thread in Threads)
- {
- if (AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
- {
- if (!WaitingToRun[Thread.ProcessorId].HasThread(SchedThread))
- {
- Logging.Debug(LogClass.KernelScheduler, $"{GetDbgThreadInfo(Thread)} signaled.");
-
- SchedThread.WaitEvent.Set();
- }
- }
- }
+ PrintDbgThreadInfo(SchedThread.Thread, "running.");
}
}
- private string GetDbgThreadInfo(KThread Thread)
+ private void PrintDbgThreadInfo(KThread Thread, string Message)
{
- return $"Thread {Thread.ThreadId} (core {Thread.ProcessorId}) prio {Thread.Priority}";
+ Logging.Debug(LogClass.KernelScheduler, "(" +
+ "ThreadId: " + Thread.ThreadId + ", " +
+ "ProcessorId: " + Thread.ProcessorId + ", " +
+ "Priority: " + Thread.Priority + ") " + Message);
}
public void Dispose()
diff --git a/Ryujinx.Core/OsHle/Handles/KSynchronizationObject.cs b/Ryujinx.Core/OsHle/Handles/KSynchronizationObject.cs
index 015b814a..3f78b965 100644
--- a/Ryujinx.Core/OsHle/Handles/KSynchronizationObject.cs
+++ b/Ryujinx.Core/OsHle/Handles/KSynchronizationObject.cs
@@ -5,11 +5,11 @@ namespace Ryujinx.Core.OsHle.Handles
{
class KSynchronizationObject : IDisposable
{
- public ManualResetEvent Handle { get; private set; }
+ public ManualResetEvent WaitEvent { get; private set; }
public KSynchronizationObject()
{
- Handle = new ManualResetEvent(false);
+ WaitEvent = new ManualResetEvent(false);
}
public void Dispose()
@@ -21,7 +21,7 @@ namespace Ryujinx.Core.OsHle.Handles
{
if (Disposing)
{
- Handle.Dispose();
+ WaitEvent.Dispose();
}
}
}
diff --git a/Ryujinx.Core/OsHle/Handles/KThread.cs b/Ryujinx.Core/OsHle/Handles/KThread.cs
index aa1b27be..9742f492 100644
--- a/Ryujinx.Core/OsHle/Handles/KThread.cs
+++ b/Ryujinx.Core/OsHle/Handles/KThread.cs
@@ -6,8 +6,10 @@ namespace Ryujinx.Core.OsHle.Handles
{
public AThread Thread { get; private set; }
- public int ProcessorId { get; private set; }
- public int Priority { get; set; }
+ public int ProcessorId { get; private set; }
+
+ public int Priority { get; set; }
+ public int Handle { get; set; }
public int ThreadId => Thread.ThreadId;
diff --git a/Ryujinx.Core/OsHle/Horizon.cs b/Ryujinx.Core/OsHle/Horizon.cs
index 049b03b2..6442025f 100644
--- a/Ryujinx.Core/OsHle/Horizon.cs
+++ b/Ryujinx.Core/OsHle/Horizon.cs
@@ -11,8 +11,7 @@ namespace Ryujinx.Core.OsHle
internal const int HidSize = 0x40000;
internal const int FontSize = 0x50;
- internal ConcurrentDictionary<long, Mutex> Mutexes { get; private set; }
- internal ConcurrentDictionary<long, CondVar> CondVars { get; private set; }
+ private KProcessScheduler Scheduler;
private ConcurrentDictionary<int, Process> Processes;
@@ -27,8 +26,7 @@ namespace Ryujinx.Core.OsHle
{
this.Ns = Ns;
- Mutexes = new ConcurrentDictionary<long, Mutex>();
- CondVars = new ConcurrentDictionary<long, CondVar>();
+ Scheduler = new KProcessScheduler();
Processes = new ConcurrentDictionary<int, Process>();
@@ -95,7 +93,7 @@ namespace Ryujinx.Core.OsHle
MainProcess.Run(IsNro);
}
- public void SignalVsync() => VsyncEvent.Handle.Set();
+ public void SignalVsync() => VsyncEvent.WaitEvent.Set();
private Process MakeProcess()
{
@@ -110,7 +108,7 @@ namespace Ryujinx.Core.OsHle
ProcessId++;
}
- Process = new Process(Ns, ProcessId);
+ Process = new Process(Ns, Scheduler, ProcessId);
Processes.TryAdd(ProcessId, Process);
}
@@ -144,11 +142,6 @@ namespace Ryujinx.Core.OsHle
if (File.Exists(NextNro))
{
- //TODO: Those dictionaries shouldn't even exist,
- //the Mutex and CondVar helper classes should be static.
- Mutexes.Clear();
- CondVars.Clear();
-
LoadProgram(NextNro);
}
}
diff --git a/Ryujinx.Core/OsHle/CondVar.cs b/Ryujinx.Core/OsHle/Kernel/ConditionVariable.cs
index f1b846d0..34d5820b 100644
--- a/Ryujinx.Core/OsHle/CondVar.cs
+++ b/Ryujinx.Core/OsHle/Kernel/ConditionVariable.cs
@@ -2,53 +2,58 @@ using Ryujinx.Core.OsHle.Handles;
using System.Collections.Generic;
using System.Threading;
-namespace Ryujinx.Core.OsHle
+namespace Ryujinx.Core.OsHle.Kernel
{
- class CondVar
+ class ConditionVariable
{
private Process Process;
private long CondVarAddress;
- private long Timeout;
private bool OwnsCondVarValue;
- private List<KThread> WaitingThreads;
+ private List<(KThread Thread, AutoResetEvent WaitEvent)> WaitingThreads;
- public CondVar(Process Process, long CondVarAddress, long Timeout)
+ public ConditionVariable(Process Process, long CondVarAddress)
{
this.Process = Process;
this.CondVarAddress = CondVarAddress;
- this.Timeout = Timeout;
- WaitingThreads = new List<KThread>();
+ WaitingThreads = new List<(KThread, AutoResetEvent)>();
}
- public bool WaitForSignal(KThread Thread)
+ public bool WaitForSignal(KThread Thread, long Timeout)
{
+ bool Result = true;
+
int Count = Process.Memory.ReadInt32(CondVarAddress);
if (Count <= 0)
{
- lock (WaitingThreads)
+ using (AutoResetEvent WaitEvent = new AutoResetEvent(false))
{
- WaitingThreads.Add(Thread);
- }
+ lock (WaitingThreads)
+ {
+ WaitingThreads.Add((Thread, WaitEvent));
+ }
- if (Timeout == -1)
- {
- Process.Scheduler.WaitForSignal(Thread);
- }
- else
- {
- bool Result = Process.Scheduler.WaitForSignal(Thread, (int)(Timeout / 1000000));
+ Process.Scheduler.Suspend(Thread.ProcessorId);
- lock (WaitingThreads)
+ if (Timeout < 0)
{
- WaitingThreads.Remove(Thread);
+ Result = WaitEvent.WaitOne();
+ }
+ else
+ {
+ Result = WaitEvent.WaitOne((int)(Timeout / 1000000));
+
+ lock (WaitingThreads)
+ {
+ WaitingThreads.Remove((Thread, WaitEvent));
+ }
}
- return Result;
+ Process.Scheduler.Resume(Thread);
}
}
@@ -63,57 +68,49 @@ namespace Ryujinx.Core.OsHle
ReleaseCondVarValue();
- return true;
+ return Result;
}
public void SetSignal(KThread Thread, int Count)
{
lock (WaitingThreads)
{
- if (Count == -1)
+ if (Count < 0)
{
- Process.Scheduler.Signal(WaitingThreads.ToArray());
-
- AcquireCondVarValue();
-
Process.Memory.WriteInt32(CondVarAddress, WaitingThreads.Count);
- ReleaseCondVarValue();
+ foreach ((_, AutoResetEvent WaitEvent) in WaitingThreads)
+ {
+ WaitEvent.Set();
+ }
WaitingThreads.Clear();
}
else
{
- if (WaitingThreads.Count > 0)
+ Process.Memory.WriteInt32(CondVarAddress, Count);
+
+ while (WaitingThreads.Count > 0 && Count-- > 0)
{
- int HighestPriority = WaitingThreads[0].Priority;
+ int HighestPriority = WaitingThreads[0].Thread.Priority;
int HighestPrioIndex = 0;
for (int Index = 1; Index < WaitingThreads.Count; Index++)
{
- if (HighestPriority > WaitingThreads[Index].Priority)
+ if (HighestPriority > WaitingThreads[Index].Thread.Priority)
{
- HighestPriority = WaitingThreads[Index].Priority;
+ HighestPriority = WaitingThreads[Index].Thread.Priority;
HighestPrioIndex = Index;
}
}
- Process.Scheduler.Signal(WaitingThreads[HighestPrioIndex]);
+ WaitingThreads[HighestPrioIndex].WaitEvent.Set();
WaitingThreads.RemoveAt(HighestPrioIndex);
}
-
- AcquireCondVarValue();
-
- Process.Memory.WriteInt32(CondVarAddress, Count);
-
- ReleaseCondVarValue();
}
}
-
- Process.Scheduler.Suspend(Thread.ProcessorId);
- Process.Scheduler.Resume(Thread);
}
private void AcquireCondVarValue()
diff --git a/Ryujinx.Core/OsHle/KernelErr.cs b/Ryujinx.Core/OsHle/Kernel/KernelErr.cs
index e476f631..e7cd72dc 100644
--- a/Ryujinx.Core/OsHle/KernelErr.cs
+++ b/Ryujinx.Core/OsHle/Kernel/KernelErr.cs
@@ -1,4 +1,4 @@
-namespace Ryujinx.Core.OsHle
+namespace Ryujinx.Core.OsHle.Kernel
{
static class KernelErr
{
diff --git a/Ryujinx.Core/OsHle/Kernel/MutualExclusion.cs b/Ryujinx.Core/OsHle/Kernel/MutualExclusion.cs
new file mode 100644
index 00000000..aeaaf70f
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Kernel/MutualExclusion.cs
@@ -0,0 +1,91 @@
+using Ryujinx.Core.OsHle.Handles;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Ryujinx.Core.OsHle.Kernel
+{
+ class MutualExclusion
+ {
+ private const int MutexHasListenersMask = 0x40000000;
+
+ private Process Process;
+
+ private long MutexAddress;
+
+ private List<(KThread Thread, AutoResetEvent WaitEvent)> WaitingThreads;
+
+ public MutualExclusion(Process Process, long MutexAddress)
+ {
+ this.Process = Process;
+ this.MutexAddress = MutexAddress;
+
+ WaitingThreads = new List<(KThread, AutoResetEvent)>();
+ }
+
+ public void WaitForLock(KThread RequestingThread)
+ {
+ int OwnerThreadHandle = Process.Memory.ReadInt32(MutexAddress) & ~MutexHasListenersMask;
+
+ WaitForLock(RequestingThread, OwnerThreadHandle);
+ }
+
+ public void WaitForLock(KThread RequestingThread, int OwnerThreadHandle)
+ {
+ if (OwnerThreadHandle == RequestingThread.Handle ||
+ OwnerThreadHandle == 0)
+ {
+ return;
+ }
+
+ using (AutoResetEvent WaitEvent = new AutoResetEvent(false))
+ {
+ lock (WaitingThreads)
+ {
+ WaitingThreads.Add((RequestingThread, WaitEvent));
+ }
+
+ Process.Scheduler.Suspend(RequestingThread.ProcessorId);
+
+ WaitEvent.WaitOne();
+
+ Process.Scheduler.Resume(RequestingThread);
+ }
+ }
+
+ public void Unlock()
+ {
+ lock (WaitingThreads)
+ {
+ int HasListeners = WaitingThreads.Count > 1 ? MutexHasListenersMask : 0;
+
+ if (WaitingThreads.Count > 0)
+ {
+ int HighestPriority = WaitingThreads[0].Thread.Priority;
+ int HighestPrioIndex = 0;
+
+ for (int Index = 1; Index < WaitingThreads.Count; Index++)
+ {
+ if (HighestPriority > WaitingThreads[Index].Thread.Priority)
+ {
+ HighestPriority = WaitingThreads[Index].Thread.Priority;
+
+ HighestPrioIndex = Index;
+ }
+ }
+
+ int Handle = WaitingThreads[HighestPrioIndex].Thread.Handle;
+
+ WaitingThreads[HighestPrioIndex].WaitEvent.Set();
+
+ WaitingThreads.RemoveAt(HighestPrioIndex);
+
+ Process.Memory.WriteInt32(MutexAddress, HasListeners | Handle);
+ }
+ else
+ {
+ Process.Memory.WriteInt32(MutexAddress, 0);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Svc/SvcHandler.cs b/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs
index 9fea59a8..4d93ef29 100644
--- a/Ryujinx.Core/OsHle/Svc/SvcHandler.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcHandler.cs
@@ -3,9 +3,10 @@ using ChocolArm64.Memory;
using ChocolArm64.State;
using Ryujinx.Core.OsHle.Handles;
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
-namespace Ryujinx.Core.OsHle.Svc
+namespace Ryujinx.Core.OsHle.Kernel
{
partial class SvcHandler : IDisposable
{
@@ -17,6 +18,9 @@ namespace Ryujinx.Core.OsHle.Svc
private Process Process;
private AMemory Memory;
+ private ConcurrentDictionary<long, MutualExclusion> Mutexes;
+ private ConcurrentDictionary<long, ConditionVariable> CondVars;
+
private HashSet<(HSharedMem, long)> MappedSharedMems;
private ulong CurrentHeapSize;
@@ -66,6 +70,9 @@ namespace Ryujinx.Core.OsHle.Svc
this.Process = Process;
this.Memory = Process.Memory;
+ Mutexes = new ConcurrentDictionary<long, MutualExclusion>();
+ CondVars = new ConcurrentDictionary<long, ConditionVariable>();
+
MappedSharedMems = new HashSet<(HSharedMem, long)>();
}
diff --git a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs b/Ryujinx.Core/OsHle/Kernel/SvcMemory.cs
index 73485715..c8aedcff 100644
--- a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcMemory.cs
@@ -4,7 +4,7 @@ using Ryujinx.Core.OsHle.Handles;
using static Ryujinx.Core.OsHle.ErrorCode;
-namespace Ryujinx.Core.OsHle.Svc
+namespace Ryujinx.Core.OsHle.Kernel
{
partial class SvcHandler
{
@@ -244,7 +244,7 @@ namespace Ryujinx.Core.OsHle.Svc
HTransferMem TMem = new HTransferMem(Memory, MapInfo.Perm, Src, Size);
ulong Handle = (ulong)Process.HandleTable.OpenHandle(TMem);
-
+
ThreadState.X0 = 0;
ThreadState.X1 = Handle;
}
@@ -252,13 +252,13 @@ namespace Ryujinx.Core.OsHle.Svc
private static bool IsValidPosition(long Position)
{
return Position >= MemoryRegions.AddrSpaceStart &&
- Position < MemoryRegions.AddrSpaceStart + MemoryRegions.AddrSpaceSize;
+ Position < MemoryRegions.AddrSpaceStart + MemoryRegions.AddrSpaceSize;
}
private static bool IsValidMapPosition(long Position)
{
return Position >= MemoryRegions.MapRegionAddress &&
- Position < MemoryRegions.MapRegionAddress + MemoryRegions.MapRegionSize;
+ Position < MemoryRegions.MapRegionAddress + MemoryRegions.MapRegionSize;
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs
index e615b429..ebbbef4a 100644
--- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs
@@ -9,7 +9,7 @@ using System.Threading;
using static Ryujinx.Core.OsHle.ErrorCode;
-namespace Ryujinx.Core.OsHle.Svc
+namespace Ryujinx.Core.OsHle.Kernel
{
partial class SvcHandler
{
@@ -69,7 +69,7 @@ namespace Ryujinx.Core.OsHle.Svc
if (Event != null)
{
- Event.Handle.Reset();
+ Event.WaitEvent.Reset();
ThreadState.X0 = 0;
}
@@ -106,7 +106,7 @@ namespace Ryujinx.Core.OsHle.Svc
return;
}
- Handles[Index] = SyncObj.Handle;
+ Handles[Index] = SyncObj.WaitEvent;
}
Process.Scheduler.Suspend(CurrThread.ProcessorId);
diff --git a/Ryujinx.Core/OsHle/Svc/SvcThread.cs b/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
index 4dc9e15c..7418732f 100644
--- a/Ryujinx.Core/OsHle/Svc/SvcThread.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcThread.cs
@@ -1,9 +1,10 @@
using ChocolArm64.State;
using Ryujinx.Core.OsHle.Handles;
+using System.Threading;
using static Ryujinx.Core.OsHle.ErrorCode;
-namespace Ryujinx.Core.OsHle.Svc
+namespace Ryujinx.Core.OsHle.Kernel
{
partial class SvcHandler
{
@@ -15,42 +16,43 @@ namespace Ryujinx.Core.OsHle.Svc
int Priority = (int)ThreadState.X4;
int ProcessorId = (int)ThreadState.X5;
- if (Ns.Os.TryGetProcess(ThreadState.ProcessId, out Process Process))
+ if (ProcessorId == -2)
{
- if (ProcessorId == -2)
- {
- //TODO: Get this value from the NPDM file.
- ProcessorId = 0;
- }
-
- int Handle = Process.MakeThread(
- EntryPoint,
- StackTop,
- ArgsPtr,
- Priority,
- ProcessorId);
-
- ThreadState.X0 = 0;
- ThreadState.X1 = (ulong)Handle;
+ //TODO: Get this value from the NPDM file.
+ ProcessorId = 0;
}
- //TODO: Error codes.
+ int Handle = Process.MakeThread(
+ EntryPoint,
+ StackTop,
+ ArgsPtr,
+ Priority,
+ ProcessorId);
+
+ ThreadState.X0 = 0;
+ ThreadState.X1 = (ulong)Handle;
}
private void SvcStartThread(AThreadState ThreadState)
{
int Handle = (int)ThreadState.X0;
- KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
+ KThread CurrThread = Process.HandleTable.GetData<KThread>(Handle);
- if (Thread != null)
+ if (CurrThread != null)
{
- Process.Scheduler.StartThread(Thread);
+ Process.Scheduler.StartThread(CurrThread);
+
+ Process.Scheduler.Yield(Process.GetThread(ThreadState.Tpidr));
ThreadState.X0 = 0;
}
+ else
+ {
+ Logging.Warn(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
- //TODO: Error codes.
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
+ }
}
private void SvcExitThread(AThreadState ThreadState)
@@ -58,8 +60,6 @@ namespace Ryujinx.Core.OsHle.Svc
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
CurrThread.Thread.StopExecution();
-
- CurrThread.Handle.Set();
}
private void SvcSleepThread(AThreadState ThreadState)
@@ -74,7 +74,11 @@ namespace Ryujinx.Core.OsHle.Svc
}
else
{
- Process.Scheduler.WaitForSignal(CurrThread, (int)(NanoSecs / 1000000));
+ Process.Scheduler.Suspend(CurrThread.ProcessorId);
+
+ Thread.Sleep((int)(NanoSecs / 1000000));
+
+ Process.Scheduler.Resume(CurrThread);
}
}
@@ -82,15 +86,19 @@ namespace Ryujinx.Core.OsHle.Svc
{
int Handle = (int)ThreadState.X1;
- KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
+ KThread CurrThread = Process.HandleTable.GetData<KThread>(Handle);
- if (Thread != null)
+ if (CurrThread != null)
{
ThreadState.X0 = 0;
- ThreadState.X1 = (ulong)Thread.Priority;
+ ThreadState.X1 = (ulong)CurrThread.Priority;
}
+ else
+ {
+ Logging.Warn(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
- //TODO: Error codes.
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
+ }
}
private void SvcSetThreadPriority(AThreadState ThreadState)
@@ -98,16 +106,20 @@ namespace Ryujinx.Core.OsHle.Svc
int Prio = (int)ThreadState.X0;
int Handle = (int)ThreadState.X1;
- KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
+ KThread CurrThread = Process.HandleTable.GetData<KThread>(Handle);
- if (Thread != null)
+ if (CurrThread != null)
{
- Thread.Priority = Prio;
+ CurrThread.Priority = Prio;
ThreadState.X0 = 0;
}
+ else
+ {
+ Logging.Warn(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
- //TODO: Error codes.
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
+ }
}
private void SvcSetThreadCoreMask(AThreadState ThreadState)
@@ -119,21 +131,19 @@ namespace Ryujinx.Core.OsHle.Svc
private void SvcGetCurrentProcessorNumber(AThreadState ThreadState)
{
- KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
-
- ThreadState.X0 = (ulong)CurrThread.ProcessorId;
+ ThreadState.X0 = (ulong)Process.GetThread(ThreadState.Tpidr).ProcessorId;
}
private void SvcGetThreadId(AThreadState ThreadState)
{
int Handle = (int)ThreadState.X1;
- KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
+ KThread CurrThread = Process.HandleTable.GetData<KThread>(Handle);
- if (Thread != null)
+ if (CurrThread != null)
{
ThreadState.X0 = 0;
- ThreadState.X1 = (ulong)Thread.ThreadId;
+ ThreadState.X1 = (ulong)CurrThread.ThreadId;
}
else
{
diff --git a/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs b/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs
new file mode 100644
index 00000000..e9d801b4
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Kernel/SvcThreadSync.cs
@@ -0,0 +1,120 @@
+using ChocolArm64.State;
+using Ryujinx.Core.OsHle.Handles;
+
+using static Ryujinx.Core.OsHle.ErrorCode;
+
+namespace Ryujinx.Core.OsHle.Kernel
+{
+ partial class SvcHandler
+ {
+ private void SvcArbitrateLock(AThreadState ThreadState)
+ {
+ int OwnerThreadHandle = (int)ThreadState.X0;
+ long MutexAddress = (long)ThreadState.X1;
+ int RequestingThreadHandle = (int)ThreadState.X2;
+
+ KThread OwnerThread = Process.HandleTable.GetData<KThread>(OwnerThreadHandle);
+
+ if (OwnerThread == null)
+ {
+ Logging.Warn(LogClass.KernelSvc, $"Invalid owner thread handle 0x{OwnerThreadHandle:x8}!");
+
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
+
+ return;
+ }
+
+ KThread RequestingThread = Process.HandleTable.GetData<KThread>(RequestingThreadHandle);
+
+ if (RequestingThread == null)
+ {
+ Logging.Warn(LogClass.KernelSvc, $"Invalid requesting thread handle 0x{RequestingThreadHandle:x8}!");
+
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
+
+ return;
+ }
+
+ MutualExclusion Mutex = GetMutex(MutexAddress);
+
+ Mutex.WaitForLock(RequestingThread, OwnerThreadHandle);
+
+ ThreadState.X0 = 0;
+ }
+
+ private void SvcArbitrateUnlock(AThreadState ThreadState)
+ {
+ long MutexAddress = (long)ThreadState.X0;
+
+ GetMutex(MutexAddress).Unlock();
+
+ Process.Scheduler.Yield(Process.GetThread(ThreadState.Tpidr));
+
+ ThreadState.X0 = 0;
+ }
+
+ private void SvcWaitProcessWideKeyAtomic(AThreadState ThreadState)
+ {
+ long MutexAddress = (long)ThreadState.X0;
+ long CondVarAddress = (long)ThreadState.X1;
+ int ThreadHandle = (int)ThreadState.X2;
+ long Timeout = (long)ThreadState.X3;
+
+ KThread Thread = Process.HandleTable.GetData<KThread>(ThreadHandle);
+
+ if (Thread == null)
+ {
+ Logging.Warn(LogClass.KernelSvc, $"Invalid thread handle 0x{ThreadHandle:x8}!");
+
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
+ }
+
+ MutualExclusion Mutex = GetMutex(MutexAddress);
+
+ Mutex.Unlock();
+
+ if (!GetCondVar(CondVarAddress).WaitForSignal(Thread, Timeout))
+ {
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.Timeout);
+
+ return;
+ }
+
+ Mutex.WaitForLock(Thread);
+
+ ThreadState.X0 = 0;
+ }
+
+ private void SvcSignalProcessWideKey(AThreadState ThreadState)
+ {
+ long CondVarAddress = (long)ThreadState.X0;
+ int Count = (int)ThreadState.X1;
+
+ KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
+
+ GetCondVar(CondVarAddress).SetSignal(CurrThread, Count);
+
+ ThreadState.X0 = 0;
+ }
+
+ private MutualExclusion GetMutex(long MutexAddress)
+ {
+ MutualExclusion MutexFactory(long Key)
+ {
+ return new MutualExclusion(Process, MutexAddress);
+ }
+
+ return Mutexes.GetOrAdd(MutexAddress, MutexFactory);
+ }
+
+ private ConditionVariable GetCondVar(long CondVarAddress)
+ {
+ ConditionVariable CondVarFactory(long Key)
+ {
+ return new ConditionVariable(Process, CondVarAddress);
+ }
+
+ return CondVars.GetOrAdd(CondVarAddress, CondVarFactory);
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Mutex.cs b/Ryujinx.Core/OsHle/Mutex.cs
deleted file mode 100644
index 7a0e8b6c..00000000
--- a/Ryujinx.Core/OsHle/Mutex.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-using Ryujinx.Core.OsHle.Handles;
-using System.Collections.Concurrent;
-using System.Threading;
-
-namespace Ryujinx.Core.OsHle
-{
- class Mutex
- {
- private const int MutexHasListenersMask = 0x40000000;
-
- private Process Process;
-
- private long MutexAddress;
-
- private bool OwnsMutexValue;
-
- private object EnterWaitLock;
-
- private ConcurrentQueue<KThread> WaitingThreads;
-
- public Mutex(Process Process, long MutexAddress, int OwnerThreadHandle)
- {
- this.Process = Process;
- this.MutexAddress = MutexAddress;
-
- //Process.Memory.WriteInt32(MutexAddress, OwnerThreadHandle);
-
- EnterWaitLock = new object();
-
- WaitingThreads = new ConcurrentQueue<KThread>();
- }
-
- public void WaitForLock(KThread RequestingThread, int RequestingThreadHandle)
- {
- AcquireMutexValue();
-
- lock (EnterWaitLock)
- {
- int CurrentThreadHandle = Process.Memory.ReadInt32(MutexAddress) & ~MutexHasListenersMask;
-
- if (CurrentThreadHandle == RequestingThreadHandle ||
- CurrentThreadHandle == 0)
- {
- return;
- }
-
- Process.Memory.WriteInt32(MutexAddress, CurrentThreadHandle | MutexHasListenersMask);
-
- ReleaseMutexValue();
-
- WaitingThreads.Enqueue(RequestingThread);
- }
-
- Process.Scheduler.WaitForSignal(RequestingThread);
- }
-
- public void GiveUpLock(int ThreadHandle)
- {
- AcquireMutexValue();
-
- lock (EnterWaitLock)
- {
- int CurrentThread = Process.Memory.ReadInt32(MutexAddress) & ~MutexHasListenersMask;
-
- if (CurrentThread == ThreadHandle)
- {
- Unlock();
- }
- }
-
- ReleaseMutexValue();
- }
-
- public void Unlock()
- {
- AcquireMutexValue();
-
- lock (EnterWaitLock)
- {
- int HasListeners = WaitingThreads.Count > 1 ? MutexHasListenersMask : 0;
-
- Process.Memory.WriteInt32(MutexAddress, HasListeners);
-
- ReleaseMutexValue();
-
- KThread[] UnlockedThreads = new KThread[WaitingThreads.Count];
-
- int Index = 0;
-
- while (WaitingThreads.TryDequeue(out KThread Thread))
- {
- UnlockedThreads[Index++] = Thread;
- }
-
- Process.Scheduler.Signal(UnlockedThreads);
- }
- }
-
- private void AcquireMutexValue()
- {
- if (!OwnsMutexValue)
- {
- while (!Process.Memory.AcquireAddress(MutexAddress))
- {
- Thread.Yield();
- }
-
- OwnsMutexValue = true;
- }
- }
-
- private void ReleaseMutexValue()
- {
- if (OwnsMutexValue)
- {
- OwnsMutexValue = false;
-
- Process.Memory.ReleaseAddress(MutexAddress);
- }
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs
index 0dd56dcb..f56103dc 100644
--- a/Ryujinx.Core/OsHle/Process.cs
+++ b/Ryujinx.Core/OsHle/Process.cs
@@ -5,8 +5,8 @@ using Ryujinx.Core.Loaders;
using Ryujinx.Core.Loaders.Executables;
using Ryujinx.Core.OsHle.Exceptions;
using Ryujinx.Core.OsHle.Handles;
+using Ryujinx.Core.OsHle.Kernel;
using Ryujinx.Core.OsHle.Services.Nv;
-using Ryujinx.Core.OsHle.Svc;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -55,17 +55,16 @@ namespace Ryujinx.Core.OsHle
private bool Disposed;
- public Process(Switch Ns, int ProcessId)
+ public Process(Switch Ns, KProcessScheduler Scheduler, int ProcessId)
{
this.Ns = Ns;
+ this.Scheduler = Scheduler;
this.ProcessId = ProcessId;
Memory = new AMemory();
HandleTable = new KProcessHandleTable();
- Scheduler = new KProcessScheduler();
-
AppletState = new AppletStateMgr();
SvcHandler = new SvcHandler(Ns, this);
@@ -127,7 +126,7 @@ namespace Ryujinx.Core.OsHle
long StackTop = MemoryRegions.MainStackAddress + MemoryRegions.MainStackSize;
- int Handle = MakeThread(Executables[0].ImageBase, StackTop, 0, 0, 0);
+ int Handle = MakeThread(Executables[0].ImageBase, StackTop, 0, 44, 0);
if (Handle == -1)
{
@@ -188,28 +187,32 @@ namespace Ryujinx.Core.OsHle
AThread Thread = new AThread(GetTranslator(), Memory, EntryPoint);
- KThread ThreadHnd = new KThread(Thread, ProcessorId, Priority);
+ KThread KernelThread = new KThread(Thread, ProcessorId, Priority);
+
+ int Handle = HandleTable.OpenHandle(KernelThread);
- int Handle = HandleTable.OpenHandle(ThreadHnd);
+ KernelThread.Handle = Handle;
int ThreadId = GetFreeTlsSlot(Thread);
long Tpidr = MemoryRegions.TlsPagesAddress + ThreadId * TlsSize;
+ Thread.ThreadState.ProcessId = ProcessId;
+ Thread.ThreadState.ThreadId = ThreadId;
+ Thread.ThreadState.CntfrqEl0 = TickFreq;
+ Thread.ThreadState.Tpidr = Tpidr;
+
+ Thread.ThreadState.X0 = (ulong)ArgsPtr;
+ Thread.ThreadState.X1 = (ulong)Handle;
+ Thread.ThreadState.X31 = (ulong)StackTop;
+
Thread.ThreadState.Break += BreakHandler;
Thread.ThreadState.SvcCall += SvcHandler.SvcCall;
Thread.ThreadState.Undefined += UndefinedHandler;
- Thread.ThreadState.ProcessId = ProcessId;
- Thread.ThreadState.ThreadId = ThreadId;
- Thread.ThreadState.CntfrqEl0 = TickFreq;
- Thread.ThreadState.Tpidr = Tpidr;
- Thread.ThreadState.X0 = (ulong)ArgsPtr;
- Thread.ThreadState.X1 = (ulong)Handle;
- Thread.ThreadState.X31 = (ulong)StackTop;
Thread.WorkFinished += ThreadFinished;
- ThreadsByTpidr.TryAdd(Thread.ThreadState.Tpidr, ThreadHnd);
+ ThreadsByTpidr.TryAdd(Thread.ThreadState.Tpidr, KernelThread);
return Handle;
}
@@ -293,6 +296,12 @@ namespace Ryujinx.Core.OsHle
Logging.Info(LogClass.KernelScheduler, $"Thread {Thread.ThreadId} exiting...");
TlsSlots.TryRemove(GetTlsSlot(Thread.ThreadState.Tpidr), out _);
+
+ KThread KernelThread = GetThread(Thread.ThreadState.Tpidr);
+
+ Scheduler.RemoveThread(KernelThread);
+
+ KernelThread.WaitEvent.Set();
}
if (TlsSlots.Count == 0)
diff --git a/Ryujinx.Core/OsHle/Services/Aud/IAudioOutManager.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioOutManager.cs
index 986b5c1e..b1d20fbe 100644
--- a/Ryujinx.Core/OsHle/Services/Aud/IAudioOutManager.cs
+++ b/Ryujinx.Core/OsHle/Services/Aud/IAudioOutManager.cs
@@ -76,7 +76,7 @@ namespace Ryujinx.Core.OsHle.Services.Aud
ReleaseCallback Callback = () =>
{
- ReleaseEvent.Handle.Set();
+ ReleaseEvent.WaitEvent.Set();
};
int Track = AudioOut.OpenTrack(SampleRate, Channels, Callback, out AudioFormat Format);
diff --git a/Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs
index 9a20939e..d3795b53 100644
--- a/Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs
+++ b/Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs
@@ -47,7 +47,7 @@ namespace Ryujinx.Core.OsHle.Services.Aud
}
//TODO: We shouldn't be signaling this here.
- UpdateEvent.Handle.Set();
+ UpdateEvent.WaitEvent.Set();
return 0;
}
diff --git a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs
index 3ba4a45f..4dc01997 100644
--- a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs
+++ b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs
@@ -391,7 +391,7 @@ namespace Ryujinx.Core.OsHle.Services.Android
{
BufferQueue[Slot].State = BufferState.Free;
- ReleaseEvent.Handle.Set();
+ ReleaseEvent.WaitEvent.Set();
lock (WaitBufferFree)
{
diff --git a/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs b/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs
deleted file mode 100644
index 318688b8..00000000
--- a/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-using ChocolArm64.State;
-using Ryujinx.Core.OsHle.Handles;
-
-using static Ryujinx.Core.OsHle.ErrorCode;
-
-namespace Ryujinx.Core.OsHle.Svc
-{
- partial class SvcHandler
- {
- private void SvcArbitrateLock(AThreadState ThreadState)
- {
- int OwnerThreadHandle = (int)ThreadState.X0;
- long MutexAddress = (long)ThreadState.X1;
- int RequestingThreadHandle = (int)ThreadState.X2;
-
- KThread RequestingThread = Process.HandleTable.GetData<KThread>(RequestingThreadHandle);
-
- Mutex M = new Mutex(Process, MutexAddress, OwnerThreadHandle);
-
- M = Ns.Os.Mutexes.GetOrAdd(MutexAddress, M);
-
- M.WaitForLock(RequestingThread, RequestingThreadHandle);
-
- ThreadState.X0 = 0;
- }
-
- private void SvcArbitrateUnlock(AThreadState ThreadState)
- {
- long MutexAddress = (long)ThreadState.X0;
-
- if (Ns.Os.Mutexes.TryGetValue(MutexAddress, out Mutex M))
- {
- M.Unlock();
- }
-
- ThreadState.X0 = 0;
- }
-
- private void SvcWaitProcessWideKeyAtomic(AThreadState ThreadState)
- {
- long MutexAddress = (long)ThreadState.X0;
- long CondVarAddress = (long)ThreadState.X1;
- int ThreadHandle = (int)ThreadState.X2;
- long Timeout = (long)ThreadState.X3;
-
- KThread Thread = Process.HandleTable.GetData<KThread>(ThreadHandle);
-
- Mutex M = new Mutex(Process, MutexAddress, ThreadHandle);
-
- M = Ns.Os.Mutexes.GetOrAdd(MutexAddress, M);
-
- M.GiveUpLock(ThreadHandle);
-
- CondVar Cv = new CondVar(Process, CondVarAddress, Timeout);
-
- Cv = Ns.Os.CondVars.GetOrAdd(CondVarAddress, Cv);
-
- if (!Cv.WaitForSignal(Thread))
- {
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.Timeout);
-
- return;
- }
-
- M.WaitForLock(Thread, ThreadHandle);
-
- ThreadState.X0 = 0;
- }
-
- private void SvcSignalProcessWideKey(AThreadState ThreadState)
- {
- long CondVarAddress = (long)ThreadState.X0;
- int Count = (int)ThreadState.X1;
-
- KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
-
- if (Ns.Os.CondVars.TryGetValue(CondVarAddress, out CondVar Cv))
- {
- Cv.SetSignal(CurrThread, Count);
- }
-
- ThreadState.X0 = 0;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs
index 5e3e1e65..6b6ae6a0 100644
--- a/Ryujinx/Ui/GLScreen.cs
+++ b/Ryujinx/Ui/GLScreen.cs
@@ -1,6 +1,5 @@
using OpenTK;
using OpenTK.Graphics;
-using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
using Ryujinx.Core;
using Ryujinx.Core.Input;