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