do_fast_gettimeoffset(void) buggy?

Ulrich Windl (Ulrich.Windl@rz.uni-regensburg.de)
Fri, 26 Apr 1996 08:15:25 +0200


Hello,

I have a question about the routine below. The routine is a Pentium
specific microtime() routine. I'm afraid it is not correct. See my
"???" tag at the beginning of a line. If someone can tell me, if I'm
wrong, I'd like to hear it!

/*
* linux/arch/i386/kernel/time.c
*
* Copyright (C) 1991, 1992, 1995 Linus Torvalds
...
/* Cycle counter value at the previous timer interrupt.. */
static unsigned long long last_timer_cc = 0;
static unsigned long long init_timer_cc = 0;

static unsigned long do_fast_gettimeoffset(void)
{
unsigned long time_low, time_high;
unsigned long quotient, remainder;

/* Get last timer tick in absolute kernel time */
__asm__("subl %2,%0\n\t"
"sbbl %3,%1"
:"=r" (time_low), "=r" (time_high)
:"m" (*(0+(long *)&init_timer_cc)),
"m" (*(1+(long *)&init_timer_cc)),
"0" (*(0+(long *)&last_timer_cc)),
"1" (*(1+(long *)&last_timer_cc)));
/*
* Divide the 64-bit time with the 32-bit jiffy counter,
* getting the quotient in clocks.
*
* Giving quotient = "average internal clocks per jiffy"
*/
__asm__("divl %2"
:"=a" (quotient), "=d" (remainder)
:"r" (jiffies),
"0" (time_low), "1" (time_high));

/* Read the time counter */
__asm__(".byte 0x0f,0x31"
:"=a" (time_low), "=d" (time_high));

/* .. relative to previous jiffy (32 bits is enough) */
time_low -= (unsigned long) last_timer_cc;
??? We have two 64 bit quantities, and we are interested in the least
??? significant 32 bit. Currently just the "low longwords" are
??? subtracted, yielding a possible overflow (result in unsigned).
??? Usually you would need some carry processing.

/*
* Time offset = (1000000/HZ * remainder) / quotient.
*/
__asm__("mull %1\n\t"
"divl %2"
:"=a" (quotient), "=d" (remainder)
:"r" (quotient),
"0" (time_low), "1" (1000000/HZ));

/*
* Due to rounding errors (and jiffies inconsistencies),
* we need to check the result so that we'll get a timer
* that is monotonous.
*/
if (quotient >= 1000000/HZ)
quotient = 1000000/HZ-1;

??? Is this the correction for the missed carry?

return quotient;
}
#endif