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

selftests: add basic posix timers selftests

Add some initial basic tests on a few posix timers interface such as
setitimer() and timer_settime().

These simply check that expiration happens in a reasonable timeframe after
expected elapsed clock time (user time, user + system time, real time,
...).

This is helpful for finding basic breakages while hacking
on this subsystem.

Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Stanislaw Gruszka <sgruszka@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: KOSAKI Motohiro <kosaki.motohiro@gmail.com>
Cc: Olivier Langlois <olivier@trillion01.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

+230
+1
tools/testing/selftests/Makefile
··· 6 6 TARGETS += mqueue 7 7 TARGETS += net 8 8 TARGETS += ptrace 9 + TARGETS += timers 9 10 TARGETS += vm 10 11 11 12 all:
+8
tools/testing/selftests/timers/Makefile
··· 1 + all: 2 + gcc posix_timers.c -o posix_timers -lrt 3 + 4 + run_tests: all 5 + ./posix_timers 6 + 7 + clean: 8 + rm -f ./posix_timers
+221
tools/testing/selftests/timers/posix_timers.c
··· 1 + /* 2 + * Copyright (C) 2013 Red Hat, Inc., Frederic Weisbecker <fweisbec@redhat.com> 3 + * 4 + * Licensed under the terms of the GNU GPL License version 2 5 + * 6 + * Selftests for a few posix timers interface. 7 + * 8 + * Kernel loop code stolen from Steven Rostedt <srostedt@redhat.com> 9 + */ 10 + 11 + #include <sys/time.h> 12 + #include <stdio.h> 13 + #include <signal.h> 14 + #include <unistd.h> 15 + #include <time.h> 16 + #include <pthread.h> 17 + 18 + #define DELAY 2 19 + #define USECS_PER_SEC 1000000 20 + 21 + static volatile int done; 22 + 23 + /* Busy loop in userspace to elapse ITIMER_VIRTUAL */ 24 + static void user_loop(void) 25 + { 26 + while (!done); 27 + } 28 + 29 + /* 30 + * Try to spend as much time as possible in kernelspace 31 + * to elapse ITIMER_PROF. 32 + */ 33 + static void kernel_loop(void) 34 + { 35 + void *addr = sbrk(0); 36 + 37 + while (!done) { 38 + brk(addr + 4096); 39 + brk(addr); 40 + } 41 + } 42 + 43 + /* 44 + * Sleep until ITIMER_REAL expiration. 45 + */ 46 + static void idle_loop(void) 47 + { 48 + pause(); 49 + } 50 + 51 + static void sig_handler(int nr) 52 + { 53 + done = 1; 54 + } 55 + 56 + /* 57 + * Check the expected timer expiration matches the GTOD elapsed delta since 58 + * we armed the timer. Keep a 0.5 sec error margin due to various jitter. 59 + */ 60 + static int check_diff(struct timeval start, struct timeval end) 61 + { 62 + long long diff; 63 + 64 + diff = end.tv_usec - start.tv_usec; 65 + diff += (end.tv_sec - start.tv_sec) * USECS_PER_SEC; 66 + 67 + if (abs(diff - DELAY * USECS_PER_SEC) > USECS_PER_SEC / 2) { 68 + printf("Diff too high: %lld..", diff); 69 + return -1; 70 + } 71 + 72 + return 0; 73 + } 74 + 75 + static int check_itimer(int which) 76 + { 77 + int err; 78 + struct timeval start, end; 79 + struct itimerval val = { 80 + .it_value.tv_sec = DELAY, 81 + }; 82 + 83 + printf("Check itimer "); 84 + 85 + if (which == ITIMER_VIRTUAL) 86 + printf("virtual... "); 87 + else if (which == ITIMER_PROF) 88 + printf("prof... "); 89 + else if (which == ITIMER_REAL) 90 + printf("real... "); 91 + 92 + fflush(stdout); 93 + 94 + done = 0; 95 + 96 + if (which == ITIMER_VIRTUAL) 97 + signal(SIGVTALRM, sig_handler); 98 + else if (which == ITIMER_PROF) 99 + signal(SIGPROF, sig_handler); 100 + else if (which == ITIMER_REAL) 101 + signal(SIGALRM, sig_handler); 102 + 103 + err = gettimeofday(&start, NULL); 104 + if (err < 0) { 105 + perror("Can't call gettimeofday()\n"); 106 + return -1; 107 + } 108 + 109 + err = setitimer(which, &val, NULL); 110 + if (err < 0) { 111 + perror("Can't set timer\n"); 112 + return -1; 113 + } 114 + 115 + if (which == ITIMER_VIRTUAL) 116 + user_loop(); 117 + else if (which == ITIMER_PROF) 118 + kernel_loop(); 119 + else if (which == ITIMER_REAL) 120 + idle_loop(); 121 + 122 + gettimeofday(&end, NULL); 123 + if (err < 0) { 124 + perror("Can't call gettimeofday()\n"); 125 + return -1; 126 + } 127 + 128 + if (!check_diff(start, end)) 129 + printf("[OK]\n"); 130 + else 131 + printf("[FAIL]\n"); 132 + 133 + return 0; 134 + } 135 + 136 + static int check_timer_create(int which) 137 + { 138 + int err; 139 + timer_t id; 140 + struct timeval start, end; 141 + struct itimerspec val = { 142 + .it_value.tv_sec = DELAY, 143 + }; 144 + 145 + printf("Check timer_create() "); 146 + if (which == CLOCK_THREAD_CPUTIME_ID) { 147 + printf("per thread... "); 148 + } else if (which == CLOCK_PROCESS_CPUTIME_ID) { 149 + printf("per process... "); 150 + } 151 + fflush(stdout); 152 + 153 + done = 0; 154 + timer_create(which, NULL, &id); 155 + if (err < 0) { 156 + perror("Can't create timer\n"); 157 + return -1; 158 + } 159 + signal(SIGALRM, sig_handler); 160 + 161 + err = gettimeofday(&start, NULL); 162 + if (err < 0) { 163 + perror("Can't call gettimeofday()\n"); 164 + return -1; 165 + } 166 + 167 + err = timer_settime(id, 0, &val, NULL); 168 + if (err < 0) { 169 + perror("Can't set timer\n"); 170 + return -1; 171 + } 172 + 173 + user_loop(); 174 + 175 + gettimeofday(&end, NULL); 176 + if (err < 0) { 177 + perror("Can't call gettimeofday()\n"); 178 + return -1; 179 + } 180 + 181 + if (!check_diff(start, end)) 182 + printf("[OK]\n"); 183 + else 184 + printf("[FAIL]\n"); 185 + 186 + return 0; 187 + } 188 + 189 + int main(int argc, char **argv) 190 + { 191 + int err; 192 + 193 + printf("Testing posix timers. False negative may happen on CPU execution \n"); 194 + printf("based timers if other threads run on the CPU...\n"); 195 + 196 + if (check_itimer(ITIMER_VIRTUAL) < 0) 197 + return -1; 198 + 199 + if (check_itimer(ITIMER_PROF) < 0) 200 + return -1; 201 + 202 + if (check_itimer(ITIMER_REAL) < 0) 203 + return -1; 204 + 205 + if (check_timer_create(CLOCK_THREAD_CPUTIME_ID) < 0) 206 + return -1; 207 + 208 + /* 209 + * It's unfortunately hard to reliably test a timer expiration 210 + * on parallel multithread cputime. We could arm it to expire 211 + * on DELAY * nr_threads, with nr_threads busy looping, then wait 212 + * the normal DELAY since the time is elapsing nr_threads faster. 213 + * But for that we need to ensure we have real physical free CPUs 214 + * to ensure true parallelism. So test only one thread until we 215 + * find a better solution. 216 + */ 217 + if (check_timer_create(CLOCK_PROCESS_CPUTIME_ID) < 0) 218 + return -1; 219 + 220 + return 0; 221 + }