gettimeofday() is small enough that a couple of extra cycles DOES show
up. And, as cpus get faster and faster WRT the front-side bus, this
can easily be the majority of the time it takes to do gettimeofday().
> In fact, they make sure that subsequent
> reads will always return positive time. It's just a bias in the
> time that affects everybody the same way. What hurts is trying to
> synchronize to some external clock. In my opinion, this is not
> the correct way to get the time. `rdtsc` returns a long long
> in two registers. This should be saved as "reference time"
> every time the system clock is set. Setting the system clock
> means saving (only) the time_t object, in seconds, at the
> time one saves the rdtsc time. This time_t object is never
> changed otherwise. The PIT only generates interrupts. It is
> not used for time. When somebody needs the time, it is calculated
> from the present `rdtsc`, the saved long long value, and the
> time_t time at which that value was saved. This guarantees
> that all time is positive and no CPU cycles are wasted trying
> to read anything.
>
> The number of CPU cycles per second are calculated once upon
> startup just as they are now. If you shut-down, or slow the
> CPU for power-saving, you just recalculate the CPU cycles
> and reset the time from CMOS. Any time, when the machine is
> in 'slow' mode is still correct.
I did something close to this in the high-res-timers patch. There are
several problems WRT TSC:
First, and the reason this thread started, there are SMP boxes with pm
code that causes the TSC to run at different speeds on the various cpus.
Second, I am lead to believe that there are boxes that adjust the cpu
speed with out telling software about it.
Third, there are boxes that just don't have TSCs, (yeah, I know they
are old...).
Because of all of this, I have a configure option to use the ACPI pm
counter. The down side of this is a) it is slow (an I/O instruction)
and b.) the resolution is much less than the TSC.
>
> time_t set_time;
> long long cpu_cycles_sec;
> long long rd_tsc_at_set_time;
>
> To read time:
>
> current_time = ((rdtsc() - rd_tsc_at_set_time)/ cpu_cycles_sec) +
> set_time;
>
> To set time:
>
> set_time = get_time_from_CMOS();
> rd_tsc_at_set_time = rdtsc();
>
> ... That's all you need.
In my code, since the time needs to be "fresh" each tick, I keep a
counter up to date each tick. This allows me to speed up the code by
only reading the low half of the TSC, and at the same time, avoid some
64-bit math.
The other thing this way of doing things needs is code to discipline
the interrupt source (the PIT in this case) so that the interrupts
come "reasonably" close to the 1/Hz boundary. Without this the timers
have too much jitter.
-- George Anzinger george@mvista.com High-res-timers: http://sourceforge.net/projects/high-res-timers/ Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/