Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.11 339 lines 6.6 kB view raw
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 25 26 27#include <stdio.h> 28#include <stdlib.h> 29#include <time.h> 30#include <sys/time.h> 31#include <sys/timex.h> 32#include <string.h> 33#include <signal.h> 34#include <unistd.h> 35#ifdef KTEST 36#include "../kselftest.h" 37#else 38static inline int ksft_exit_pass(void) 39{ 40 exit(0); 41} 42static inline int ksft_exit_fail(void) 43{ 44 exit(1); 45} 46#endif 47 48#define NSEC_PER_SEC 1000000000LL 49#define USEC_PER_SEC 1000000LL 50 51#define ADJ_SETOFFSET 0x0100 52 53#include <sys/syscall.h> 54static int clock_adjtime(clockid_t id, struct timex *tx) 55{ 56 return syscall(__NR_clock_adjtime, id, tx); 57} 58 59 60/* clear NTP time_status & time_state */ 61int clear_time_state(void) 62{ 63 struct timex tx; 64 int ret; 65 66 tx.modes = ADJ_STATUS; 67 tx.status = 0; 68 ret = adjtimex(&tx); 69 return ret; 70} 71 72#define NUM_FREQ_VALID 32 73#define NUM_FREQ_OUTOFRANGE 4 74#define NUM_FREQ_INVALID 2 75 76long valid_freq[NUM_FREQ_VALID] = { 77 -499<<16, 78 -450<<16, 79 -400<<16, 80 -350<<16, 81 -300<<16, 82 -250<<16, 83 -200<<16, 84 -150<<16, 85 -100<<16, 86 -75<<16, 87 -50<<16, 88 -25<<16, 89 -10<<16, 90 -5<<16, 91 -1<<16, 92 -1000, 93 1<<16, 94 5<<16, 95 10<<16, 96 25<<16, 97 50<<16, 98 75<<16, 99 100<<16, 100 150<<16, 101 200<<16, 102 250<<16, 103 300<<16, 104 350<<16, 105 400<<16, 106 450<<16, 107 499<<16, 108}; 109 110long outofrange_freq[NUM_FREQ_OUTOFRANGE] = { 111 -1000<<16, 112 -550<<16, 113 550<<16, 114 1000<<16, 115}; 116 117#define LONG_MAX (~0UL>>1) 118#define LONG_MIN (-LONG_MAX - 1) 119 120long invalid_freq[NUM_FREQ_INVALID] = { 121 LONG_MAX, 122 LONG_MIN, 123}; 124 125int validate_freq(void) 126{ 127 struct timex tx; 128 int ret, pass = 0; 129 int i; 130 131 clear_time_state(); 132 133 memset(&tx, 0, sizeof(struct timex)); 134 /* Set the leap second insert flag */ 135 136 printf("Testing ADJ_FREQ... "); 137 for (i = 0; i < NUM_FREQ_VALID; i++) { 138 tx.modes = ADJ_FREQUENCY; 139 tx.freq = valid_freq[i]; 140 141 ret = adjtimex(&tx); 142 if (ret < 0) { 143 printf("[FAIL]\n"); 144 printf("Error: adjtimex(ADJ_FREQ, %ld - %ld ppm\n", 145 valid_freq[i], valid_freq[i]>>16); 146 pass = -1; 147 goto out; 148 } 149 tx.modes = 0; 150 ret = adjtimex(&tx); 151 if (tx.freq != valid_freq[i]) { 152 printf("Warning: freq value %ld not what we set it (%ld)!\n", 153 tx.freq, valid_freq[i]); 154 } 155 } 156 for (i = 0; i < NUM_FREQ_OUTOFRANGE; i++) { 157 tx.modes = ADJ_FREQUENCY; 158 tx.freq = outofrange_freq[i]; 159 160 ret = adjtimex(&tx); 161 if (ret < 0) { 162 printf("[FAIL]\n"); 163 printf("Error: adjtimex(ADJ_FREQ, %ld - %ld ppm\n", 164 outofrange_freq[i], outofrange_freq[i]>>16); 165 pass = -1; 166 goto out; 167 } 168 tx.modes = 0; 169 ret = adjtimex(&tx); 170 if (tx.freq == outofrange_freq[i]) { 171 printf("[FAIL]\n"); 172 printf("ERROR: out of range value %ld actually set!\n", 173 tx.freq); 174 pass = -1; 175 goto out; 176 } 177 } 178 179 180 if (sizeof(long) == 8) { /* this case only applies to 64bit systems */ 181 for (i = 0; i < NUM_FREQ_INVALID; i++) { 182 tx.modes = ADJ_FREQUENCY; 183 tx.freq = invalid_freq[i]; 184 ret = adjtimex(&tx); 185 if (ret >= 0) { 186 printf("[FAIL]\n"); 187 printf("Error: No failure on invalid ADJ_FREQUENCY %ld\n", 188 invalid_freq[i]); 189 pass = -1; 190 goto out; 191 } 192 } 193 } 194 195 printf("[OK]\n"); 196out: 197 /* reset freq to zero */ 198 tx.modes = ADJ_FREQUENCY; 199 tx.freq = 0; 200 ret = adjtimex(&tx); 201 202 return pass; 203} 204 205 206int set_offset(long long offset, int use_nano) 207{ 208 struct timex tmx = {}; 209 int ret; 210 211 tmx.modes = ADJ_SETOFFSET; 212 if (use_nano) { 213 tmx.modes |= ADJ_NANO; 214 215 tmx.time.tv_sec = offset / NSEC_PER_SEC; 216 tmx.time.tv_usec = offset % NSEC_PER_SEC; 217 218 if (offset < 0 && tmx.time.tv_usec) { 219 tmx.time.tv_sec -= 1; 220 tmx.time.tv_usec += NSEC_PER_SEC; 221 } 222 } else { 223 tmx.time.tv_sec = offset / USEC_PER_SEC; 224 tmx.time.tv_usec = offset % USEC_PER_SEC; 225 226 if (offset < 0 && tmx.time.tv_usec) { 227 tmx.time.tv_sec -= 1; 228 tmx.time.tv_usec += USEC_PER_SEC; 229 } 230 } 231 232 ret = clock_adjtime(CLOCK_REALTIME, &tmx); 233 if (ret < 0) { 234 printf("(sec: %ld usec: %ld) ", tmx.time.tv_sec, tmx.time.tv_usec); 235 printf("[FAIL]\n"); 236 return -1; 237 } 238 return 0; 239} 240 241int set_bad_offset(long sec, long usec, int use_nano) 242{ 243 struct timex tmx = {}; 244 int ret; 245 246 tmx.modes = ADJ_SETOFFSET; 247 if (use_nano) 248 tmx.modes |= ADJ_NANO; 249 250 tmx.time.tv_sec = sec; 251 tmx.time.tv_usec = usec; 252 ret = clock_adjtime(CLOCK_REALTIME, &tmx); 253 if (ret >= 0) { 254 printf("Invalid (sec: %ld usec: %ld) did not fail! ", tmx.time.tv_sec, tmx.time.tv_usec); 255 printf("[FAIL]\n"); 256 return -1; 257 } 258 return 0; 259} 260 261int validate_set_offset(void) 262{ 263 printf("Testing ADJ_SETOFFSET... "); 264 265 /* Test valid values */ 266 if (set_offset(NSEC_PER_SEC - 1, 1)) 267 return -1; 268 269 if (set_offset(-NSEC_PER_SEC + 1, 1)) 270 return -1; 271 272 if (set_offset(-NSEC_PER_SEC - 1, 1)) 273 return -1; 274 275 if (set_offset(5 * NSEC_PER_SEC, 1)) 276 return -1; 277 278 if (set_offset(-5 * NSEC_PER_SEC, 1)) 279 return -1; 280 281 if (set_offset(5 * NSEC_PER_SEC + NSEC_PER_SEC / 2, 1)) 282 return -1; 283 284 if (set_offset(-5 * NSEC_PER_SEC - NSEC_PER_SEC / 2, 1)) 285 return -1; 286 287 if (set_offset(USEC_PER_SEC - 1, 0)) 288 return -1; 289 290 if (set_offset(-USEC_PER_SEC + 1, 0)) 291 return -1; 292 293 if (set_offset(-USEC_PER_SEC - 1, 0)) 294 return -1; 295 296 if (set_offset(5 * USEC_PER_SEC, 0)) 297 return -1; 298 299 if (set_offset(-5 * USEC_PER_SEC, 0)) 300 return -1; 301 302 if (set_offset(5 * USEC_PER_SEC + USEC_PER_SEC / 2, 0)) 303 return -1; 304 305 if (set_offset(-5 * USEC_PER_SEC - USEC_PER_SEC / 2, 0)) 306 return -1; 307 308 /* Test invalid values */ 309 if (set_bad_offset(0, -1, 1)) 310 return -1; 311 if (set_bad_offset(0, -1, 0)) 312 return -1; 313 if (set_bad_offset(0, 2 * NSEC_PER_SEC, 1)) 314 return -1; 315 if (set_bad_offset(0, 2 * USEC_PER_SEC, 0)) 316 return -1; 317 if (set_bad_offset(0, NSEC_PER_SEC, 1)) 318 return -1; 319 if (set_bad_offset(0, USEC_PER_SEC, 0)) 320 return -1; 321 if (set_bad_offset(0, -NSEC_PER_SEC, 1)) 322 return -1; 323 if (set_bad_offset(0, -USEC_PER_SEC, 0)) 324 return -1; 325 326 printf("[OK]\n"); 327 return 0; 328} 329 330int main(int argc, char **argv) 331{ 332 if (validate_freq()) 333 return ksft_exit_fail(); 334 335 if (validate_set_offset()) 336 return ksft_exit_fail(); 337 338 return ksft_exit_pass(); 339}