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 26int debug; 27char progname[10]; 28double sys_residual; 29double average; 30void sys_gettime(l_fp *); 31 32int 33main( 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 */ 93void 94get_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