[Simh] CPU idle on vax - patch
Peter Svensson
psvsimh at psv.nu
Tue Aug 3 10:59:24 EDT 2010
Hi,
The stock CPU idle support for the vax emulation seems to not work. I
found two problems:
1) The code in cpu_set_idle() in vax_cpu.c calls sim_set_idle() with the
string argument. This is a numeric argument used on some targets. For vax
I think it should instead pass in a NULL if it is targeting one of the
operating systems supported on the vax target. As it currently is the
sim_set_idle will reject the activation of the idle function since the
argument it receives is not numeric.
2) When the cpu_idle_svc() function in vax_cpu fires it instructs
sim_idle() to try to sleep until the next scheduled event. If that is too
near no sleep is done. However, cpu_idle_svc can only be scheduled after
an exception or REI. There are several scheduled events which do not
always generate interrupts, e.g. the tti_svc which polls regularly. These
will prevent (if fired close to idle loop entry) or at least terminate the
idle sleep.
I created the attached patch. It seems to work well for Ultrix and VMS. On
my computer both Ultrix and VMS now idle at 1-2% CPU load, while still
performing as normal when loaded. Before the load would be close to 100%.
With only the first part of the patch (cpu_set_idle) the load went down
and then back up as the simulated idle loop drifted in and out of phase
with respect to the tti_svc routine.
For 1) the patch is a simple change to NULL if the argument was found in
the list of supported operating systems.
For 2) I tried two versions. In one version cpu_idle_svc() was rescheduled
by cpu_idle_svc itself if sim_idle() indicated a failure. Thus a new sleep
attempt would be made cpu_idle_wait instructions later. If the code
meanwhile executed an interrupt the existing code in cpu_psl_ipl_idle()
should cancel the cpu_idle_svc with no ill effects. This handles the case
where sleep is prevented by the tti_svc or similar being scheduled close
to the start of the idle code.
The second version (activated by default in the patch by the preprocessor
#if always schedules another cpu_idle_svc() after sim_idle() returns. This
way, any number of other scheduled events may occur between each actual
exception and sleep will resume cpu_idle_wait instructions after each
non-exception-generating event. Again, any exception will cancel the
cpu_idle_svc() via cpu_psl_ipl_idle().
I do not know if other targets would benefit from similar changes. I only
use the vax target.
Peter
-------------- next part --------------
--- VAX/vax_cpu.c.ORIG 2010-08-02 11:18:25.000000000 +0200
+++ VAX/vax_cpu.c 2010-08-03 15:39:56.000000000 +0200
@@ -3088,8 +3088,16 @@
t_stat cpu_idle_svc (UNIT *uptr)
{
-if (sim_idle_enab)
+if (sim_idle_enab) {
+#if 0
+ if (! sim_idle (TMR_CLK, FALSE) ) {
+ sim_activate (&cpu_unit, cpu_idle_wait);
+ }
+#else
sim_idle (TMR_CLK, FALSE);
+ sim_activate (&cpu_unit, cpu_idle_wait);
+#endif
+ }
return SCPE_OK;
}
@@ -3399,7 +3407,7 @@
if (strcmp (os_tab[i].name, cptr) == 0) {
cpu_idle_type = i + 1;
cpu_idle_ipl_mask = os_tab[i].mask;
- return sim_set_idle (uptr, val, cptr, desc);
+ return sim_set_idle (uptr, val, NULL, desc);
}
}
return SCPE_ARG;
More information about the Simh
mailing list