#include #include #include #include #include #include #include #include #include #define SAMPLES 30 #define SAMPLES_PER_SEC 10 #define SAMPLE_LOOPS 40 struct sample { uint64_t tsc; uint64_t ts; int delay; }; static uint64_t rdtsc() { #if 1 uint32_t a, d; __asm__ __volatile__("rdtsc" : "=a" (a), "=d" (d)); return (uint64_t)d << 32 | a; #else return __builtin_ia32_rdtsc(); #endif } static void get_sample(struct sample *sample) { int i, delay, mindelay; struct timespec ts = {0, 0}, ts1; uint64_t tsc = 0, tsc1, tsc2; for (i = 0, mindelay = INT_MAX; i < SAMPLE_LOOPS; i++) { tsc1 = rdtsc(); #if 1 clock_gettime(CLOCK_REALTIME, &ts1); #else syscall(__NR_clock_gettime, CLOCK_REALTIME, &ts1); #endif tsc2 = rdtsc(); delay = tsc2 - tsc1; if (delay <= mindelay) { ts = ts1; tsc = (tsc1 + tsc2) / 2; mindelay = delay; } } sample->tsc = tsc; sample->ts = (uint64_t)ts.tv_sec * 1000000000 + ts.tv_nsec; sample->delay = mindelay; } /* taken/modified from chrony/regress.c */ void regress (double *x, /* independent variable */ double *y, /* measured data */ int n, /* number of data points */ /* And now the results */ double *b0, /* estimated y axis intercept */ double *b1, /* estimated slope */ double *s2 /* Could add correlation stuff later if required */ ) { double P, Q, U, V, W; double diff; double u, ui; int i; assert(n >= 3); W = U = 0; for (i=0; i max_offset) max_offset = fabs(offset); printf("%5d %5d %9.1f\n", i, samples[i].delay, offset); } printf("n: %d, slope: %.2f (%.2f GHz), dev: %.1f ns, max: %.1f ns\n", SAMPLES, slope, 1.0 / slope, sqrt(variance), max_offset); return 0; }