forked from Mirror/Ryujinx
Fix performance regression caused by the new scheduler changes (#422)
* Call interrupt less often, remove some leftovers from the old scheduler code * Remove unneeded attribute
This commit is contained in:
parent
fae097408e
commit
99b2692425
7 changed files with 33 additions and 66 deletions
|
@ -46,8 +46,6 @@ namespace ChocolArm64
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Work.Name = "cpu_thread_" + Work.ManagedThreadId;
|
|
||||||
|
|
||||||
Work.Start();
|
Work.Start();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -2,6 +2,7 @@ using ChocolArm64.Events;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.Intrinsics;
|
using System.Runtime.Intrinsics;
|
||||||
|
|
||||||
namespace ChocolArm64.State
|
namespace ChocolArm64.State
|
||||||
|
@ -14,6 +15,8 @@ namespace ChocolArm64.State
|
||||||
internal const int ErgSizeLog2 = 4;
|
internal const int ErgSizeLog2 = 4;
|
||||||
internal const int DczSizeLog2 = 4;
|
internal const int DczSizeLog2 = 4;
|
||||||
|
|
||||||
|
private const int MinInstForCheck = 4000000;
|
||||||
|
|
||||||
internal AExecutionMode ExecutionMode;
|
internal AExecutionMode ExecutionMode;
|
||||||
|
|
||||||
//AArch32 state.
|
//AArch32 state.
|
||||||
|
@ -45,6 +48,8 @@ namespace ChocolArm64.State
|
||||||
|
|
||||||
private bool Interrupted;
|
private bool Interrupted;
|
||||||
|
|
||||||
|
private int SyncCount;
|
||||||
|
|
||||||
public long TpidrEl0 { get; set; }
|
public long TpidrEl0 { get; set; }
|
||||||
public long Tpidr { get; set; }
|
public long Tpidr { get; set; }
|
||||||
|
|
||||||
|
@ -101,13 +106,16 @@ namespace ChocolArm64.State
|
||||||
TickCounter.Start();
|
TickCounter.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool Synchronize()
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal bool Synchronize(int BbWeight)
|
||||||
{
|
{
|
||||||
if (Interrupted)
|
//Firing a interrupt frequently is expensive, so we only
|
||||||
{
|
//do it after a given number of instructions has executed.
|
||||||
Interrupted = false;
|
SyncCount += BbWeight;
|
||||||
|
|
||||||
OnInterrupt();
|
if (SyncCount >= MinInstForCheck)
|
||||||
|
{
|
||||||
|
CheckInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Running;
|
return Running;
|
||||||
|
@ -118,10 +126,18 @@ namespace ChocolArm64.State
|
||||||
Interrupted = true;
|
Interrupted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInterrupt()
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
private void CheckInterrupt()
|
||||||
{
|
{
|
||||||
|
SyncCount = 0;
|
||||||
|
|
||||||
|
if (Interrupted)
|
||||||
|
{
|
||||||
|
Interrupted = false;
|
||||||
|
|
||||||
Interrupt?.Invoke(this, EventArgs.Empty);
|
Interrupt?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal void OnBreak(long Position, int Imm)
|
internal void OnBreak(long Position, int Imm)
|
||||||
{
|
{
|
||||||
|
|
|
@ -123,6 +123,8 @@ namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
EmitLdarg(ATranslatedSub.StateArgIdx);
|
EmitLdarg(ATranslatedSub.StateArgIdx);
|
||||||
|
|
||||||
|
EmitLdc_I4(CurrBlock.OpCodes.Count);
|
||||||
|
|
||||||
EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.Synchronize));
|
EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.Synchronize));
|
||||||
|
|
||||||
EmitLdc_I4(0);
|
EmitLdc_I4(0);
|
||||||
|
|
|
@ -28,8 +28,11 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
Thread.LastScheduledTicks = (uint)Environment.TickCount;
|
Thread.LastScheduledTicks = (uint)Environment.TickCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SelectedThread != CurrentThread)
|
||||||
|
{
|
||||||
ContextSwitchNeeded = true;
|
ContextSwitchNeeded = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void UpdateCurrentThread()
|
public void UpdateCurrentThread()
|
||||||
{
|
{
|
||||||
|
@ -58,10 +61,5 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
CurrentThread.Context.Execute();
|
CurrentThread.Context.Execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveThread(KThread Thread)
|
|
||||||
{
|
|
||||||
//TODO.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -81,8 +81,6 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
CurrentThread.Exit();
|
CurrentThread.Exit();
|
||||||
|
|
||||||
System.Scheduler.StopThread(CurrentThread);
|
System.Scheduler.StopThread(CurrentThread);
|
||||||
|
|
||||||
System.Scheduler.CoreContexts[CurrentThread.CurrentCore].RemoveThread(CurrentThread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SvcSleepThread(AThreadState ThreadState)
|
private void SvcSleepThread(AThreadState ThreadState)
|
||||||
|
|
|
@ -356,7 +356,10 @@ namespace Ryujinx.HLE.HOS
|
||||||
{
|
{
|
||||||
if (sender is AThread Thread)
|
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)
|
if (Threads.Count == 0)
|
||||||
|
|
Loading…
Reference in a new issue