^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * This test checks the response of the system clock to frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * steps made with adjtimex(). The frequency error and stability of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * the CLOCK_MONOTONIC clock relative to the CLOCK_MONOTONIC_RAW clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * is measured in two intervals following the step. The test fails if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * values from the second interval exceed specified limits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) Miroslav Lichvar <mlichvar@redhat.com> 2017
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <math.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <sys/timex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "../kselftest.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define SAMPLES 100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define SAMPLE_READINGS 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define MEAN_SAMPLE_INTERVAL 0.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define STEP_INTERVAL 1.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define MAX_PRECISION 500e-9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define MAX_FREQ_ERROR 0.02e-6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define MAX_STDDEV 50e-9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #ifndef ADJ_SETOFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define ADJ_SETOFFSET 0x0100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct sample {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) double offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) double time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static time_t mono_raw_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static time_t mono_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static long user_hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static double precision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static double mono_freq_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static double diff_timespec(struct timespec *ts1, struct timespec *ts2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return ts1->tv_sec - ts2->tv_sec + (ts1->tv_nsec - ts2->tv_nsec) / 1e9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static double get_sample(struct sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) double delay, mindelay = 0.0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct timespec ts1, ts2, ts3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) for (i = 0; i < SAMPLE_READINGS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) clock_gettime(CLOCK_MONOTONIC_RAW, &ts1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) clock_gettime(CLOCK_MONOTONIC, &ts2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) clock_gettime(CLOCK_MONOTONIC_RAW, &ts3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) ts1.tv_sec -= mono_raw_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) ts2.tv_sec -= mono_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) ts3.tv_sec -= mono_raw_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) delay = diff_timespec(&ts3, &ts1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (delay <= 1e-9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) i--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (!i || delay < mindelay) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) sample->offset = diff_timespec(&ts2, &ts1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) sample->offset -= delay / 2.0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) sample->time = ts1.tv_sec + ts1.tv_nsec / 1e9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) mindelay = delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return mindelay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static void reset_ntp_error(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct timex txc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) txc.modes = ADJ_SETOFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) txc.time.tv_sec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) txc.time.tv_usec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (adjtimex(&txc) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) perror("[FAIL] adjtimex");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ksft_exit_fail();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static void set_frequency(double freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct timex txc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int tick_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) tick_offset = 1e6 * freq / user_hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) txc.modes = ADJ_TICK | ADJ_FREQUENCY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) txc.tick = 1000000 / user_hz + tick_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) txc.freq = (1e6 * freq - user_hz * tick_offset) * (1 << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (adjtimex(&txc) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) perror("[FAIL] adjtimex");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ksft_exit_fail();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static void regress(struct sample *samples, int n, double *intercept,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) double *slope, double *r_stddev, double *r_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) double x, y, r, x_sum, y_sum, xy_sum, x2_sum, r2_sum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) x_sum = 0.0, y_sum = 0.0, xy_sum = 0.0, x2_sum = 0.0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) for (i = 0; i < n; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) x = samples[i].time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) y = samples[i].offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) x_sum += x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) y_sum += y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) xy_sum += x * y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) x2_sum += x * x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) *slope = (xy_sum - x_sum * y_sum / n) / (x2_sum - x_sum * x_sum / n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) *intercept = (y_sum - *slope * x_sum) / n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) *r_max = 0.0, r2_sum = 0.0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) for (i = 0; i < n; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) x = samples[i].time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) y = samples[i].offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) r = fabs(x * *slope + *intercept - y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (*r_max < r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) *r_max = r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) r2_sum += r * r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) *r_stddev = sqrt(r2_sum / n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static int run_test(int calibration, double freq_base, double freq_step)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct sample samples[SAMPLES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) double intercept, slope, stddev1, max1, stddev2, max2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) double freq_error1, freq_error2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) set_frequency(freq_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) for (i = 0; i < 10; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) usleep(1e6 * MEAN_SAMPLE_INTERVAL / 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) reset_ntp_error();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) set_frequency(freq_base + freq_step);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) for (i = 0; i < 10; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) usleep(rand() % 2000000 * STEP_INTERVAL / 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) set_frequency(freq_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) for (i = 0; i < SAMPLES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) usleep(rand() % 2000000 * MEAN_SAMPLE_INTERVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) get_sample(&samples[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (calibration) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) regress(samples, SAMPLES, &intercept, &slope, &stddev1, &max1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) mono_freq_offset = slope;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) printf("CLOCK_MONOTONIC_RAW frequency offset: %11.3f ppm\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 1e6 * mono_freq_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) regress(samples, SAMPLES / 2, &intercept, &slope, &stddev1, &max1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) freq_error1 = slope * (1.0 - mono_freq_offset) - mono_freq_offset -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) freq_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) regress(samples + SAMPLES / 2, SAMPLES / 2, &intercept, &slope,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) &stddev2, &max2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) freq_error2 = slope * (1.0 - mono_freq_offset) - mono_freq_offset -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) freq_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) printf("%6.0f %+10.3f %6.0f %7.0f %+10.3f %6.0f %7.0f\t",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 1e6 * freq_step,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 1e6 * freq_error1, 1e9 * stddev1, 1e9 * max1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 1e6 * freq_error2, 1e9 * stddev2, 1e9 * max2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (fabs(freq_error2) > MAX_FREQ_ERROR || stddev2 > MAX_STDDEV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) printf("[FAIL]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) printf("[OK]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static void init_test(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct timespec ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct sample sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) perror("[FAIL] clock_gettime(CLOCK_MONOTONIC_RAW)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) ksft_exit_fail();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) mono_raw_base = ts.tv_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) perror("[FAIL] clock_gettime(CLOCK_MONOTONIC)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ksft_exit_fail();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) mono_base = ts.tv_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) user_hz = sysconf(_SC_CLK_TCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) precision = get_sample(&sample) / 2.0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) printf("CLOCK_MONOTONIC_RAW+CLOCK_MONOTONIC precision: %.0f ns\t\t",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 1e9 * precision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (precision > MAX_PRECISION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) ksft_exit_skip("precision: %.0f ns > MAX_PRECISION: %.0f ns\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 1e9 * precision, 1e9 * MAX_PRECISION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) printf("[OK]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) srand(ts.tv_sec ^ ts.tv_nsec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) run_test(1, 0.0, 0.0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) int main(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) double freq_base, freq_step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int i, j, fails = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) init_test();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) printf("Checking response to frequency step:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) printf(" Step 1st interval 2nd interval\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) printf(" Freq Dev Max Freq Dev Max\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) for (i = 2; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) for (j = 0; j < 5; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) freq_base = (rand() % (1 << 24) - (1 << 23)) / 65536e6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) freq_step = 10e-6 * (1 << (6 * i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) fails += run_test(0, freq_base, freq_step);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) set_frequency(0.0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (fails)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return ksft_exit_fail();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return ksft_exit_pass();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }