summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2021-03-19 02:09:03 -0700
committer Aaron Giles <aaron@aarongiles.com>2021-03-19 02:09:03 -0700
commitb531cd61eeebb3d34b0f1fc2e9b6c6e789f49e80 (patch)
tree930f3c027d504262b4b841d0ba4255b35bc18ac0
parentc5f0635323338d3e65850f83171b81dcdf2f86c6 (diff)
Aim for overshoot rather than undershoot when scheduling devices, reducing needless extra loops in core scheduler.
-rw-r--r--src/emu/schedule.cpp96
1 files changed, 46 insertions, 50 deletions
diff --git a/src/emu/schedule.cpp b/src/emu/schedule.cpp
index e6c883ee5d7..9306757a2e6 100644
--- a/src/emu/schedule.cpp
+++ b/src/emu/schedule.cpp
@@ -461,70 +461,66 @@ void device_scheduler::timeslice()
if (m_suspend_changes_pending)
apply_suspend_changes();
- // loop over all CPUs
+ // loop over all executing devices
for (device_execute_interface *exec = m_execute_list; exec != nullptr; exec = exec->m_nextexec)
{
- // only process if this CPU is executing or truly halted (not yielding)
+ // only process if this device is executing or truly halted (not yielding)
// and if our target is later than the CPU's current time (coarse check)
if (EXPECTED(exec->m_suspend == 0 || exec->m_eatcycles))
{
// compute how many attoseconds to execute this CPU
attoseconds_t delta = target - exec->m_localtime.relative();
- if (exec->m_attoseconds_per_cycle == 0)
- {
- exec->m_localtime.set(target);
- }
- // if we have enough for at least 1 cycle, do the math
- else if (delta >= exec->m_attoseconds_per_cycle)
- {
- // compute how many cycles we want to execute
- int ran = exec->m_cycles_running = divu_64x32(u64(delta) >> exec->m_divshift, exec->m_divisor);
- LOG(" cpu '%s': %d (%d cycles)\n", exec->device().tag(), delta, exec->m_cycles_running);
+ // if we're already ahead, do nothing
+ if (delta <= 0)
+ continue;
- // if we're not suspended, actually execute
- if (exec->m_suspend == 0)
+ // compute how many cycles we want to execute, rounding up
+ u32 ran = exec->m_cycles_running = u64(delta - 1) / u64(exec->m_attoseconds_per_cycle) + 1;
+ LOG(" cpu '%s': %d (%d cycles)\n", exec->device().tag(), delta, exec->m_cycles_running);
+
+ // if we're not suspended, actually execute
+ if (exec->m_suspend == 0)
+ {
+ g_profiler.start(exec->m_profiler);
+
+ // note that this global variable cycles_stolen can be modified
+ // via the call to cpu_execute
+ exec->m_cycles_stolen = 0;
+ m_executing_device = exec;
+ *exec->m_icountptr = exec->m_cycles_running;
+ if (!call_debugger)
+ exec->run();
+ else
{
- g_profiler.start(exec->m_profiler);
-
- // note that this global variable cycles_stolen can be modified
- // via the call to cpu_execute
- exec->m_cycles_stolen = 0;
- m_executing_device = exec;
- *exec->m_icountptr = exec->m_cycles_running;
- if (!call_debugger)
- exec->run();
- else
- {
- exec->debugger_start_cpu_hook(attotime(m_basetime.seconds(), target) + attotime::zero);
- exec->run();
- exec->debugger_stop_cpu_hook();
- }
-
- // adjust for any cycles we took back
- assert(ran >= *exec->m_icountptr);
- ran -= *exec->m_icountptr;
- assert(ran >= exec->m_cycles_stolen);
- ran -= exec->m_cycles_stolen;
- g_profiler.stop();
+ exec->debugger_start_cpu_hook(attotime(m_basetime.seconds(), target) + attotime::zero);
+ exec->run();
+ exec->debugger_stop_cpu_hook();
}
- // account for these cycles
- exec->m_totalcycles += ran;
+ // adjust for any cycles we took back
+ assert(ran >= *exec->m_icountptr);
+ ran -= *exec->m_icountptr;
+ assert(ran >= exec->m_cycles_stolen);
+ ran -= exec->m_cycles_stolen;
+ g_profiler.stop();
+ }
- // update the local time for this CPU
- assert(ran < exec->m_cycles_per_second);
- attoseconds_t deltatime = exec->m_attoseconds_per_cycle * ran;
- assert(deltatime >= 0);
- exec->m_localtime.add(deltatime);
- LOG(" %d ran, %d total, time = %s\n", ran, s32(exec->m_totalcycles), exec->m_localtime.as_string(PRECISION));
+ // account for these cycles
+ exec->m_totalcycles += ran;
- // if the new local CPU time is less than our target, move the target up, but not before the base
- if (exec->m_localtime.relative() < target)
- {
- target = std::max(exec->m_localtime.relative(), basetime);
- LOG(" (new target)\n");
- }
+ // update the local time for this CPU
+ assert(ran < exec->m_cycles_per_second);
+ attoseconds_t deltatime = exec->m_attoseconds_per_cycle * ran;
+ assert(deltatime >= 0);
+ exec->m_localtime.add(deltatime);
+ LOG(" %d ran, %d total, time = %s\n", ran, s32(exec->m_totalcycles), exec->m_localtime.as_string(PRECISION));
+
+ // if the new local CPU time is less than our target, move the target up, but not before the base
+ if (exec->m_localtime.relative() < target)
+ {
+ target = std::max(exec->m_localtime.relative(), basetime);
+ LOG(" (new target)\n");
}
}
}