1*cdfa2a7eSchristos /* $NetBSD: hist.c,v 1.5 2020/05/25 20:47:37 christos Exp $ */
2abb0f93cSkardel
3abb0f93cSkardel /*
4abb0f93cSkardel * This program can be used to calibrate the clock reading jitter of a
5abb0f93cSkardel * particular CPU and operating system. It first tickles every element
6abb0f93cSkardel * of an array, in order to force pages into memory, then repeatedly calls
7abb0f93cSkardel * gettimeofday() and, finally, writes out the time values for later
8abb0f93cSkardel * analysis. From this you can determine the jitter and if the clock ever
9abb0f93cSkardel * runs backwards.
10abb0f93cSkardel */
11abb0f93cSkardel
12abb0f93cSkardel #ifdef HAVE_CONFIG_H
13abb0f93cSkardel # include <config.h>
14abb0f93cSkardel #endif
15abb0f93cSkardel
16abb0f93cSkardel #include "ntp_types.h"
17abb0f93cSkardel
18abb0f93cSkardel #include <stdio.h>
19abb0f93cSkardel #include <stdlib.h>
20abb0f93cSkardel
21abb0f93cSkardel #define NBUF 100001 /* size of basic histogram */
22abb0f93cSkardel #define NSRT 20000 /* size of overflow histogram */
23abb0f93cSkardel #define NCNT (600 * 1000000) /* sample interval (us) */
24abb0f93cSkardel
258585484eSchristos int col (const void *, const void *);
26abb0f93cSkardel
27abb0f93cSkardel int
main(int argc,char * argv[])28abb0f93cSkardel main(
29abb0f93cSkardel int argc,
30abb0f93cSkardel char *argv[]
31abb0f93cSkardel )
32abb0f93cSkardel {
33abb0f93cSkardel struct timeval ts, tr, tp;
34abb0f93cSkardel struct timezone tzp;
35abb0f93cSkardel int i, j, n;
36abb0f93cSkardel long t, u, v, w, gtod[NBUF], ovfl[NSRT];
37abb0f93cSkardel
38abb0f93cSkardel /*
39abb0f93cSkardel * Force pages into memory
40abb0f93cSkardel */
41abb0f93cSkardel for (i = 0; i < NBUF; i++)
42abb0f93cSkardel gtod[i] = 0;
43abb0f93cSkardel for (i = 0; i < NSRT; i++)
44abb0f93cSkardel ovfl[i] = 0;
45abb0f93cSkardel
46abb0f93cSkardel /*
47abb0f93cSkardel * Construct histogram
48abb0f93cSkardel */
49abb0f93cSkardel n = 0;
50abb0f93cSkardel gettimeofday(&ts, &tzp);
51abb0f93cSkardel t = ts.tv_sec * 1000000 + ts.tv_usec;
52abb0f93cSkardel v = t;
53abb0f93cSkardel while (1) {
54abb0f93cSkardel gettimeofday(&tr, &tzp);
55abb0f93cSkardel u = tr.tv_sec * 1000000 + tr.tv_usec;
56abb0f93cSkardel if (u - v > NCNT)
57abb0f93cSkardel break;
58abb0f93cSkardel w = u - t;
59abb0f93cSkardel if (w <= 0) {
60abb0f93cSkardel /*
61abb0f93cSkardel printf("error <= 0 %ld %d %d, %d %d\n", w, ts.tv_sec,
62abb0f93cSkardel ts.tv_usec, tr.tv_sec, tr.tv_usec);
63abb0f93cSkardel */
64abb0f93cSkardel } else if (w > NBUF - 1) {
65abb0f93cSkardel ovfl[n] = w;
66abb0f93cSkardel if (n < NSRT - 1)
67abb0f93cSkardel n++;
68abb0f93cSkardel } else {
69abb0f93cSkardel gtod[w]++;
70abb0f93cSkardel }
71abb0f93cSkardel ts = tr;
72abb0f93cSkardel t = u;
73abb0f93cSkardel }
74abb0f93cSkardel
75abb0f93cSkardel /*
76abb0f93cSkardel * Write out histogram
77abb0f93cSkardel */
78abb0f93cSkardel for (i = 0; i < NBUF - 1; i++) {
79abb0f93cSkardel if (gtod[i] > 0)
80abb0f93cSkardel printf("%ld %ld\n", i, gtod[i]);
81abb0f93cSkardel }
82abb0f93cSkardel if (n == 0)
83abb0f93cSkardel return;
848585484eSchristos qsort(&ovfl, (size_t)n, sizeof(ovfl[0]), col);
85abb0f93cSkardel w = 0;
86abb0f93cSkardel j = 0;
87abb0f93cSkardel for (i = 0; i < n; i++) {
88abb0f93cSkardel if (ovfl[i] != w) {
89abb0f93cSkardel if (j > 0)
90abb0f93cSkardel printf("%ld %ld\n", w, j);
91abb0f93cSkardel w = ovfl[i];
92abb0f93cSkardel j = 1;
93abb0f93cSkardel } else
94abb0f93cSkardel j++;
95abb0f93cSkardel }
96abb0f93cSkardel if (j > 0)
97abb0f93cSkardel printf("%ld %ld\n", w, j);
98abb0f93cSkardel
99abb0f93cSkardel exit(0);
100abb0f93cSkardel }
101abb0f93cSkardel
102abb0f93cSkardel int
col(const void * vx,const void * vy)103abb0f93cSkardel col(
1048585484eSchristos const void *vx,
1058585484eSchristos const void *vy
106abb0f93cSkardel )
107abb0f93cSkardel {
1088585484eSchristos const long *x = vx;
1098585484eSchristos const long *y = vy;
1108585484eSchristos
111abb0f93cSkardel return (*x - *y);
112abb0f93cSkardel }
113