[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