[Rpcemu] Improving CPU usage when idle

Jake Waskett jake at waskett.org
Mon Apr 6 16:54:34 EDT 2009

On 06/04/09 13:24 +0100, Theo Markettos wrote:
>So I wonder if it would be feasible to have a separate user input and timer
>thread?  This queues up mouse and keyboard events, and runs the timers. 
>Each mouse/key event is supplied with a timestamp, which is delivered to the
>emulator as an interrupt.

I'm just trying to make sense of the IOMD timer code at the moment,
and wonder if perhaps someone can help bring me up to speed.  The code
is somewhat confusing - a brief overview of how the current mechanisms
work would save a lot of time in trying to work it out!

>We have to be a bit careful, because in the real hardware there's no
>timestamp supplied with events: the OS just reads the central timer sometime
>after the interrupt is received.  So presumably we can cause the timer to
>jump forward to the time of the click, but we have to keep on incrementing
>it afterwards.

I'm not sure that we can safely jump forwards in time (as it were)
when delivering simulated events.  I think that we need to try to
replicate the same intervals between each event.  If I remember
correctly (it has been a decade, so forgive me if I'm totally wrong
here!), RISC OS uses a 10 millisecond timer to coordinate the timing
needs of the system.  This is more than fast enough for both mouse and
keyboard events, so I anticipated adding something like the following

/* countdown to next event */
if (event_queue_head != NULL && event_queue_head->ticks > 0)

/* and simulate all pending events */
while (event_queue_head != NULL && event_queue_head->ticks == 0)
    /* do what's necessary to simulate event */
    /* ... */
    /* and remove it from the event queue */

/* now simulate timer interrupt */

> This means that things that check whether a long enough
>period has elapsed between events (eg key auto-repeat) may fail if the timer
>keeps getting incremented by the thread but the interrupt service routine on
>the emulator hasn't got run because the machine is so busy that the CPU
>thread hasn't got run yet.

I'm not sure if I fully understand the problem.  I think the above
code would handle that, provided that it was called from the context
of the CPU thread.

I'm making the assumption that Allegro has a background thread that
does an XNextEvent, GetMessage, or whatever it is under MacOS, and
then calls the callback routines.  I think this must be the case,
because otherwise we'd have to poll periodically, and that doesn't
seem to be necessary.  A small amount of thread synchronisation code
will be needed to protect the integrity of the queue data structure,
and I think this will have to depend on this thread.  This is a bit
ugly as an implementation detail, and I don't particularly like that
little bit of non-portable code (it'll have to be #ifdef'd), but I
don't see any alternative.

>True, I hadn't thought about putting the CPU into idle, I was more assuming that
>if the CPU load was reduced the (Centrino/whatever) CPU clock would be
>reduced.  The system load would increase, but it would still get the jobs
>done under the lower clock.

I think it's best to leave that kind of decision to the host kernel.
Managing the hardware for optimum power usage is its responsibility,
not ours.  All we need to do to help it is to try to be asleep as
often and for as long as possible.

>That's true.  Probably a Wimp filter would return you that information...
>(Pity we can't access the Wimp's idle loop directly)

I know nothing whatsoever about Wimp filters. :-)

>> Portable_Speed, however, is certainly being called in 4.02, and would
>> be perfect for gauging the system load.
>It's only a binary switch though, but if the Wimp modulates it fast enough
>it may be acceptable (eg once/second not once/minute).

I don't think that's going to be a problem.  It seems extremely
responsive.  I'm seeing as many as five calls to Portable_Speed per

>Sounds good to me.  RISC OS code can be inserted in the emulator by building
>it as a module and putting it into the 'poduleroms' directory.  The emulator
>packs it all up into a ROM image which it inserts as an emulated podule. 
>That code gets linked into the module chain quite early on in the RISC OS
>boot sequence.

Right, that should work then.  It seems sensible, though, to get the
event queueing working first.

>Another use for the Portable module is to tell the emulator about the host's
>battery state.  The RO6 PRM describes how VRPC uses this - not much
>different to what the A4 and A9home do.  Is there a cross-platform way for
>the emulator to read the power management state?

No such luck, I'm afraid.  It wouldn't be *too* hard to write a little
library to abstract the differences.  Here is some of the
documentation that I'm aware of:




More information about the Rpcemu mailing list