Re: gettimeofday & high-res timers

Bruce Elliott (bde@nwlink.com)
Wed, 24 Feb 1999 01:42:45 -0800


On Feb 24, 11:00am, Tom Holroyd wrote:
} Subject: Re: gettimeofday & high-res timers
} On Tue, 23 Feb 1999, Vojtech Pavlik wrote:
}
} Hmm. On my AlphaPC164LX running 2.2.1 with /dev/rtc enabled, the timetest
} program produces deltas of -4088 or so every second! Very sawtooth.

You probably need the missing second half of a patch I submitted, but
missed the 2.2 cutoff.

> From: Bruce Elliott <bde@nwlink.com>
> Message-Id: <199901110550.VAA01240@mail.nwlink.com>
> Date: Sun, 10 Jan 1999 21:47:53 -0800
> X-Mailer: Mail User's Shell (7.2.5 10/14/92)
> To: linux-kernel@vger.rutgers.edu
> Subject: Re: Problems in ALPHA Timekeeping
> Cc: torvalds@transmeta.com
> Sender: owner-linux-kernel@vger.rutgers.edu
> Precedence: bulk
> X-Loop: majordomo@vger.rutgers.edu
> X-Orcpt: rfc822;linux-kernel-outgoing-dig
> X-UIDL: 1447633ab1bad139c20ce340083a192d
> Status: OR
>
> (This probably doesn't have a very high priority, as I have received zero
> comments on the first patch. The timekeeping does work much better with
> this however.)
>
> My previous patch to arch/alpha/time.c was somewhat incomplete.
>
> timer_interrupt() logic did some updating even when no tick had passed.
>
> do_gettimeofday() didn't account for the unused partial tick.
>
> do_settimeofday() didn't handle any of this.
>
> Making this work properly with SMP will require more changes.

======
--- linux.rels/arch/alpha/kernel/time.c Sun Dec 27 15:21:50 1998
+++ linux/arch/alpha/kernel/time.c Tue Dec 29 20:45:41 1998
@@ -93,14 +98,17 @@
/*
* Calculate how many ticks have passed since the last update,
* including any previous partial leftover. Save any resulting
- * fraction for the next pass.
+ * fraction for the next pass. Don't change anything unless
+ * at least one tick has passed.
*/
now = rpcc();
delta = now - state.last_time;
- state.last_time = now;
delta = delta * state.scaled_ticks_per_cycle + state.partial_tick;
- state.partial_tick = delta & ((1UL << FIX_SHIFT) - 1);
nticks = delta >> FIX_SHIFT;
+ if (nticks) {
+ state.last_time = now;
+ state.partial_tick = delta & ((1UL << FIX_SHIFT) - 1);
+ }

while (nticks > 0) {
do_timer(regs);
@@ -339,12 +378,14 @@
{
unsigned long flags, now, delta_cycles, delta_usec;
unsigned long sec, usec;
+ unsigned long partial_tick;

- now = rpcc();
save_and_cli(flags);
+ now = rpcc();
sec = xtime.tv_sec;
usec = xtime.tv_usec;
delta_cycles = now - state.last_time;
+ partial_tick = state.partial_tick;
restore_flags(flags);

/*
@@ -360,7 +401,8 @@
* with no clear gain.
*/

- delta_usec = delta_cycles * state.scaled_ticks_per_cycle * 15625;
+ delta_usec = delta_cycles * state.scaled_ticks_per_cycle + partial_tick;
+ delta_usec *= 15625;
delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;

usec += delta_usec;
@@ -376,8 +418,24 @@
void
do_settimeofday(struct timeval *tv)
{
+ unsigned long delta_usec;
+
+ /*
+ * The offset that is added into time in do_gettimeofday above must
+ * be subtracted here to keep a coherent view of the time. Without
+ * this, a full-tick error is possible.
+ */
cli();
+ delta_usec = (rpcc() - state.last_time) * state.scaled_ticks_per_cycle +
+ state.partial_tick;
+ delta_usec *= 15625;
+ delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;
xtime = *tv;
+ xtime.tv_usec -= delta_usec;
+ if (xtime.tv_usec < 0) {
+ xtime.tv_usec += 1000000;
+ xtime.tv_sec--;
+ }
time_state = TIME_BAD;
time_maxerror = 0x70000000;
time_esterror = 0x70000000;
======

-- 
B. D. Elliott   bde@nwlink.com   (Seattle)

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/