1 /* $NetBSD: jitter.c,v 1.1.1.2 2013/12/27 23:31:40 christos 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 char progname[10]; 27 double sys_residual; 28 double average; 29 void sys_gettime(l_fp *); 30 31 int 32 main( 33 int argc, 34 char *argv[] 35 ) 36 { 37 l_fp tr; 38 int i, j; 39 double dtemp, gtod[NBUF]; 40 41 /* 42 * Force pages into memory 43 */ 44 for (i = 0; i < NBUF; i ++) 45 gtod[i] = 0; 46 47 /* 48 * Construct gtod array 49 */ 50 for (i = 0; i < NBUF; i ++) { 51 get_systime(&tr); 52 LFPTOD(&tr, gtod[i]); 53 } 54 55 /* 56 * Write out gtod array for later processing with Matlab 57 */ 58 average = 0; 59 for (i = 0; i < NBUF - 2; i++) { 60 gtod[i] = gtod[i + 1] - gtod[i]; 61 printf("%13.9f\n", gtod[i]); 62 average += gtod[i]; 63 } 64 65 /* 66 * Sort the gtod array and display deciles 67 */ 68 for (i = 0; i < NBUF - 2; i++) { 69 for (j = 0; j <= i; j++) { 70 if (gtod[j] > gtod[i]) { 71 dtemp = gtod[j]; 72 gtod[j] = gtod[i]; 73 gtod[i] = dtemp; 74 } 75 } 76 } 77 average = average / (NBUF - 2); 78 fprintf(stderr, "Average %13.9f\n", average); 79 fprintf(stderr, "First rank\n"); 80 for (i = 0; i < 10; i++) 81 fprintf(stderr, "%2d %13.9f\n", i, gtod[i]); 82 fprintf(stderr, "Last rank\n"); 83 for (i = NBUF - 12; i < NBUF - 2; i++) 84 fprintf(stderr, "%2d %13.9f\n", i, gtod[i]); 85 exit(0); 86 } 87 88 89 /* 90 * get_systime - return system time in NTP timestamp format. 91 */ 92 void 93 get_systime( 94 l_fp *now /* system time */ 95 ) 96 { 97 double dtemp; 98 99 #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK) 100 struct timespec ts; /* seconds and nanoseconds */ 101 102 /* 103 * Convert Unix clock from seconds and nanoseconds to seconds. 104 */ 105 # ifdef HAVE_CLOCK_GETTIME 106 clock_gettime(CLOCK_REALTIME, &ts); 107 # else 108 getclock(TIMEOFDAY, &ts); 109 # endif 110 now->l_i = ts.tv_sec + JAN_1970; 111 dtemp = ts.tv_nsec / 1e9; 112 113 #else /* HAVE_CLOCK_GETTIME || HAVE_GETCLOCK */ 114 struct timeval tv; /* seconds and microseconds */ 115 116 /* 117 * Convert Unix clock from seconds and microseconds to seconds. 118 */ 119 gettimeofday(&tv, NULL); 120 now->l_i = tv.tv_sec + JAN_1970; 121 dtemp = tv.tv_usec / 1e6; 122 123 #endif /* HAVE_CLOCK_GETTIME || HAVE_GETCLOCK */ 124 125 /* 126 * Renormalize to seconds past 1900 and fraction. 127 */ 128 dtemp += sys_residual; 129 if (dtemp >= 1) { 130 dtemp -= 1; 131 now->l_i++; 132 } else if (dtemp < -1) { 133 dtemp += 1; 134 now->l_i--; 135 } 136 dtemp *= FRAC; 137 now->l_uf = (u_int32)dtemp; 138 } 139