Re: How do i read the clock cycle counter?

Richard Jones (rjones@orchestream.com)
Tue, 28 Apr 1998 10:58:13 +0000


This is a multi-part message in MIME format.
--------------75C45FF35294E2429CADDE5E
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

Paul Flinders wrote:
>
> Thomas Jensen <kauf@cs.auc.dk> writes:
>
> > Hi!
> >
> > I'm using Linux RedHat 5.0 (Kernel 2.0.33), and i have to do some time
> > measurements. How do i read the clock cycle counter register in a
> > pentium / Pentium II CPU ??
> unsigned int count[2];
> asm("rdtsc"
> :"=a" (count[0]),
> "=d" (count[1]));

You can in fact use "=&A" to read the 64 bit integer in one go.

Take a look at the following C++ program which calibrates
the TSC. Gives me about 6 significant figures accuracy each
time I run it ...

Rich.

-- 
Richard Jones rjones@orchestream.com Tel: +44 171 598 7557 Fax: 460 4461
Orchestream Ltd.  125 Old Brompton Rd. London SW7 3RP PGP: www.four11.com
"boredom ... one of the most overrated emotions ... the sky is made
of bubbles ..."   Original message content Copyright © 1998
--------------75C45FF35294E2429CADDE5E
Content-Type: text/plain; charset=us-ascii; name="calibrate-tsc.cc"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="calibrate-tsc.cc"

// -*- C++ -*- // // CALIBRATE-TSC Copyright (C) 1998 Richard W.M. Jones <rjones@imcl.com> // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, // USA.

// Compile with: // g++ -Wall -O2 -o calibrate-tsc calibrate-tsc.cc // Tested with EGCS 1.0.2

#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/time.h> #include <unistd.h> #include <iostream.h>

// Read the Pentium TSC. static inline u_int64_t rdtsc () { u_int64_t d; // Instruction is volatile because we don't want it to move // over an adjacent gettimeofday. That would ruin the timing // calibrations. __asm__ __volatile__ ("rdtsc" : "=&A" (d)); return d; }

// Compute 64 bit value / timeval (treated as a real). static inline u_int64_t operator / (u_int64_t v, timeval t) { return u_int64_t (v / (double (t.tv_sec) + double (t.tv_usec) / 1000000.)); }

// Compute left - right for timeval structures. static inline timeval operator - (const timeval &left, const timeval &right) { u_int64_t left_us = (u_int64_t) left.tv_sec * 1000000 + left.tv_usec; u_int64_t right_us = (u_int64_t) right.tv_sec * 1000000 + right.tv_usec; u_int64_t diff_us = left_us - right_us; timeval r = { diff_us / 1000000, diff_us % 1000000 }; return r; }

// Compute the positive difference between two 64 bit numbers. static inline u_int64_t diff (u_int64_t v1, u_int64_t v2) { int64_t d = v1 - v2; if (d >= 0) return d; else return -d; }

int main (int argc, char *argv []) { // Compute the period. Loop until we get 3 consecutive periods that // are the same to within a small error. The error is chosen // to be +/- 1% on a P-200. const u_int64_t error = 2000000; const int max_iterations = 20; int count; u_int64_t period, period1 = error * 2, period2 = 0, period3 = 0; for (count = 0; count < max_iterations; count++) { timeval start_time, end_time; u_int64_t start_tsc, end_tsc;

gettimeofday (&start_time, 0); start_tsc = rdtsc (); sleep (1); gettimeofday (&end_time, 0); end_tsc = rdtsc ();

period3 = (end_tsc - start_tsc) / (end_time - start_time);

if (diff (period1, period2) <= error && diff (period2, period3) <= error && diff (period1, period3) <= error) break;

period1 = period2; period2 = period3; } if (count == max_iterations) { cerr << "calibrate-tsc: gettimeofday or Pentium TSC not stable\n" << " enough for accurate timing.\n"; exit (1); }

// Set the period to the average period measured. period = (period1 + period2 + period3) / 3;

// Some Pentiums have broken TSCs that increment very // slowly or unevenly. My P-133, for example, has a TSC // that appears to increment at ~20kHz. if (period < 10000000) { cerr << "calibrate-tsc: Pentium TSC seems to be broken on this CPU.\n"; exit (1); }

cout << "Calibrated Pentium timestamp counter: " << period << " Hz\n"; }

--------------75C45FF35294E2429CADDE5E--

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu