~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/timers/freq-step.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /tools/testing/selftests/timers/freq-step.c (Version linux-6.12-rc7) and /tools/testing/selftests/timers/freq-step.c (Version linux-5.13.19)


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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php