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
pseudocode:
/* countdown to next event */
if (event_queue_head != NULL && event_queue_head->ticks > 0)
event_queue_head->ticks--;
/* 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 */
delete_event_queue_head();
}
/* 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
second.
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:
Linux:
http://tldp.org/HOWTO/ACPI-HOWTO/usingacpi.html
Win32:
http://msdn.microsoft.com/en-us/library/aa373163(VS.85).aspx
http://msdn.microsoft.com/en-us/library/aa373196(VS.85).aspx
Jake
_______________________________________________
Rpcemu mailing list
[email protected]
http://www.riscos.info/cgi-bin/mailman/listinfo/rpcemu