Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Emulator/Cores/tlib
11 changes: 5 additions & 6 deletions src/Emulator/Peripherals/Peripherals/CPU/BaseCPU.cs
Original file line number Diff line number Diff line change
Expand Up @@ -792,14 +792,13 @@ protected CpuResult CpuThreadBodyInner(bool singleStep, bool skipThisRound = fal
this.Trace();
var instructionsToSkip = Math.Min(InstructionsToNearestLimit(), instructionsLeftThisRound);

virtualTimeAhead = machine.LocalTimeSource.ElapsedVirtualHostTimeDifference;
if(!machine.LocalTimeSource.AdvanceImmediately && virtualTimeAhead.Ticks > 0 && instructionsToSkip > 0)
if(!machine.LocalTimeSource.AdvanceImmediately && instructionsToSkip > 0)
{
// Don't fall behind realtime by sleeping
var intervalToSleep = TimeInterval.FromCPUCycles(instructionsToSkip, PerformanceInMips, out var cyclesResiduum).WithTicksMin(virtualTimeAhead.Ticks);
// Sleep for the full remaining quantum while waiting for an interrupt.
// sleeper.Interrupt() from OnGPIO will wake us early when an IRQ arrives,
// so we only burn host CPU for the actual wait duration, not the full quantum.
var intervalToSleep = TimeInterval.FromCPUCycles(instructionsToSkip, PerformanceInMips, out var cyclesResiduum);
sleeper.Sleep(intervalToSleep.ToTimeSpan(out var nsResiduum), out var intervalSlept);
// If we have a CPU of less than 10 MIPS, it might be the case that the interval slept (which is in units of 100 ns)
// is less than 1 instruction. Just round up it in this case.
instructionsToSkip = Math.Max(TimeInterval.FromTimeSpan(intervalSlept, nsResiduum).ToCPUCycles(PerformanceInMips, out var _) + cyclesResiduum, 1);
}

Expand Down