1*053f45beSAndroid Build Coastguard Worker /* adjtimex() tick adjustment test
2*053f45beSAndroid Build Coastguard Worker * by: John Stultz <[email protected]>
3*053f45beSAndroid Build Coastguard Worker * (C) Copyright Linaro Limited 2015
4*053f45beSAndroid Build Coastguard Worker * Licensed under the GPLv2
5*053f45beSAndroid Build Coastguard Worker *
6*053f45beSAndroid Build Coastguard Worker * To build:
7*053f45beSAndroid Build Coastguard Worker * $ gcc adjtick.c -o adjtick -lrt
8*053f45beSAndroid Build Coastguard Worker *
9*053f45beSAndroid Build Coastguard Worker * This program is free software: you can redistribute it and/or modify
10*053f45beSAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
11*053f45beSAndroid Build Coastguard Worker * the Free Software Foundation, either version 2 of the License, or
12*053f45beSAndroid Build Coastguard Worker * (at your option) any later version.
13*053f45beSAndroid Build Coastguard Worker *
14*053f45beSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
15*053f45beSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
16*053f45beSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17*053f45beSAndroid Build Coastguard Worker * GNU General Public License for more details.
18*053f45beSAndroid Build Coastguard Worker */
19*053f45beSAndroid Build Coastguard Worker #include <stdio.h>
20*053f45beSAndroid Build Coastguard Worker #include <unistd.h>
21*053f45beSAndroid Build Coastguard Worker #include <stdlib.h>
22*053f45beSAndroid Build Coastguard Worker #include <sys/time.h>
23*053f45beSAndroid Build Coastguard Worker #include <sys/timex.h>
24*053f45beSAndroid Build Coastguard Worker #include <time.h>
25*053f45beSAndroid Build Coastguard Worker
26*053f45beSAndroid Build Coastguard Worker #include "../kselftest.h"
27*053f45beSAndroid Build Coastguard Worker
28*053f45beSAndroid Build Coastguard Worker #define CLOCK_MONOTONIC_RAW 4
29*053f45beSAndroid Build Coastguard Worker
30*053f45beSAndroid Build Coastguard Worker #define NSEC_PER_SEC 1000000000LL
31*053f45beSAndroid Build Coastguard Worker #define USEC_PER_SEC 1000000
32*053f45beSAndroid Build Coastguard Worker
33*053f45beSAndroid Build Coastguard Worker #define MILLION 1000000
34*053f45beSAndroid Build Coastguard Worker
35*053f45beSAndroid Build Coastguard Worker long systick;
36*053f45beSAndroid Build Coastguard Worker
llabs(long long val)37*053f45beSAndroid Build Coastguard Worker long long llabs(long long val)
38*053f45beSAndroid Build Coastguard Worker {
39*053f45beSAndroid Build Coastguard Worker if (val < 0)
40*053f45beSAndroid Build Coastguard Worker val = -val;
41*053f45beSAndroid Build Coastguard Worker return val;
42*053f45beSAndroid Build Coastguard Worker }
43*053f45beSAndroid Build Coastguard Worker
ts_to_nsec(struct timespec ts)44*053f45beSAndroid Build Coastguard Worker unsigned long long ts_to_nsec(struct timespec ts)
45*053f45beSAndroid Build Coastguard Worker {
46*053f45beSAndroid Build Coastguard Worker return ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
47*053f45beSAndroid Build Coastguard Worker }
48*053f45beSAndroid Build Coastguard Worker
nsec_to_ts(long long ns)49*053f45beSAndroid Build Coastguard Worker struct timespec nsec_to_ts(long long ns)
50*053f45beSAndroid Build Coastguard Worker {
51*053f45beSAndroid Build Coastguard Worker struct timespec ts;
52*053f45beSAndroid Build Coastguard Worker
53*053f45beSAndroid Build Coastguard Worker ts.tv_sec = ns/NSEC_PER_SEC;
54*053f45beSAndroid Build Coastguard Worker ts.tv_nsec = ns%NSEC_PER_SEC;
55*053f45beSAndroid Build Coastguard Worker
56*053f45beSAndroid Build Coastguard Worker return ts;
57*053f45beSAndroid Build Coastguard Worker }
58*053f45beSAndroid Build Coastguard Worker
diff_timespec(struct timespec start,struct timespec end)59*053f45beSAndroid Build Coastguard Worker long long diff_timespec(struct timespec start, struct timespec end)
60*053f45beSAndroid Build Coastguard Worker {
61*053f45beSAndroid Build Coastguard Worker long long start_ns, end_ns;
62*053f45beSAndroid Build Coastguard Worker
63*053f45beSAndroid Build Coastguard Worker start_ns = ts_to_nsec(start);
64*053f45beSAndroid Build Coastguard Worker end_ns = ts_to_nsec(end);
65*053f45beSAndroid Build Coastguard Worker
66*053f45beSAndroid Build Coastguard Worker return end_ns - start_ns;
67*053f45beSAndroid Build Coastguard Worker }
68*053f45beSAndroid Build Coastguard Worker
get_monotonic_and_raw(struct timespec * mon,struct timespec * raw)69*053f45beSAndroid Build Coastguard Worker void get_monotonic_and_raw(struct timespec *mon, struct timespec *raw)
70*053f45beSAndroid Build Coastguard Worker {
71*053f45beSAndroid Build Coastguard Worker struct timespec start, mid, end;
72*053f45beSAndroid Build Coastguard Worker long long diff = 0, tmp;
73*053f45beSAndroid Build Coastguard Worker int i;
74*053f45beSAndroid Build Coastguard Worker
75*053f45beSAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC, mon);
76*053f45beSAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC_RAW, raw);
77*053f45beSAndroid Build Coastguard Worker
78*053f45beSAndroid Build Coastguard Worker /* Try to get a more tightly bound pairing */
79*053f45beSAndroid Build Coastguard Worker for (i = 0; i < 3; i++) {
80*053f45beSAndroid Build Coastguard Worker long long newdiff;
81*053f45beSAndroid Build Coastguard Worker
82*053f45beSAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC, &start);
83*053f45beSAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC_RAW, &mid);
84*053f45beSAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC, &end);
85*053f45beSAndroid Build Coastguard Worker
86*053f45beSAndroid Build Coastguard Worker newdiff = diff_timespec(start, end);
87*053f45beSAndroid Build Coastguard Worker if (diff == 0 || newdiff < diff) {
88*053f45beSAndroid Build Coastguard Worker diff = newdiff;
89*053f45beSAndroid Build Coastguard Worker *raw = mid;
90*053f45beSAndroid Build Coastguard Worker tmp = (ts_to_nsec(start) + ts_to_nsec(end))/2;
91*053f45beSAndroid Build Coastguard Worker *mon = nsec_to_ts(tmp);
92*053f45beSAndroid Build Coastguard Worker }
93*053f45beSAndroid Build Coastguard Worker }
94*053f45beSAndroid Build Coastguard Worker }
95*053f45beSAndroid Build Coastguard Worker
get_ppm_drift(void)96*053f45beSAndroid Build Coastguard Worker long long get_ppm_drift(void)
97*053f45beSAndroid Build Coastguard Worker {
98*053f45beSAndroid Build Coastguard Worker struct timespec mon_start, raw_start, mon_end, raw_end;
99*053f45beSAndroid Build Coastguard Worker long long delta1, delta2, eppm;
100*053f45beSAndroid Build Coastguard Worker
101*053f45beSAndroid Build Coastguard Worker get_monotonic_and_raw(&mon_start, &raw_start);
102*053f45beSAndroid Build Coastguard Worker
103*053f45beSAndroid Build Coastguard Worker sleep(15);
104*053f45beSAndroid Build Coastguard Worker
105*053f45beSAndroid Build Coastguard Worker get_monotonic_and_raw(&mon_end, &raw_end);
106*053f45beSAndroid Build Coastguard Worker
107*053f45beSAndroid Build Coastguard Worker delta1 = diff_timespec(mon_start, mon_end);
108*053f45beSAndroid Build Coastguard Worker delta2 = diff_timespec(raw_start, raw_end);
109*053f45beSAndroid Build Coastguard Worker
110*053f45beSAndroid Build Coastguard Worker eppm = (delta1*MILLION)/delta2 - MILLION;
111*053f45beSAndroid Build Coastguard Worker
112*053f45beSAndroid Build Coastguard Worker return eppm;
113*053f45beSAndroid Build Coastguard Worker }
114*053f45beSAndroid Build Coastguard Worker
check_tick_adj(long tickval)115*053f45beSAndroid Build Coastguard Worker int check_tick_adj(long tickval)
116*053f45beSAndroid Build Coastguard Worker {
117*053f45beSAndroid Build Coastguard Worker long long eppm, ppm;
118*053f45beSAndroid Build Coastguard Worker struct timex tx1;
119*053f45beSAndroid Build Coastguard Worker
120*053f45beSAndroid Build Coastguard Worker tx1.modes = ADJ_TICK;
121*053f45beSAndroid Build Coastguard Worker tx1.modes |= ADJ_OFFSET;
122*053f45beSAndroid Build Coastguard Worker tx1.modes |= ADJ_FREQUENCY;
123*053f45beSAndroid Build Coastguard Worker tx1.modes |= ADJ_STATUS;
124*053f45beSAndroid Build Coastguard Worker
125*053f45beSAndroid Build Coastguard Worker tx1.status = STA_PLL;
126*053f45beSAndroid Build Coastguard Worker tx1.offset = 0;
127*053f45beSAndroid Build Coastguard Worker tx1.freq = 0;
128*053f45beSAndroid Build Coastguard Worker tx1.tick = tickval;
129*053f45beSAndroid Build Coastguard Worker
130*053f45beSAndroid Build Coastguard Worker adjtimex(&tx1);
131*053f45beSAndroid Build Coastguard Worker
132*053f45beSAndroid Build Coastguard Worker sleep(1);
133*053f45beSAndroid Build Coastguard Worker
134*053f45beSAndroid Build Coastguard Worker ppm = ((long long)tickval * MILLION)/systick - MILLION;
135*053f45beSAndroid Build Coastguard Worker printf("Estimating tick (act: %ld usec, %lld ppm): ", tickval, ppm);
136*053f45beSAndroid Build Coastguard Worker
137*053f45beSAndroid Build Coastguard Worker eppm = get_ppm_drift();
138*053f45beSAndroid Build Coastguard Worker printf("%lld usec, %lld ppm", systick + (systick * eppm / MILLION), eppm);
139*053f45beSAndroid Build Coastguard Worker fflush(stdout);
140*053f45beSAndroid Build Coastguard Worker
141*053f45beSAndroid Build Coastguard Worker tx1.modes = 0;
142*053f45beSAndroid Build Coastguard Worker adjtimex(&tx1);
143*053f45beSAndroid Build Coastguard Worker
144*053f45beSAndroid Build Coastguard Worker if (tx1.offset || tx1.freq || tx1.tick != tickval) {
145*053f45beSAndroid Build Coastguard Worker printf(" [ERROR]\n");
146*053f45beSAndroid Build Coastguard Worker printf("\tUnexpected adjtimex return values, make sure ntpd is not running.\n");
147*053f45beSAndroid Build Coastguard Worker return -1;
148*053f45beSAndroid Build Coastguard Worker }
149*053f45beSAndroid Build Coastguard Worker
150*053f45beSAndroid Build Coastguard Worker /*
151*053f45beSAndroid Build Coastguard Worker * Here we use 100ppm difference as an error bound.
152*053f45beSAndroid Build Coastguard Worker * We likely should see better, but some coarse clocksources
153*053f45beSAndroid Build Coastguard Worker * cannot match the HZ tick size accurately, so we have a
154*053f45beSAndroid Build Coastguard Worker * internal correction factor that doesn't scale exactly
155*053f45beSAndroid Build Coastguard Worker * with the adjustment, resulting in > 10ppm error during
156*053f45beSAndroid Build Coastguard Worker * a 10% adjustment. 100ppm also gives us more breathing
157*053f45beSAndroid Build Coastguard Worker * room for interruptions during the measurement.
158*053f45beSAndroid Build Coastguard Worker */
159*053f45beSAndroid Build Coastguard Worker if (llabs(eppm - ppm) > 100) {
160*053f45beSAndroid Build Coastguard Worker printf(" [FAILED]\n");
161*053f45beSAndroid Build Coastguard Worker return -1;
162*053f45beSAndroid Build Coastguard Worker }
163*053f45beSAndroid Build Coastguard Worker printf(" [OK]\n");
164*053f45beSAndroid Build Coastguard Worker
165*053f45beSAndroid Build Coastguard Worker return 0;
166*053f45beSAndroid Build Coastguard Worker }
167*053f45beSAndroid Build Coastguard Worker
main(int argc,char ** argv)168*053f45beSAndroid Build Coastguard Worker int main(int argc, char **argv)
169*053f45beSAndroid Build Coastguard Worker {
170*053f45beSAndroid Build Coastguard Worker struct timespec raw;
171*053f45beSAndroid Build Coastguard Worker long tick, max, interval, err;
172*053f45beSAndroid Build Coastguard Worker struct timex tx1;
173*053f45beSAndroid Build Coastguard Worker
174*053f45beSAndroid Build Coastguard Worker err = 0;
175*053f45beSAndroid Build Coastguard Worker setbuf(stdout, NULL);
176*053f45beSAndroid Build Coastguard Worker
177*053f45beSAndroid Build Coastguard Worker if (clock_gettime(CLOCK_MONOTONIC_RAW, &raw)) {
178*053f45beSAndroid Build Coastguard Worker printf("ERR: NO CLOCK_MONOTONIC_RAW\n");
179*053f45beSAndroid Build Coastguard Worker return -1;
180*053f45beSAndroid Build Coastguard Worker }
181*053f45beSAndroid Build Coastguard Worker
182*053f45beSAndroid Build Coastguard Worker printf("Each iteration takes about 15 seconds\n");
183*053f45beSAndroid Build Coastguard Worker
184*053f45beSAndroid Build Coastguard Worker systick = sysconf(_SC_CLK_TCK);
185*053f45beSAndroid Build Coastguard Worker systick = USEC_PER_SEC/sysconf(_SC_CLK_TCK);
186*053f45beSAndroid Build Coastguard Worker max = systick/10; /* +/- 10% */
187*053f45beSAndroid Build Coastguard Worker interval = max/4; /* in 4 steps each side */
188*053f45beSAndroid Build Coastguard Worker
189*053f45beSAndroid Build Coastguard Worker for (tick = (systick - max); tick < (systick + max); tick += interval) {
190*053f45beSAndroid Build Coastguard Worker if (check_tick_adj(tick)) {
191*053f45beSAndroid Build Coastguard Worker err = 1;
192*053f45beSAndroid Build Coastguard Worker break;
193*053f45beSAndroid Build Coastguard Worker }
194*053f45beSAndroid Build Coastguard Worker }
195*053f45beSAndroid Build Coastguard Worker
196*053f45beSAndroid Build Coastguard Worker /* Reset things to zero */
197*053f45beSAndroid Build Coastguard Worker tx1.modes = ADJ_TICK;
198*053f45beSAndroid Build Coastguard Worker tx1.modes |= ADJ_OFFSET;
199*053f45beSAndroid Build Coastguard Worker tx1.modes |= ADJ_FREQUENCY;
200*053f45beSAndroid Build Coastguard Worker
201*053f45beSAndroid Build Coastguard Worker tx1.offset = 0;
202*053f45beSAndroid Build Coastguard Worker tx1.freq = 0;
203*053f45beSAndroid Build Coastguard Worker tx1.tick = systick;
204*053f45beSAndroid Build Coastguard Worker
205*053f45beSAndroid Build Coastguard Worker adjtimex(&tx1);
206*053f45beSAndroid Build Coastguard Worker
207*053f45beSAndroid Build Coastguard Worker if (err)
208*053f45beSAndroid Build Coastguard Worker return ksft_exit_fail();
209*053f45beSAndroid Build Coastguard Worker
210*053f45beSAndroid Build Coastguard Worker return ksft_exit_pass();
211*053f45beSAndroid Build Coastguard Worker }
212