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

selftests/timers: Add inconsistency-check test from timetests

This adds my inconsistency-test from my timetests suite,
which checks for (single threaded) time inconsistencies
across the various clockids.

Cc: Shuah Khan <shuahkh@osg.samsung.com>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Tested-by: Prarit Bhargava <prarit@redhat.com>
Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>

authored by

John Stultz and committed by
Shuah Khan
ed3fe34a 689f32fb

+206 -2
+2 -2
tools/testing/selftests/timers/Makefile
··· 2 2 BUILD_FLAGS = -DKTEST 3 3 CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS) 4 4 LDFLAGS += -lrt -lpthread 5 - bins = posix_timers nanosleep 5 + bins = posix_timers nanosleep inconsistency-check 6 6 7 7 all: ${bins} 8 8 9 9 run_tests: all 10 10 ./posix_timers 11 11 ./nanosleep 12 - 12 + ./inconsistency-check 13 13 clean: 14 14 rm -f ${bins}
+204
tools/testing/selftests/timers/inconsistency-check.c
··· 1 + /* Time inconsistency check test 2 + * by: john stultz (johnstul@us.ibm.com) 3 + * (C) Copyright IBM 2003, 2004, 2005, 2012 4 + * (C) Copyright Linaro Limited 2015 5 + * Licensed under the GPLv2 6 + * 7 + * To build: 8 + * $ gcc inconsistency-check.c -o inconsistency-check -lrt 9 + * 10 + * This program is free software: you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation, either version 2 of the License, or 13 + * (at your option) any later version. 14 + * 15 + * This program is distributed in the hope that it will be useful, 16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 + * GNU General Public License for more details. 19 + */ 20 + 21 + 22 + 23 + #include <stdio.h> 24 + #include <unistd.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 + #ifdef KTEST 32 + #include "../kselftest.h" 33 + #else 34 + static inline int ksft_exit_pass(void) 35 + { 36 + exit(0); 37 + } 38 + static inline int ksft_exit_fail(void) 39 + { 40 + exit(1); 41 + } 42 + #endif 43 + 44 + #define CALLS_PER_LOOP 64 45 + #define NSEC_PER_SEC 1000000000ULL 46 + 47 + #define CLOCK_REALTIME 0 48 + #define CLOCK_MONOTONIC 1 49 + #define CLOCK_PROCESS_CPUTIME_ID 2 50 + #define CLOCK_THREAD_CPUTIME_ID 3 51 + #define CLOCK_MONOTONIC_RAW 4 52 + #define CLOCK_REALTIME_COARSE 5 53 + #define CLOCK_MONOTONIC_COARSE 6 54 + #define CLOCK_BOOTTIME 7 55 + #define CLOCK_REALTIME_ALARM 8 56 + #define CLOCK_BOOTTIME_ALARM 9 57 + #define CLOCK_HWSPECIFIC 10 58 + #define CLOCK_TAI 11 59 + #define NR_CLOCKIDS 12 60 + 61 + char *clockstring(int clockid) 62 + { 63 + switch (clockid) { 64 + case CLOCK_REALTIME: 65 + return "CLOCK_REALTIME"; 66 + case CLOCK_MONOTONIC: 67 + return "CLOCK_MONOTONIC"; 68 + case CLOCK_PROCESS_CPUTIME_ID: 69 + return "CLOCK_PROCESS_CPUTIME_ID"; 70 + case CLOCK_THREAD_CPUTIME_ID: 71 + return "CLOCK_THREAD_CPUTIME_ID"; 72 + case CLOCK_MONOTONIC_RAW: 73 + return "CLOCK_MONOTONIC_RAW"; 74 + case CLOCK_REALTIME_COARSE: 75 + return "CLOCK_REALTIME_COARSE"; 76 + case CLOCK_MONOTONIC_COARSE: 77 + return "CLOCK_MONOTONIC_COARSE"; 78 + case CLOCK_BOOTTIME: 79 + return "CLOCK_BOOTTIME"; 80 + case CLOCK_REALTIME_ALARM: 81 + return "CLOCK_REALTIME_ALARM"; 82 + case CLOCK_BOOTTIME_ALARM: 83 + return "CLOCK_BOOTTIME_ALARM"; 84 + case CLOCK_TAI: 85 + return "CLOCK_TAI"; 86 + }; 87 + return "UNKNOWN_CLOCKID"; 88 + } 89 + 90 + /* returns 1 if a <= b, 0 otherwise */ 91 + static inline int in_order(struct timespec a, struct timespec b) 92 + { 93 + /* use unsigned to avoid false positives on 2038 rollover */ 94 + if ((unsigned long)a.tv_sec < (unsigned long)b.tv_sec) 95 + return 1; 96 + if ((unsigned long)a.tv_sec > (unsigned long)b.tv_sec) 97 + return 0; 98 + if (a.tv_nsec > b.tv_nsec) 99 + return 0; 100 + return 1; 101 + } 102 + 103 + 104 + 105 + int consistency_test(int clock_type, unsigned long seconds) 106 + { 107 + struct timespec list[CALLS_PER_LOOP]; 108 + int i, inconsistent; 109 + long now, then; 110 + time_t t; 111 + char *start_str; 112 + 113 + clock_gettime(clock_type, &list[0]); 114 + now = then = list[0].tv_sec; 115 + 116 + /* timestamp start of test */ 117 + t = time(0); 118 + start_str = ctime(&t); 119 + 120 + while (seconds == -1 || now - then < seconds) { 121 + inconsistent = 0; 122 + 123 + /* Fill list */ 124 + for (i = 0; i < CALLS_PER_LOOP; i++) 125 + clock_gettime(clock_type, &list[i]); 126 + 127 + /* Check for inconsistencies */ 128 + for (i = 0; i < CALLS_PER_LOOP - 1; i++) 129 + if (!in_order(list[i], list[i+1])) 130 + inconsistent = i; 131 + 132 + /* display inconsistency */ 133 + if (inconsistent) { 134 + unsigned long long delta; 135 + 136 + printf("\%s\n", start_str); 137 + for (i = 0; i < CALLS_PER_LOOP; i++) { 138 + if (i == inconsistent) 139 + printf("--------------------\n"); 140 + printf("%lu:%lu\n", list[i].tv_sec, 141 + list[i].tv_nsec); 142 + if (i == inconsistent + 1) 143 + printf("--------------------\n"); 144 + } 145 + delta = list[inconsistent].tv_sec * NSEC_PER_SEC; 146 + delta += list[inconsistent].tv_nsec; 147 + delta -= list[inconsistent+1].tv_sec * NSEC_PER_SEC; 148 + delta -= list[inconsistent+1].tv_nsec; 149 + printf("Delta: %llu ns\n", delta); 150 + fflush(0); 151 + /* timestamp inconsistency*/ 152 + t = time(0); 153 + printf("%s\n", ctime(&t)); 154 + printf("[FAILED]\n"); 155 + return -1; 156 + } 157 + now = list[0].tv_sec; 158 + } 159 + printf("[OK]\n"); 160 + return 0; 161 + } 162 + 163 + 164 + int main(int argc, char *argv[]) 165 + { 166 + int clockid, opt; 167 + int userclock = CLOCK_REALTIME; 168 + int maxclocks = NR_CLOCKIDS; 169 + int runtime = 30; 170 + struct timespec ts; 171 + 172 + /* Process arguments */ 173 + while ((opt = getopt(argc, argv, "t:c:")) != -1) { 174 + switch (opt) { 175 + case 't': 176 + runtime = atoi(optarg); 177 + break; 178 + case 'c': 179 + userclock = atoi(optarg); 180 + maxclocks = userclock + 1; 181 + break; 182 + default: 183 + printf("Usage: %s [-t <secs>] [-c <clockid>]\n", argv[0]); 184 + printf(" -t: Number of seconds to run\n"); 185 + printf(" -c: clockid to use (default, all clockids)\n"); 186 + exit(-1); 187 + } 188 + } 189 + 190 + setbuf(stdout, NULL); 191 + 192 + for (clockid = userclock; clockid < maxclocks; clockid++) { 193 + 194 + if (clockid == CLOCK_HWSPECIFIC) 195 + continue; 196 + 197 + if (!clock_gettime(clockid, &ts)) { 198 + printf("Consistent %-30s ", clockstring(clockid)); 199 + if (consistency_test(clockid, runtime)) 200 + return ksft_exit_fail(); 201 + } 202 + } 203 + return ksft_exit_pass(); 204 + }