xref: /aosp_15_r20/external/linux-kselftest/tools/testing/selftests/timers/adjtick.c (revision 053f45be4e351dfd5e965df293cd45b779f579ee)
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