/contrib/ntp/util/jitter.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 137 lines · 88 code · 17 blank · 32 comment · 12 complexity · 9bcdb403f4e9f30c721e0d95ccb08ac9 MD5 · raw file

  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. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. #include <stdio.h>
  13. #include <sys/time.h>
  14. #include <stdlib.h>
  15. #include "jitter.h"
  16. #define NBUF 80002
  17. #define FRAC 4294967296. /* a bbbbillion */
  18. #define JAN_1970 2208988800UL /* Unix base epoch */
  19. #define CLOCK_GETTIME /* Solaris hires clock */
  20. int debug;
  21. char progname[10];
  22. double sys_residual;
  23. double average;
  24. void sys_gettime(l_fp *);
  25. int
  26. main(
  27. int argc,
  28. char *argv[]
  29. )
  30. {
  31. l_fp tr;
  32. int i, j;
  33. double dtemp, gtod[NBUF];
  34. /*
  35. * Force pages into memory
  36. */
  37. for (i = 0; i < NBUF; i ++)
  38. gtod[i] = 0;
  39. /*
  40. * Construct gtod array
  41. */
  42. for (i = 0; i < NBUF; i ++) {
  43. get_systime(&tr);
  44. LFPTOD(&tr, gtod[i]);
  45. }
  46. /*
  47. * Write out gtod array for later processing with Matlab
  48. */
  49. average = 0;
  50. for (i = 0; i < NBUF - 2; i++) {
  51. gtod[i] = gtod[i + 1] - gtod[i];
  52. printf("%13.9f\n", gtod[i]);
  53. average += gtod[i];
  54. }
  55. /*
  56. * Sort the gtod array and display deciles
  57. */
  58. for (i = 0; i < NBUF - 2; i++) {
  59. for (j = 0; j <= i; j++) {
  60. if (gtod[j] > gtod[i]) {
  61. dtemp = gtod[j];
  62. gtod[j] = gtod[i];
  63. gtod[i] = dtemp;
  64. }
  65. }
  66. }
  67. average = average / (NBUF - 2);
  68. fprintf(stderr, "Average %13.9f\n", average);
  69. fprintf(stderr, "First rank\n");
  70. for (i = 0; i < 10; i++)
  71. fprintf(stderr, "%2d %13.9f\n", i, gtod[i]);
  72. fprintf(stderr, "Last rank\n");
  73. for (i = NBUF - 12; i < NBUF - 2; i++)
  74. fprintf(stderr, "%2d %13.9f\n", i, gtod[i]);
  75. exit(0);
  76. }
  77. /*
  78. * get_systime - return system time in NTP timestamp format.
  79. */
  80. void
  81. get_systime(
  82. l_fp *now /* system time */
  83. )
  84. {
  85. double dtemp;
  86. #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
  87. struct timespec ts; /* seconds and nanoseconds */
  88. /*
  89. * Convert Unix clock from seconds and nanoseconds to seconds.
  90. */
  91. # ifdef HAVE_CLOCK_GETTIME
  92. clock_gettime(CLOCK_REALTIME, &ts);
  93. # else
  94. getclock(TIMEOFDAY, &ts);
  95. # endif
  96. now->l_i = ts.tv_sec + JAN_1970;
  97. dtemp = ts.tv_nsec / 1e9;
  98. #else /* HAVE_CLOCK_GETTIME || HAVE_GETCLOCK */
  99. struct timeval tv; /* seconds and microseconds */
  100. /*
  101. * Convert Unix clock from seconds and microseconds to seconds.
  102. */
  103. gettimeofday(&tv, NULL);
  104. now->l_i = tv.tv_sec + JAN_1970;
  105. dtemp = tv.tv_usec / 1e6;
  106. #endif /* HAVE_CLOCK_GETTIME || HAVE_GETCLOCK */
  107. /*
  108. * Renormalize to seconds past 1900 and fraction.
  109. */
  110. dtemp += sys_residual;
  111. if (dtemp >= 1) {
  112. dtemp -= 1;
  113. now->l_i++;
  114. } else if (dtemp < -1) {
  115. dtemp += 1;
  116. now->l_i--;
  117. }
  118. dtemp *= FRAC;
  119. now->l_uf = (u_int32)dtemp;
  120. }