Jan Kiszka wrote:
> > I still don't get why you would bother providing two different time
> > specs? Is this really needed?
>
> I think it's time to repeat the measuring, e.g. rt_timer_read() vs.
> rt_timer_read_tsc(). It will certainly not make a big difference on GHz
> machines, but on anything around Pentium I, we once measured a
> significant overhead. Will try to organise some more concrete numbers
> tomorrow.
What costs are the calls to llimd and imuldiv, right ? According to
some measurements I made, ullimd is around 100 cycles and imuldiv around
30 cycles on a PII and PIII class machine without cache effects. By
pre-computing the conversion factors (this can always be done, since
they do not change often), you can even go down to less than 30 cycles
for ullimd and less than 5 cycles for imuldiv (1 cycle on pentium
M), I never commited this, since I lost one bit of accuracy, and never
understood where... But even 100 cycles is ridiculous when compared to
cache effects and hardware latencies. And llimd should never be called
on the critical path, that is at the wake-up time, only imuldiv is
called to compute the next timer shot.
> Simple example, based on native skin:
> Call rt_sem_p with a timeout provided in nanoseconds.
>
> aperiodic mode
> --------------
> timeout = 100000000; // 1 ms
> ...
> rt_sem_p(&sem, timeout);
>
> periodic mode
> -------------
> timeout = 100000000; // 1 ms
> ...
> rt_sem_p(&sem, rt_timer_ns2ticks(timeout));
>
> Now you have two different code fragments serving the same purpose, only
> performing under different timer modes. No big problem for the
> application that knows how it configured the timer, but anything at
> lower levels always has to check for the current mode.
Changing this is in on the todo-list... Ok, it was probably
forgotten. But this inconsistency is in no way related to the problem of
choosing nanoseconds, TSCs, or anything else, as a unit for the nucleus
to keep its internal timings, since it would be possible to have
rt_timer_ns2ticks call xnpod_ns2ticks internally, which would return its
argument as result when called in aperiodic mode, and the nucleus could
continue using nanoseconds as its internal unit in aperiodic mode.
> I do not understand yet the portability problem of TSC values, but the
> inconsistency issue on SMP systems was new to me and make your choice a
> bit more comprehensible. Does moving to nanoseconds really solve the
> problem? The clocks used in aperiodic mode will not run synchronised nor
> will they be started at (almost) the same time, will they? So, all
> absolute times (taken on CPU A and applied on CPU B) might still be
> inconsistent.
Good point ! However, there is only function in nucleus' timer.c which
might enqueue a timer on a different CPU than the one it is currently
running on, it is the function "xntimer_set_sched", this was part of the
work on "per-cpu timers".
> > What would such tick represent in aperiodic mode, time-wise?
>
> For me, ticks are what the system timer uses internally in the
> respective mode: TSCs?! Then it becomes more understandable to the
> developer that one always has to convert human-processable time to
> internal units.
Note that TSCs are only useful as a native unit for... busy waiting, since
timer clocks have frequencies different from the CPU. So, there is no
difference between choosing TSCs and nanoseconds.
> Well, I just read through xntimer_do_timers again and I remembered it
> correctly: you don't actually make use of nanoseconds as tick
> abstraction in aperiodic mode. Otherwise, you should store all timer
> dates as nanoseconds and convert the current time to ns before starting
> to compare it with the pending timers. This way it is now should not
> provide any advantage on SMP boxes, should it?
xntimer_do_timers either is called on only one CPU, if the "per-cpu
timers" are not activated, and handles all the timers (which results in
xnpod_schedule generating IPIs to wake-up tasks on another CPU), or is
called on each CPU to handle the timers of this CPU if the "per-cpu
timers" are activated.
In either case, xntimer_do_timers may safely assume that every timer it
handles is using the same unit. Again, the only place where timer may
change of CPU is xntimer_set_sched.
--
Gilles Chanteperdrix.