1ef64b99roberto/*
2ef64b99roberto * This program can be used to calibrate the clock reading jitter of a
3ef64b99roberto * particular CPU and operating system. It first tickles every element
4ef64b99roberto * of an array, in order to force pages into memory, then repeatedly calls
5ef64b99roberto * gettimeofday() and, finally, writes out the time values for later
6ef64b99roberto * analysis. From this you can determine the jitter and if the clock ever
7ef64b99roberto * runs backwards.
8ef64b99roberto */
9ef64b99roberto
10ef64b99roberto#ifdef HAVE_CONFIG_H
1140b8e41roberto# include <config.h>
12ef64b99roberto#endif
13ef64b99roberto
14ef64b99roberto#include "ntp_types.h"
15ef64b99roberto
1640b8e41roberto#include <stdio.h>
1740b8e41roberto#include <stdlib.h>
1840b8e41roberto
19ef64b99roberto#define NBUF 100001		/* size of basic histogram */
20ef64b99roberto#define NSRT 20000		/* size of overflow histogram */
21ef64b99roberto#define NCNT (600 * 1000000)	/* sample interval (us) */
22ef64b99roberto
23047f369cyint col (const void *, const void *);
24ef64b99roberto
25ef64b99robertoint
26ef64b99robertomain(
27ef64b99roberto	int argc,
28ef64b99roberto	char *argv[]
29ef64b99roberto	)
30ef64b99roberto{
317a6072eroberto	struct timeval ts, tr, tp;
327a6072eroberto	struct timezone tzp;
33ef64b99roberto	int i, j, n;
347a6072eroberto	long t, u, v, w, gtod[NBUF], ovfl[NSRT];
35ef64b99roberto
36ef64b99roberto	/*
37ef64b99roberto	 * Force pages into memory
38ef64b99roberto	 */
39ef64b99roberto	for (i = 0; i < NBUF; i++)
40047f369cy		gtod[i] = 0;
41ef64b99roberto	for (i = 0; i < NSRT; i++)
42047f369cy		ovfl[i] = 0;
43ef64b99roberto
44ef64b99roberto	/*
45ef64b99roberto	 * Construct histogram
46ef64b99roberto	 */
47ef64b99roberto	n = 0;
487a6072eroberto	gettimeofday(&ts, &tzp);
497a6072eroberto	t = ts.tv_sec * 1000000 + ts.tv_usec;
50ef64b99roberto	v = t;
51ef64b99roberto	while (1) {
527a6072eroberto		gettimeofday(&tr, &tzp);
537a6072eroberto		u = tr.tv_sec * 1000000 + tr.tv_usec;
54ef64b99roberto		if (u - v > NCNT)
55047f369cy			break;
56ef64b99roberto		w = u - t;
57ef64b99roberto		if (w <= 0) {
58ef64b99roberto/*
59ef64b99roberto			printf("error <= 0 %ld %d %d, %d %d\n", w, ts.tv_sec,
60ef64b99roberto			       ts.tv_usec, tr.tv_sec, tr.tv_usec);
61ef64b99roberto*/
62ef64b99roberto		} else if (w > NBUF - 1) {
63ef64b99roberto			ovfl[n] = w;
64ef64b99roberto			if (n < NSRT - 1)
65047f369cy				n++;
66ef64b99roberto		} else {
67ef64b99roberto			gtod[w]++;
68ef64b99roberto		}
697a6072eroberto		ts = tr;
70ef64b99roberto		t = u;
71ef64b99roberto	}
72ef64b99roberto
73ef64b99roberto	/*
74ef64b99roberto	 * Write out histogram
75ef64b99roberto	 */
76ef64b99roberto	for (i = 0; i < NBUF - 1; i++) {
77ef64b99roberto		if (gtod[i] > 0)
78047f369cy			printf("%ld %ld\n", i, gtod[i]);
79ef64b99roberto	}
80ef64b99roberto	if (n == 0)
81047f369cy		return;
82047f369cy	qsort(&ovfl, (size_t)n, sizeof(ovfl[0]), col);
83ef64b99roberto	w = 0;
84ef64b99roberto	j = 0;
85ef64b99roberto	for (i = 0; i < n; i++) {
86ef64b99roberto		if (ovfl[i] != w) {
87ef64b99roberto			if (j > 0)
88047f369cy				printf("%ld %ld\n", w, j);
89ef64b99roberto			w = ovfl[i];
90ef64b99roberto			j = 1;
91ef64b99roberto		} else
92047f369cy			j++;
93ef64b99roberto	}
94ef64b99roberto	if (j > 0)
95047f369cy		printf("%ld %ld\n", w, j);
96ef64b99roberto
97ef64b99roberto	exit(0);
98ef64b99roberto}
99ef64b99roberto
100ef64b99robertoint
101ef64b99robertocol(
102047f369cy	const void *vx,
103047f369cy	const void *vy
104ef64b99roberto	)
105ef64b99roberto{
106047f369cy	const long *x = vx;
107047f369cy	const long *y = vy;
108047f369cy
109ef64b99roberto	return (*x - *y);
110ef64b99roberto}
111