[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[MiNT] Tsetitimer()



On Sun, 2005-11-06 at 17:11 -0600, Evan Langlois wrote:

> has an alarm() but the granularity is seconds.  Setitimer has
> microsecond granularity, so MiNT compromises with a millisecond
> Talarm().

After looking at the code, it looks like Talarm(), opcode 0x120, may
only have a granularity of seconds according to the comments in the
kernel, which isn't what the Compendium says.  Could someone confirm?
It looks like there is a new call, Tmalarm(), opcode 0x13d, for
millisecond granularity.

There is also a Tsetitimer() function just like in Unix and this is the
call that the Unix shell command "time" uses, but it looks like its
limited to millisecond granularity (most Unix systems go to microsecond
granularity here).  I recommend its use for your timer needs.  You can
schedule different types of alarms for different types of time if you
need to.  Its not documented in the compendium, so I'll give the details
here since I have the code on my screen and I've been working with the
setitimer() call recently under Linux for some code I've been working
on.

Tsetitimer(which, interval, value, ointerval, ovalue)
GEMDOS OpCode: 0x149
int which;
long *interval, *value, *ointerval, *ovalue;

which determines which timer you are looking to modify:
#define ITIMER_REAL    0
#define ITIMER_VIRTUAL 1
#define ITIMER_PROF    2

Everything else is a pointer to a 32 bit value in milliseconds.
As the timer ticks, value is decremented.  When value reaches 0, it
sends you a signal and then resets "value" to "interval", so unlike
working with Talarm(), you're clock keeps ticking until you set interval
to 0.

The "ovalue" and "ointerval" are the old values, which will be filled in
by the kernel in case you want to know them.

The three timers are each have a different signal.  ITIMER_REAL sends a
SIGALRM, so don't use it with Talarm() in the same program, they
normally share the same timer!  This timer decrements in real time (aka,
wall clock time).  ITIMER_VIRTUAL only ticks while the process is
executing (aka "user time"), so if your program is blocking for events,
this timer won't tick.  It sends a SIGVTALARM. ITIMER_PROF ticks as long
as your program runs AND while the kernel is executing on your programs
behalf ("user time" + "system time", subtract to get just "system
time").  It sends a SIGPROF.

In general, your process only gets *1* timer of each type, so you have
to do some calculations if you want multiple timer events and only
schedule the NEXT alarm.

Incidently, there isn't much you are allowed to do from within a timer
itself.  The Linux project I'm working on uses a simple trick to
integrate signals into the event loop based on the fact that most OSs
will allow you to call write() from a signal handler!  Is this allowed
in MiNT?

Basically, for any signal I'm interested in, I use sigaction() so that
the signal handler is directed to my signal handler function.  The
signal handler then just writes the signal number to a pipe.  The main
event loop will then wake up and run the "event" defined for that pipe
file handle.  The event reads the signal number from the pipe and then
uses a switch statement to get to the code for that particular signal.
In the case of timer signals, I grab the timer events from a queue and
execute them until I find a timer event that isn't ready to be executed
yet and then call setitimer() to schedule the next timer event, and then
return to the event loop.  

I can then handle an unlimited number of timer events (up to 49 days
away) and have it completely integrated with the main event loop, while
only using the single alarm timer.  I've been testing it with 10, 25,
30, and 50ms interval timers as well as a 5s interval timer that
schedules a single 10s timer event.  Its currently set to never schedule
more than 1 event during the same ms, so it just delays the event until
the next ms.  I may get rid of this restriction as right now I get 0-4ms
latency as some events are being forced back on the queue when the
events would overlap.   I'm not sure if the added trouble is really
worth it though.  Being 4ms late doesn't seem all that bad to me.

BTW - this should all port to MiNT fairly easily.  Anyone know if the
MiNT poll() will handle more than 32 file handles?  It looks like it
calls select() and that has a limit of 32 file handles since it just
points to a long.  GUI events will be handled in a similar manner
(across a pipe, using a seperate thread for the GUI event loop).  I'm
just waiting on a new Aranym release before I attempt to port
anything.  

-- Evan