~ [ 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-4.13.16)


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

~ [ 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