diff --git a/ChocolArm64/AThread.cs b/ChocolArm64/AThread.cs index 76b36da4..38c2b53d 100644 --- a/ChocolArm64/AThread.cs +++ b/ChocolArm64/AThread.cs @@ -46,8 +46,6 @@ namespace ChocolArm64 return false; } - Work.Name = "cpu_thread_" + Work.ManagedThreadId; - Work.Start(); return true; diff --git a/ChocolArm64/State/AThreadState.cs b/ChocolArm64/State/AThreadState.cs index 783f5a12..22e3df14 100644 --- a/ChocolArm64/State/AThreadState.cs +++ b/ChocolArm64/State/AThreadState.cs @@ -2,6 +2,7 @@ using ChocolArm64.Events; using System; using System.Collections.Generic; using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Runtime.Intrinsics; namespace ChocolArm64.State @@ -14,6 +15,8 @@ namespace ChocolArm64.State internal const int ErgSizeLog2 = 4; internal const int DczSizeLog2 = 4; + private const int MinInstForCheck = 4000000; + internal AExecutionMode ExecutionMode; //AArch32 state. @@ -45,6 +48,8 @@ namespace ChocolArm64.State private bool Interrupted; + private int SyncCount; + public long TpidrEl0 { get; set; } public long Tpidr { get; set; } @@ -101,13 +106,16 @@ namespace ChocolArm64.State TickCounter.Start(); } - internal bool Synchronize() + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal bool Synchronize(int BbWeight) { - if (Interrupted) - { - Interrupted = false; + //Firing a interrupt frequently is expensive, so we only + //do it after a given number of instructions has executed. + SyncCount += BbWeight; - OnInterrupt(); + if (SyncCount >= MinInstForCheck) + { + CheckInterrupt(); } return Running; @@ -118,9 +126,17 @@ namespace ChocolArm64.State Interrupted = true; } - private void OnInterrupt() + [MethodImpl(MethodImplOptions.NoInlining)] + private void CheckInterrupt() { - Interrupt?.Invoke(this, EventArgs.Empty); + SyncCount = 0; + + if (Interrupted) + { + Interrupted = false; + + Interrupt?.Invoke(this, EventArgs.Empty); + } } internal void OnBreak(long Position, int Imm) diff --git a/ChocolArm64/Translation/AILEmitterCtx.cs b/ChocolArm64/Translation/AILEmitterCtx.cs index 40e33ba8..48700715 100644 --- a/ChocolArm64/Translation/AILEmitterCtx.cs +++ b/ChocolArm64/Translation/AILEmitterCtx.cs @@ -123,6 +123,8 @@ namespace ChocolArm64.Translation { EmitLdarg(ATranslatedSub.StateArgIdx); + EmitLdc_I4(CurrBlock.OpCodes.Count); + EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.Synchronize)); EmitLdc_I4(0); diff --git a/Ryujinx.HLE/HOS/Kernel/KCoreContext.cs b/Ryujinx.HLE/HOS/Kernel/KCoreContext.cs index 70fe1a61..51f27e2a 100644 --- a/Ryujinx.HLE/HOS/Kernel/KCoreContext.cs +++ b/Ryujinx.HLE/HOS/Kernel/KCoreContext.cs @@ -28,7 +28,10 @@ namespace Ryujinx.HLE.HOS.Kernel Thread.LastScheduledTicks = (uint)Environment.TickCount; } - ContextSwitchNeeded = true; + if (SelectedThread != CurrentThread) + { + ContextSwitchNeeded = true; + } } public void UpdateCurrentThread() @@ -58,10 +61,5 @@ namespace Ryujinx.HLE.HOS.Kernel CurrentThread.Context.Execute(); } } - - public void RemoveThread(KThread Thread) - { - //TODO. - } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SchedulerThread.cs b/Ryujinx.HLE/HOS/Kernel/SchedulerThread.cs deleted file mode 100644 index bab7b03e..00000000 --- a/Ryujinx.HLE/HOS/Kernel/SchedulerThread.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Threading; - -namespace Ryujinx.HLE.HOS.Kernel -{ - class SchedulerThread : IDisposable - { - public KThread Thread { get; private set; } - - public SchedulerThread Next { get; set; } - - public bool IsActive { get; set; } - - public AutoResetEvent WaitSync { get; private set; } - public ManualResetEvent WaitActivity { get; private set; } - public AutoResetEvent WaitSched { get; private set; } - - public SchedulerThread(KThread Thread) - { - this.Thread = Thread; - - IsActive = true; - - WaitSync = new AutoResetEvent(false); - - WaitActivity = new ManualResetEvent(true); - - WaitSched = new AutoResetEvent(false); - } - - public void Dispose() - { - Dispose(true); - } - - protected virtual void Dispose(bool Disposing) - { - if (Disposing) - { - WaitSync.Dispose(); - - WaitActivity.Dispose(); - - WaitSched.Dispose(); - } - } - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SvcThread.cs b/Ryujinx.HLE/HOS/Kernel/SvcThread.cs index aa6e551b..dc296b06 100644 --- a/Ryujinx.HLE/HOS/Kernel/SvcThread.cs +++ b/Ryujinx.HLE/HOS/Kernel/SvcThread.cs @@ -81,8 +81,6 @@ namespace Ryujinx.HLE.HOS.Kernel CurrentThread.Exit(); System.Scheduler.StopThread(CurrentThread); - - System.Scheduler.CoreContexts[CurrentThread.CurrentCore].RemoveThread(CurrentThread); } private void SvcSleepThread(AThreadState ThreadState) diff --git a/Ryujinx.HLE/HOS/Process.cs b/Ryujinx.HLE/HOS/Process.cs index 7900705d..0bc95f0c 100644 --- a/Ryujinx.HLE/HOS/Process.cs +++ b/Ryujinx.HLE/HOS/Process.cs @@ -356,7 +356,10 @@ namespace Ryujinx.HLE.HOS { if (sender is AThread Thread) { - Threads.TryRemove(Thread.ThreadState.Tpidr, out KThread KernelThread); + if (Threads.TryRemove(Thread.ThreadState.Tpidr, out KThread KernelThread)) + { + Device.System.Scheduler.RemoveThread(KernelThread); + } } if (Threads.Count == 0)