Re: 'Detected 19943xxx Hz processor'-fluctuations...

Florian Weimer (fw@cygnus.stuttgart.netsurf.de)
14 Jan 1999 17:58:21 +0100


Robert Woodcock <rcw@debian.org> writes:

> > Aren't you trying to measure the precision of a clock with the same
> > clock?
>
> No wonder it was working so well :>
>
> Anyone wanna fill me in on how well it works with a kernel compiled to
> use do_slow_gettimeoffset?

Here's something new to play with. The program gives the correct
processor frequency most of the time, but some values are awefully wrong
(about 40 or 400 MHz for a PII/266MHz...).

Of course, the questions still is whether the program really measures
clocks per RTC interrupt (and nothing else is disturbing the results).

/*
* Comparision of Pentium TSC and RTC.
*
* Copyright (c) 1999 by Florian Weimer.
* Based on Paul Gortmaker's /dev/rtc example program.
*
* Released under the GNU General Public License, version 2.
*
* Compile with: gcc -O2 -Wall tsc-rtc.c -o tsc-rtc
* Invoke with: tsc-rtc frequency
* For example: tsc-rtc 16
* means 16 measurements per second
* Frequency should a power of two between 1 and 64.
* Higher powers of two are possible, but require superuser privileges.
* The program perpetually prints approximations of the processors
* clock frequency. Requires RDTSC instruction and /dev/rtc kernel
* support. Doesn't work with SMP, of course.
*
*/

#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>

#include <linux/mc146818rtc.h>

typedef unsigned long long int tsc_t;
extern __inline__ tsc_t rdtsc(void)
{
tsc_t x;
__asm__ volatile ("rdtsc"
: "=A" (x));
return x;
}

int main(int argc, char ** argv)
{
int fd, retval, first;
unsigned int freq;
tsc_t old_tsc = 0;

if (argc != 2) {
fprintf(stderr, "usage: %s frequency\n", argv[0]);
exit(EINVAL);
}

freq = atoi(argv[1]);

fd = open ("/dev/rtc", O_RDONLY);

if (fd == -1) {
perror("open(\"/dev/rtc\")");
exit(errno);
}


/* Turn off update interrupts */
retval = ioctl(fd, RTC_UIE_OFF, 0);
if (retval == -1) {
perror("ioctl(RTC_UIE_OFF)");
exit(errno);
}

/* Set periodic interrupt frequency */
retval = ioctl(fd, RTC_IRQP_SET, freq);
if (retval == -1) {
perror("ioctl(RTC_IRQP_SET");
exit(errno);
}

/* Enable periodic interrupts */
retval = ioctl(fd, RTC_PIE_ON, 0);
if (retval == -1) {
perror("ioctl(RTC_PIE_ON)");
exit(errno);
}

first = 1;
while (1) {
tsc_t new_tsc;
unsigned int count;

/* This blocks */
retval = read(fd, &count, sizeof(count));
if (retval == -1) {
perror("read(\"/dev/rtc\")");
exit(errno);
}

new_tsc = rdtsc();
count >>= 8; /* Calculate IRQ count */

if (!first) {
int diff;
diff = ((unsigned)new_tsc - (unsigned)old_tsc);
/* First divide, then multiply to avoid overflow. */
printf("%d\n", (diff / count) * freq);
} else {
first = 0;
}
old_tsc = new_tsc;
}

return 0;
}

-
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/