154359Sroberto/* 254359Sroberto * This program can be used to calibrate the clock reading jitter of a 354359Sroberto * particular CPU and operating system. It first tickles every element 454359Sroberto * of an array, in order to force pages into memory, then repeatedly calls 554359Sroberto * gettimeofday() and, finally, writes out the time values for later 654359Sroberto * analysis. From this you can determine the jitter and if the clock ever 754359Sroberto * runs backwards. 854359Sroberto */ 954359Sroberto 1054359Sroberto#ifdef HAVE_CONFIG_H 1182498Sroberto# include <config.h> 1254359Sroberto#endif 1382498Sroberto 1482498Sroberto#include "ntp_types.h" 1582498Sroberto 1654359Sroberto#include <stdio.h> 1754359Sroberto#include <stdlib.h> 1854359Sroberto 1954359Sroberto#define NBUF 100001 /* size of basic histogram */ 2054359Sroberto#define NSRT 20000 /* size of overflow histogram */ 2154359Sroberto#define NCNT (600 * 1000000) /* sample interval (us) */ 2254359Sroberto 23290001Sglebiusint col (const void *, const void *); 2454359Sroberto 2554359Srobertoint 2654359Srobertomain( 2754359Sroberto int argc, 2854359Sroberto char *argv[] 2954359Sroberto ) 3054359Sroberto{ 31182007Sroberto struct timeval ts, tr, tp; 32182007Sroberto struct timezone tzp; 3354359Sroberto int i, j, n; 34182007Sroberto long t, u, v, w, gtod[NBUF], ovfl[NSRT]; 3554359Sroberto 3654359Sroberto /* 3754359Sroberto * Force pages into memory 3854359Sroberto */ 3954359Sroberto for (i = 0; i < NBUF; i++) 40290001Sglebius gtod[i] = 0; 4154359Sroberto for (i = 0; i < NSRT; i++) 42290001Sglebius ovfl[i] = 0; 4354359Sroberto 4454359Sroberto /* 4554359Sroberto * Construct histogram 4654359Sroberto */ 4754359Sroberto n = 0; 48182007Sroberto gettimeofday(&ts, &tzp); 49182007Sroberto t = ts.tv_sec * 1000000 + ts.tv_usec; 5054359Sroberto v = t; 5154359Sroberto while (1) { 52182007Sroberto gettimeofday(&tr, &tzp); 53182007Sroberto u = tr.tv_sec * 1000000 + tr.tv_usec; 5454359Sroberto if (u - v > NCNT) 55290001Sglebius break; 5654359Sroberto w = u - t; 5754359Sroberto if (w <= 0) { 5854359Sroberto/* 5954359Sroberto printf("error <= 0 %ld %d %d, %d %d\n", w, ts.tv_sec, 6054359Sroberto ts.tv_usec, tr.tv_sec, tr.tv_usec); 6154359Sroberto*/ 6254359Sroberto } else if (w > NBUF - 1) { 6354359Sroberto ovfl[n] = w; 6454359Sroberto if (n < NSRT - 1) 65290001Sglebius n++; 6654359Sroberto } else { 6754359Sroberto gtod[w]++; 6854359Sroberto } 69182007Sroberto ts = tr; 7054359Sroberto t = u; 7154359Sroberto } 7254359Sroberto 7354359Sroberto /* 7454359Sroberto * Write out histogram 7554359Sroberto */ 7654359Sroberto for (i = 0; i < NBUF - 1; i++) { 7754359Sroberto if (gtod[i] > 0) 78290001Sglebius printf("%ld %ld\n", i, gtod[i]); 7954359Sroberto } 8054359Sroberto if (n == 0) 81290001Sglebius return; 82290001Sglebius qsort(&ovfl, (size_t)n, sizeof(ovfl[0]), col); 8354359Sroberto w = 0; 8454359Sroberto j = 0; 8554359Sroberto for (i = 0; i < n; i++) { 8654359Sroberto if (ovfl[i] != w) { 8754359Sroberto if (j > 0) 88290001Sglebius printf("%ld %ld\n", w, j); 8954359Sroberto w = ovfl[i]; 9054359Sroberto j = 1; 9154359Sroberto } else 92290001Sglebius j++; 9354359Sroberto } 9454359Sroberto if (j > 0) 95290001Sglebius printf("%ld %ld\n", w, j); 9654359Sroberto 9754359Sroberto exit(0); 9854359Sroberto} 9954359Sroberto 10054359Srobertoint 10154359Srobertocol( 102290001Sglebius const void *vx, 103290001Sglebius const void *vy 10454359Sroberto ) 10554359Sroberto{ 106290001Sglebius const long *x = vx; 107290001Sglebius const long *y = vy; 108290001Sglebius 10954359Sroberto return (*x - *y); 11054359Sroberto} 111