HZ跟CPU频率没关系,HZ,The frequency of the system timer (the tick rate) is programmed on system boot based on a static preprocessor define,HZ.每秒发中断次数timer interrupt (IRQ 0)次数。
Tick, 1/HZ, HZ=100时,tick=10ms
Jiffies,开机以来每次tick,++Jiffies
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <asm/param.h>
#include <time.h>
#define USECREQ 250
#define LOOPS 1000
void event_handler (int signum)
{
static unsigned long cnt = 0;
static struct timeval tsFirst;
if (cnt == 0) {
gettimeofday (&tsFirst, 0);
}
cnt ++;
if (cnt >= LOOPS) {
struct timeval tsNow;
struct timeval diff;
setitimer (ITIMER_REAL, NULL, NULL);
gettimeofday (&tsNow, 0);
timersub(&tsNow, &tsFirst, &diff);
unsigned long long udiff = (diff.tv_sec * 1000000) + diff.tv_usec;
double delta = (double)(udiff/cnt)/1000000;
int hz = (unsigned)(1.0/delta);
printf ("kernel timer interrupt frequency is approx. %d Hz", hz);
if (hz >= (int) (1.0/((double)(USECREQ)/1000000))) {
printf (" or higher");
}
printf ("\n");
exit (0);
}
}
int main (int argc, char **argv)
{
printf("%d\n", HZ);
struct timespec res;
double resolution;
printf("UserHZ %ld\n", sysconf(_SC_CLK_TCK));
clock_getres(CLOCK_REALTIME, &res);
resolution = res.tv_sec + (((double)res.tv_nsec)/1.0e9);
printf("SystemHZ %ld\n", (unsigned long)(1/resolution + 0.5));
struct sigaction sa;
struct itimerval timer;
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &event_handler;
sigaction (SIGALRM, &sa, NULL);
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = USECREQ;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = USECREQ;
setitimer (ITIMER_REAL, &timer, NULL);
while (1);
}
g++ -lrt test.cc
centos64,,2.6.32-358.el6.x86_64
100
UserHZ 100
SystemHZ 1000000000
kernel timer interrupt frequency is approx. 4016 Hz or higher
redhat54 2.6.18-164.el5 x86_64
100
UserHZ 100
SystemHZ 1000
kernel timer interrupt frequency is approx. 1002 Hz
grep TSC /var/log/messages
Dec 30 13:59:10 vdc06 kernel: Fast TSC calibration using PIT
Dec 30 13:59:10 vdc06 kernel: Refined TSC clocksource calibration: 1999.999 MHz.
grep clock /var/log/messages
Dec 30 13:59:10 vdc06 kernel: Switching to clocksource hpet
Dec 30 13:59:10 vdc06 kernel: rtc_cmos 00:04: setting system clock to 2013-12-30 05:58:59 UTC (1388383139)
Dec 30 13:59:10 vdc06 kernel: Refined TSC clocksource calibration: 1999.999 MHz.
Dec 30 13:59:10 vdc06 kernel: Switching to clocksource tsc
Dec 30 13:59:10 vdc06 kernel: PTP clock support registered
TSC定时器使用
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
static unsigned cyc_hi = 0;
static unsigned cyc_lo = 0;
void access_counter(unsigned *hi, unsigned *lo)
{
asm("rdtsc; movl %%edx, %0; movl %%eax, %1"
: "=r" (*hi), "=r" (*lo)
: /* No input */
: "%edx", "%eax");
return;
}
void start_counter(void)
{
access_counter(&cyc_hi, &cyc_lo);
return;
}
double get_counter(void)
{
unsigned int ncyc_hi, ncyc_lo;
unsigned int hi, lo, borrow;
double result;
/* Get cycle counter */
access_counter(&ncyc_hi, &ncyc_lo);
/* Do double precision subtraction */
lo = ncyc_lo - cyc_lo;
borrow = lo > ncyc_lo;
hi = ncyc_hi - cyc_hi - borrow;
result = (double)hi * (1 << 30) * 4 + lo;
if (result < 0) {
printf("Error: counter returns neg value: %.0f\n", result);
}
return result;
}
int main()
{
start_counter();
sleep(2);
double cnt = get_counter();
printf("counter = %lf.\n",cnt);
}
counter = 4000216988.000000