File Index
Files and directories
Sign in
FILE

valid-adjtimex.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/timers/valid-adjtimex.c C
  1/* valid adjtimex test
  2 *              by: John Stultz <john.stultz@linaro.org>
  3 *              (C) Copyright Linaro 2015
  4 *              Licensed under the GPLv2
  5 *
  6 *  This test validates adjtimex interface with valid
  7 *  and invalid test data.
  8 *
  9 *  Usage: valid-adjtimex
 10 *
 11 *  To build:
 12 *	$ gcc valid-adjtimex.c -o valid-adjtimex -lrt
 13 *
 14 *   This program is free software: you can redistribute it and/or modify
 15 *   it under the terms of the GNU General Public License as published by
 16 *   the Free Software Foundation, either version 2 of the License, or
 17 *   (at your option) any later version.
 18 *
 19 *   This program is distributed in the hope that it will be useful,
 20 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 21 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 22 *   GNU General Public License for more details.
 23 */
 24#include <stdio.h>
 25#include <stdlib.h>
 26#include <time.h>
 27#include <sys/time.h>
 28#include <sys/timex.h>
 29#include <string.h>
 30#include <signal.h>
 31#include <unistd.h>
 32#include <include/vdso/time64.h>
 33#include "kselftest.h"
 34
 35#define ADJ_SETOFFSET 0x0100
 36
 37#include <sys/syscall.h>
 38int clock_adjtime(clockid_t id, struct timex *tx)
 39{
 40	return syscall(__NR_clock_adjtime, id, tx);
 41}
 42
 43
 44/* clear NTP time_status & time_state */
 45int clear_time_state(void)
 46{
 47	struct timex tx;
 48	int ret;
 49
 50	tx.modes = ADJ_STATUS;
 51	tx.status = 0;
 52	ret = adjtimex(&tx);
 53	return ret;
 54}
 55
 56#define NUM_FREQ_VALID 32
 57#define NUM_FREQ_OUTOFRANGE 4
 58#define NUM_FREQ_INVALID 2
 59
 60#define SHIFTED_PPM (1 << 16)
 61
 62long valid_freq[NUM_FREQ_VALID] = {
 63	 -499 * SHIFTED_PPM,
 64	 -450 * SHIFTED_PPM,
 65	 -400 * SHIFTED_PPM,
 66	 -350 * SHIFTED_PPM,
 67	 -300 * SHIFTED_PPM,
 68	 -250 * SHIFTED_PPM,
 69	 -200 * SHIFTED_PPM,
 70	 -150 * SHIFTED_PPM,
 71	 -100 * SHIFTED_PPM,
 72	  -75 * SHIFTED_PPM,
 73	  -50 * SHIFTED_PPM,
 74	  -25 * SHIFTED_PPM,
 75	  -10 * SHIFTED_PPM,
 76	   -5 * SHIFTED_PPM,
 77	   -1 * SHIFTED_PPM,
 78	-1000,
 79	    1 * SHIFTED_PPM,
 80	    5 * SHIFTED_PPM,
 81	   10 * SHIFTED_PPM,
 82	   25 * SHIFTED_PPM,
 83	   50 * SHIFTED_PPM,
 84	   75 * SHIFTED_PPM,
 85	  100 * SHIFTED_PPM,
 86	  150 * SHIFTED_PPM,
 87	  200 * SHIFTED_PPM,
 88	  250 * SHIFTED_PPM,
 89	  300 * SHIFTED_PPM,
 90	  350 * SHIFTED_PPM,
 91	  400 * SHIFTED_PPM,
 92	  450 * SHIFTED_PPM,
 93	  499 * SHIFTED_PPM,
 94};
 95
 96long outofrange_freq[NUM_FREQ_OUTOFRANGE] = {
 97	-1000 * SHIFTED_PPM,
 98	 -550 * SHIFTED_PPM,
 99	  550 * SHIFTED_PPM,
100	 1000 * SHIFTED_PPM,
101};
102
103#define LONG_MAX (~0UL>>1)
104#define LONG_MIN (-LONG_MAX - 1)
105
106long invalid_freq[NUM_FREQ_INVALID] = {
107	LONG_MAX,
108	LONG_MIN,
109};
110
111int validate_freq(void)
112{
113	struct timex tx;
114	int ret, pass = 0;
115	int i;
116
117	clear_time_state();
118
119	memset(&tx, 0, sizeof(struct timex));
120	/* Set the leap second insert flag */
121
122	printf("Testing ADJ_FREQ... ");
123	fflush(stdout);
124	for (i = 0; i < NUM_FREQ_VALID; i++) {
125		tx.modes = ADJ_FREQUENCY;
126		tx.freq = valid_freq[i];
127
128		ret = adjtimex(&tx);
129		if (ret < 0) {
130			printf("[FAIL]\n");
131			printf("Error: adjtimex(ADJ_FREQ, %ld - %ld ppm\n",
132				valid_freq[i], valid_freq[i]>>16);
133			pass = -1;
134			goto out;
135		}
136		tx.modes = 0;
137		ret = adjtimex(&tx);
138		if (tx.freq != valid_freq[i]) {
139			printf("Warning: freq value %ld not what we set it (%ld)!\n",
140					tx.freq, valid_freq[i]);
141		}
142	}
143	for (i = 0; i < NUM_FREQ_OUTOFRANGE; i++) {
144		tx.modes = ADJ_FREQUENCY;
145		tx.freq = outofrange_freq[i];
146
147		ret = adjtimex(&tx);
148		if (ret < 0) {
149			printf("[FAIL]\n");
150			printf("Error: adjtimex(ADJ_FREQ, %ld - %ld ppm\n",
151				outofrange_freq[i], outofrange_freq[i]>>16);
152			pass = -1;
153			goto out;
154		}
155		tx.modes = 0;
156		ret = adjtimex(&tx);
157		if (tx.freq == outofrange_freq[i]) {
158			printf("[FAIL]\n");
159			printf("ERROR: out of range value %ld actually set!\n",
160					tx.freq);
161			pass = -1;
162			goto out;
163		}
164	}
165
166
167	if (sizeof(long) == 8) { /* this case only applies to 64bit systems */
168		for (i = 0; i < NUM_FREQ_INVALID; i++) {
169			tx.modes = ADJ_FREQUENCY;
170			tx.freq = invalid_freq[i];
171			ret = adjtimex(&tx);
172			if (ret >= 0) {
173				printf("[FAIL]\n");
174				printf("Error: No failure on invalid ADJ_FREQUENCY %ld\n",
175					invalid_freq[i]);
176				pass = -1;
177				goto out;
178			}
179		}
180	}
181
182	printf("[OK]\n");
183out:
184	/* reset freq to zero */
185	tx.modes = ADJ_FREQUENCY;
186	tx.freq = 0;
187	ret = adjtimex(&tx);
188
189	return pass;
190}
191
192
193int set_offset(long long offset, int use_nano)
194{
195	struct timex tmx = {};
196	int ret;
197
198	tmx.modes = ADJ_SETOFFSET;
199	if (use_nano) {
200		tmx.modes |= ADJ_NANO;
201
202		tmx.time.tv_sec = offset / NSEC_PER_SEC;
203		tmx.time.tv_usec = offset % NSEC_PER_SEC;
204
205		if (offset < 0 && tmx.time.tv_usec) {
206			tmx.time.tv_sec -= 1;
207			tmx.time.tv_usec += NSEC_PER_SEC;
208		}
209	} else {
210		tmx.time.tv_sec = offset / USEC_PER_SEC;
211		tmx.time.tv_usec = offset % USEC_PER_SEC;
212
213		if (offset < 0 && tmx.time.tv_usec) {
214			tmx.time.tv_sec -= 1;
215			tmx.time.tv_usec += USEC_PER_SEC;
216		}
217	}
218
219	ret = clock_adjtime(CLOCK_REALTIME, &tmx);
220	if (ret < 0) {
221		printf("(sec: %ld  usec: %ld) ", tmx.time.tv_sec, tmx.time.tv_usec);
222		printf("[FAIL]\n");
223		return -1;
224	}
225	return 0;
226}
227
228int set_bad_offset(long sec, long usec, int use_nano)
229{
230	struct timex tmx = {};
231	int ret;
232
233	tmx.modes = ADJ_SETOFFSET;
234	if (use_nano)
235		tmx.modes |= ADJ_NANO;
236
237	tmx.time.tv_sec = sec;
238	tmx.time.tv_usec = usec;
239	ret = clock_adjtime(CLOCK_REALTIME, &tmx);
240	if (ret >= 0) {
241		printf("Invalid (sec: %ld  usec: %ld) did not fail! ", tmx.time.tv_sec, tmx.time.tv_usec);
242		printf("[FAIL]\n");
243		return -1;
244	}
245	return 0;
246}
247
248int validate_set_offset(void)
249{
250	printf("Testing ADJ_SETOFFSET... ");
251	fflush(stdout);
252
253	/* Test valid values */
254	if (set_offset(NSEC_PER_SEC - 1, 1))
255		return -1;
256
257	if (set_offset(-NSEC_PER_SEC + 1, 1))
258		return -1;
259
260	if (set_offset(-NSEC_PER_SEC - 1, 1))
261		return -1;
262
263	if (set_offset(5 * NSEC_PER_SEC, 1))
264		return -1;
265
266	if (set_offset(-5 * NSEC_PER_SEC, 1))
267		return -1;
268
269	if (set_offset(5 * NSEC_PER_SEC + NSEC_PER_SEC / 2, 1))
270		return -1;
271
272	if (set_offset(-5 * NSEC_PER_SEC - NSEC_PER_SEC / 2, 1))
273		return -1;
274
275	if (set_offset(USEC_PER_SEC - 1, 0))
276		return -1;
277
278	if (set_offset(-USEC_PER_SEC + 1, 0))
279		return -1;
280
281	if (set_offset(-USEC_PER_SEC - 1, 0))
282		return -1;
283
284	if (set_offset(5 * USEC_PER_SEC, 0))
285		return -1;
286
287	if (set_offset(-5 * USEC_PER_SEC, 0))
288		return -1;
289
290	if (set_offset(5 * USEC_PER_SEC + USEC_PER_SEC / 2, 0))
291		return -1;
292
293	if (set_offset(-5 * USEC_PER_SEC - USEC_PER_SEC / 2, 0))
294		return -1;
295
296	/* Test invalid values */
297	if (set_bad_offset(0, -1, 1))
298		return -1;
299	if (set_bad_offset(0, -1, 0))
300		return -1;
301	if (set_bad_offset(0, 2 * NSEC_PER_SEC, 1))
302		return -1;
303	if (set_bad_offset(0, 2 * USEC_PER_SEC, 0))
304		return -1;
305	if (set_bad_offset(0, NSEC_PER_SEC, 1))
306		return -1;
307	if (set_bad_offset(0, USEC_PER_SEC, 0))
308		return -1;
309	if (set_bad_offset(0, -NSEC_PER_SEC, 1))
310		return -1;
311	if (set_bad_offset(0, -USEC_PER_SEC, 0))
312		return -1;
313
314	printf("[OK]\n");
315	return 0;
316}
317
318int main(int argc, char **argv)
319{
320	if (validate_freq())
321		ksft_exit_fail();
322
323	if (validate_set_offset())
324		ksft_exit_fail();
325
326	ksft_exit_pass();
327}
~/ Read-only file preview.