1: /*
2: * This program can be used to calibrate the clock reading jitter of a
3: * particular CPU and operating system. It first tickles every element
4: * of an array, in order to force pages into memory, then repeatedly
5: * reads the system clock and, finally, writes out the time values for
6: * later analysis. From this you can determine the jitter and if the
7: * clock ever runs backwards.
8: */
9:
10: #ifdef HAVE_CONFIG_H
11: # include <config.h>
12: #endif
13:
14: #include <stdio.h>
15: #include <sys/time.h>
16: #include <stdlib.h>
17: #include "jitter.h"
18:
19: #define NBUF 800002
20: #define FRAC 4294967296. /* a bbbbillion */
21: #define JAN_1970 2208988800UL /* Unix base epoch */
22: #define CLOCK_GETTIME /* Solaris hires clock */
23:
24: int debug;
25: char progname[10];
26: double sys_residual;
27: double average;
28: void sys_gettime(l_fp *);
29:
30: int
31: main(
32: int argc,
33: char *argv[]
34: )
35: {
36: l_fp tr;
37: int i, j;
38: double dtemp, gtod[NBUF];
39:
40: /*
41: * Force pages into memory
42: */
43: for (i = 0; i < NBUF; i ++)
44: gtod[i] = 0;
45:
46: /*
47: * Construct gtod array
48: */
49: for (i = 0; i < NBUF; i ++) {
50: get_systime(&tr);
51: LFPTOD(&tr, gtod[i]);
52: }
53:
54: /*
55: * Write out gtod array for later processing with Matlab
56: */
57: average = 0;
58: for (i = 0; i < NBUF - 2; i++) {
59: gtod[i] = gtod[i + 1] - gtod[i];
60: printf("%13.9f\n", gtod[i]);
61: average += gtod[i];
62: }
63:
64: /*
65: * Sort the gtod array and display deciles
66: */
67: for (i = 0; i < NBUF - 2; i++) {
68: for (j = 0; j <= i; j++) {
69: if (gtod[j] > gtod[i]) {
70: dtemp = gtod[j];
71: gtod[j] = gtod[i];
72: gtod[i] = dtemp;
73: }
74: }
75: }
76: average = average / (NBUF - 2);
77: fprintf(stderr, "Average %13.9f\n", average);
78: fprintf(stderr, "First rank\n");
79: for (i = 0; i < 10; i++)
80: fprintf(stderr, "%2d %13.9f\n", i, gtod[i]);
81: fprintf(stderr, "Last rank\n");
82: for (i = NBUF - 12; i < NBUF - 2; i++)
83: fprintf(stderr, "%2d %13.9f\n", i, gtod[i]);
84: exit(0);
85: }
86:
87:
88: /*
89: * get_systime - return system time in NTP timestamp format.
90: */
91: void
92: get_systime(
93: l_fp *now /* system time */
94: )
95: {
96: double dtemp;
97:
98: #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
99: struct timespec ts; /* seconds and nanoseconds */
100:
101: /*
102: * Convert Unix clock from seconds and nanoseconds to seconds.
103: */
104: # ifdef HAVE_CLOCK_GETTIME
105: clock_gettime(CLOCK_REALTIME, &ts);
106: # else
107: getclock(TIMEOFDAY, &ts);
108: # endif
109: now->l_i = ts.tv_sec + JAN_1970;
110: dtemp = ts.tv_nsec / 1e9;
111:
112: #else /* HAVE_CLOCK_GETTIME || HAVE_GETCLOCK */
113: struct timeval tv; /* seconds and microseconds */
114:
115: /*
116: * Convert Unix clock from seconds and microseconds to seconds.
117: */
118: gettimeofday(&tv, NULL);
119: now->l_i = tv.tv_sec + JAN_1970;
120: dtemp = tv.tv_usec / 1e6;
121:
122: #endif /* HAVE_CLOCK_GETTIME || HAVE_GETCLOCK */
123:
124: /*
125: * Renormalize to seconds past 1900 and fraction.
126: */
127: dtemp += sys_residual;
128: if (dtemp >= 1) {
129: dtemp -= 1;
130: now->l_i++;
131: } else if (dtemp < -1) {
132: dtemp += 1;
133: now->l_i--;
134: }
135: dtemp *= FRAC;
136: now->l_uf = (u_int32)dtemp;
137: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>