Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2013 Red Hat, Inc., Frederic Weisbecker <fweisbec@redhat.com>
  4 *
 
 
  5 * Selftests for a few posix timers interface.
  6 *
  7 * Kernel loop code stolen from Steven Rostedt <srostedt@redhat.com>
  8 */
  9#define _GNU_SOURCE
 10#include <sys/time.h>
 11#include <sys/types.h>
 12#include <stdio.h>
 13#include <signal.h>
 14#include <stdint.h>
 15#include <string.h>
 16#include <unistd.h>
 17#include <time.h>
 18#include <include/vdso/time64.h>
 19#include <pthread.h>
 20
 21#include "../kselftest.h"
 22
 23#define DELAY 2
 24
 25static void __fatal_error(const char *test, const char *name, const char *what)
 26{
 27	char buf[64];
 28	char *ret_str = NULL;
 29
 30	ret_str = strerror_r(errno, buf, sizeof(buf));
 31
 32	if (name && strlen(name) && ret_str)
 33		ksft_exit_fail_msg("%s %s %s %s\n", test, name, what, ret_str);
 34	else if (ret_str)
 35		ksft_exit_fail_msg("%s %s %s\n", test, what, ret_str);
 36	else
 37		ksft_exit_fail_msg("%s %s\n", test, what);
 38
 39}
 40
 41#define fatal_error(name, what)	__fatal_error(__func__, name, what)
 42
 43static volatile int done;
 44
 45/* Busy loop in userspace to elapse ITIMER_VIRTUAL */
 46static void user_loop(void)
 47{
 48	while (!done);
 49}
 50
 51/*
 52 * Try to spend as much time as possible in kernelspace
 53 * to elapse ITIMER_PROF.
 54 */
 55static void kernel_loop(void)
 56{
 57	void *addr = sbrk(0);
 58	int err = 0;
 59
 60	while (!done && !err) {
 61		err = brk(addr + 4096);
 62		err |= brk(addr);
 63	}
 64}
 65
 66/*
 67 * Sleep until ITIMER_REAL expiration.
 68 */
 69static void idle_loop(void)
 70{
 71	pause();
 72}
 73
 74static void sig_handler(int nr)
 75{
 76	done = 1;
 77}
 78
 79/*
 80 * Check the expected timer expiration matches the GTOD elapsed delta since
 81 * we armed the timer. Keep a 0.5 sec error margin due to various jitter.
 82 */
 83static int check_diff(struct timeval start, struct timeval end)
 84{
 85	long long diff;
 86
 87	diff = end.tv_usec - start.tv_usec;
 88	diff += (end.tv_sec - start.tv_sec) * USEC_PER_SEC;
 89
 90	if (llabs(diff - DELAY * USEC_PER_SEC) > USEC_PER_SEC / 2) {
 91		printf("Diff too high: %lld..", diff);
 92		return -1;
 93	}
 94
 95	return 0;
 96}
 97
 98static void check_itimer(int which, const char *name)
 99{
 
100	struct timeval start, end;
101	struct itimerval val = {
102		.it_value.tv_sec = DELAY,
103	};
104
 
 
 
 
 
 
 
 
 
 
 
105	done = 0;
106
107	if (which == ITIMER_VIRTUAL)
108		signal(SIGVTALRM, sig_handler);
109	else if (which == ITIMER_PROF)
110		signal(SIGPROF, sig_handler);
111	else if (which == ITIMER_REAL)
112		signal(SIGALRM, sig_handler);
113
114	if (gettimeofday(&start, NULL) < 0)
115		fatal_error(name, "gettimeofday()");
 
 
 
116
117	if (setitimer(which, &val, NULL) < 0)
118		fatal_error(name, "setitimer()");
 
 
 
119
120	if (which == ITIMER_VIRTUAL)
121		user_loop();
122	else if (which == ITIMER_PROF)
123		kernel_loop();
124	else if (which == ITIMER_REAL)
125		idle_loop();
126
127	if (gettimeofday(&end, NULL) < 0)
128		fatal_error(name, "gettimeofday()");
 
 
 
 
 
 
 
 
129
130	ksft_test_result(check_diff(start, end) == 0, "%s\n", name);
131}
132
133static void check_timer_create(int which, const char *name)
134{
 
 
135	struct timeval start, end;
136	struct itimerspec val = {
137		.it_value.tv_sec = DELAY,
138	};
139	timer_t id;
140
141	done = 0;
142
143	if (timer_create(which, NULL, &id) < 0)
144		fatal_error(name, "timer_create()");
145
146	if (signal(SIGALRM, sig_handler) == SIG_ERR)
147		fatal_error(name, "signal()");
148
149	if (gettimeofday(&start, NULL) < 0)
150		fatal_error(name, "gettimeofday()");
151
152	if (timer_settime(id, 0, &val, NULL) < 0)
153		fatal_error(name, "timer_settime()");
154
155	user_loop();
156
157	if (gettimeofday(&end, NULL) < 0)
158		fatal_error(name, "gettimeofday()");
159
160	ksft_test_result(check_diff(start, end) == 0,
161			 "timer_create() per %s\n", name);
162}
163
164static pthread_t ctd_thread;
165static volatile int ctd_count, ctd_failed;
166
167static void ctd_sighandler(int sig)
168{
169	if (pthread_self() != ctd_thread)
170		ctd_failed = 1;
171	ctd_count--;
172}
173
174static void *ctd_thread_func(void *arg)
175{
176	struct itimerspec val = {
177		.it_value.tv_sec = 0,
178		.it_value.tv_nsec = 1000 * 1000,
179		.it_interval.tv_sec = 0,
180		.it_interval.tv_nsec = 1000 * 1000,
181	};
182	timer_t id;
183
184	/* 1/10 seconds to ensure the leader sleeps */
185	usleep(10000);
186
187	ctd_count = 100;
188	if (timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id))
189		fatal_error(NULL, "timer_create()");
190	if (timer_settime(id, 0, &val, NULL))
191		fatal_error(NULL, "timer_settime()");
192	while (ctd_count > 0 && !ctd_failed)
193		;
194
195	if (timer_delete(id))
196		fatal_error(NULL, "timer_delete()");
197
198	return NULL;
199}
200
201/*
202 * Test that only the running thread receives the timer signal.
203 */
204static void check_timer_distribution(void)
205{
206	if (signal(SIGALRM, ctd_sighandler) == SIG_ERR)
207		fatal_error(NULL, "signal()");
208
209	if (pthread_create(&ctd_thread, NULL, ctd_thread_func, NULL))
210		fatal_error(NULL, "pthread_create()");
211
212	if (pthread_join(ctd_thread, NULL))
213		fatal_error(NULL, "pthread_join()");
214
215	if (!ctd_failed)
216		ksft_test_result_pass("check signal distribution\n");
217	else if (ksft_min_kernel_version(6, 3))
218		ksft_test_result_fail("check signal distribution\n");
219	else
220		ksft_test_result_skip("check signal distribution (old kernel)\n");
221}
222
223struct tmrsig {
224	int	signals;
225	int	overruns;
226};
227
228static void siginfo_handler(int sig, siginfo_t *si, void *uc)
229{
230	struct tmrsig *tsig = si ? si->si_ptr : NULL;
231
232	if (tsig) {
233		tsig->signals++;
234		tsig->overruns += si->si_overrun;
235	}
236}
237
238static void *ignore_thread(void *arg)
239{
240	unsigned int *tid = arg;
241	sigset_t set;
242
243	sigemptyset(&set);
244	sigaddset(&set, SIGUSR1);
245	if (sigprocmask(SIG_BLOCK, &set, NULL))
246		fatal_error(NULL, "sigprocmask(SIG_BLOCK)");
247
248	*tid = gettid();
249	sleep(100);
250
251	if (sigprocmask(SIG_UNBLOCK, &set, NULL))
252		fatal_error(NULL, "sigprocmask(SIG_UNBLOCK)");
253	return NULL;
254}
255
256static void check_sig_ign(int thread)
257{
258	struct tmrsig tsig = { };
259	struct itimerspec its;
260	unsigned int tid = 0;
261	struct sigaction sa;
262	struct sigevent sev;
263	pthread_t pthread;
264	timer_t timerid;
265	sigset_t set;
266
267	if (thread) {
268		if (pthread_create(&pthread, NULL, ignore_thread, &tid))
269			fatal_error(NULL, "pthread_create()");
270		sleep(1);
271	}
272
273	sa.sa_flags = SA_SIGINFO;
274	sa.sa_sigaction = siginfo_handler;
275	sigemptyset(&sa.sa_mask);
276	if (sigaction(SIGUSR1, &sa, NULL))
277		fatal_error(NULL, "sigaction()");
278
279	/* Block the signal */
280	sigemptyset(&set);
281	sigaddset(&set, SIGUSR1);
282	if (sigprocmask(SIG_BLOCK, &set, NULL))
283		fatal_error(NULL, "sigprocmask(SIG_BLOCK)");
284
285	memset(&sev, 0, sizeof(sev));
286	sev.sigev_notify = SIGEV_SIGNAL;
287	sev.sigev_signo = SIGUSR1;
288	sev.sigev_value.sival_ptr = &tsig;
289	if (thread) {
290		sev.sigev_notify = SIGEV_THREAD_ID;
291		sev._sigev_un._tid = tid;
292	}
 
293
294	if (timer_create(CLOCK_MONOTONIC, &sev, &timerid))
295		fatal_error(NULL, "timer_create()");
296
297	/* Start the timer to expire in 100ms and 100ms intervals */
298	its.it_value.tv_sec = 0;
299	its.it_value.tv_nsec = 100000000;
300	its.it_interval.tv_sec = 0;
301	its.it_interval.tv_nsec = 100000000;
302	timer_settime(timerid, 0, &its, NULL);
303
304	sleep(1);
305
306	/* Set the signal to be ignored */
307	if (signal(SIGUSR1, SIG_IGN) == SIG_ERR)
308		fatal_error(NULL, "signal(SIG_IGN)");
309
310	sleep(1);
311
312	if (thread) {
313		/* Stop the thread first. No signal should be delivered to it */
314		if (pthread_cancel(pthread))
315			fatal_error(NULL, "pthread_cancel()");
316		if (pthread_join(pthread, NULL))
317			fatal_error(NULL, "pthread_join()");
318	}
319
320	/* Restore the handler */
321	if (sigaction(SIGUSR1, &sa, NULL))
322		fatal_error(NULL, "sigaction()");
323
324	sleep(1);
325
326	/* Unblock it, which should deliver the signal in the !thread case*/
327	if (sigprocmask(SIG_UNBLOCK, &set, NULL))
328		fatal_error(NULL, "sigprocmask(SIG_UNBLOCK)");
329
330	if (timer_delete(timerid))
331		fatal_error(NULL, "timer_delete()");
332
333	if (!thread) {
334		ksft_test_result(tsig.signals == 1 && tsig.overruns == 29,
335				 "check_sig_ign SIGEV_SIGNAL\n");
336	} else {
337		ksft_test_result(tsig.signals == 0 && tsig.overruns == 0,
338				 "check_sig_ign SIGEV_THREAD_ID\n");
339	}
340}
341
342static void check_rearm(void)
343{
344	struct tmrsig tsig = { };
345	struct itimerspec its;
346	struct sigaction sa;
347	struct sigevent sev;
348	timer_t timerid;
349	sigset_t set;
350
351	sa.sa_flags = SA_SIGINFO;
352	sa.sa_sigaction = siginfo_handler;
353	sigemptyset(&sa.sa_mask);
354	if (sigaction(SIGUSR1, &sa, NULL))
355		fatal_error(NULL, "sigaction()");
356
357	/* Block the signal */
358	sigemptyset(&set);
359	sigaddset(&set, SIGUSR1);
360	if (sigprocmask(SIG_BLOCK, &set, NULL))
361		fatal_error(NULL, "sigprocmask(SIG_BLOCK)");
362
363	memset(&sev, 0, sizeof(sev));
364	sev.sigev_notify = SIGEV_SIGNAL;
365	sev.sigev_signo = SIGUSR1;
366	sev.sigev_value.sival_ptr = &tsig;
367	if (timer_create(CLOCK_MONOTONIC, &sev, &timerid))
368		fatal_error(NULL, "timer_create()");
369
370	/* Start the timer to expire in 100ms and 100ms intervals */
371	its.it_value.tv_sec = 0;
372	its.it_value.tv_nsec = 100000000;
373	its.it_interval.tv_sec = 0;
374	its.it_interval.tv_nsec = 100000000;
375	if (timer_settime(timerid, 0, &its, NULL))
376		fatal_error(NULL, "timer_settime()");
377
378	sleep(1);
379
380	/* Reprogram the timer to single shot */
381	its.it_value.tv_sec = 10;
382	its.it_value.tv_nsec = 0;
383	its.it_interval.tv_sec = 0;
384	its.it_interval.tv_nsec = 0;
385	if (timer_settime(timerid, 0, &its, NULL))
386		fatal_error(NULL, "timer_settime()");
387
388	/* Unblock it, which should not deliver a signal */
389	if (sigprocmask(SIG_UNBLOCK, &set, NULL))
390		fatal_error(NULL, "sigprocmask(SIG_UNBLOCK)");
391
392	if (timer_delete(timerid))
393		fatal_error(NULL, "timer_delete()");
394
395	ksft_test_result(!tsig.signals, "check_rearm\n");
396}
397
398static void check_delete(void)
399{
400	struct tmrsig tsig = { };
401	struct itimerspec its;
402	struct sigaction sa;
403	struct sigevent sev;
404	timer_t timerid;
405	sigset_t set;
406
407	sa.sa_flags = SA_SIGINFO;
408	sa.sa_sigaction = siginfo_handler;
409	sigemptyset(&sa.sa_mask);
410	if (sigaction(SIGUSR1, &sa, NULL))
411		fatal_error(NULL, "sigaction()");
412
413	/* Block the signal */
414	sigemptyset(&set);
415	sigaddset(&set, SIGUSR1);
416	if (sigprocmask(SIG_BLOCK, &set, NULL))
417		fatal_error(NULL, "sigprocmask(SIG_BLOCK)");
418
419	memset(&sev, 0, sizeof(sev));
420	sev.sigev_notify = SIGEV_SIGNAL;
421	sev.sigev_signo = SIGUSR1;
422	sev.sigev_value.sival_ptr = &tsig;
423	if (timer_create(CLOCK_MONOTONIC, &sev, &timerid))
424		fatal_error(NULL, "timer_create()");
425
426	/* Start the timer to expire in 100ms and 100ms intervals */
427	its.it_value.tv_sec = 0;
428	its.it_value.tv_nsec = 100000000;
429	its.it_interval.tv_sec = 0;
430	its.it_interval.tv_nsec = 100000000;
431	if (timer_settime(timerid, 0, &its, NULL))
432		fatal_error(NULL, "timer_settime()");
433
434	sleep(1);
435
436	if (timer_delete(timerid))
437		fatal_error(NULL, "timer_delete()");
438
439	/* Unblock it, which should not deliver a signal */
440	if (sigprocmask(SIG_UNBLOCK, &set, NULL))
441		fatal_error(NULL, "sigprocmask(SIG_UNBLOCK)");
442
443	ksft_test_result(!tsig.signals, "check_delete\n");
444}
445
446static inline int64_t calcdiff_ns(struct timespec t1, struct timespec t2)
447{
448	int64_t diff;
449
450	diff = NSEC_PER_SEC * (int64_t)((int) t1.tv_sec - (int) t2.tv_sec);
451	diff += ((int) t1.tv_nsec - (int) t2.tv_nsec);
452	return diff;
453}
454
455static void check_sigev_none(int which, const char *name)
456{
457	struct timespec start, now;
458	struct itimerspec its;
459	struct sigevent sev;
460	timer_t timerid;
461
462	memset(&sev, 0, sizeof(sev));
463	sev.sigev_notify = SIGEV_NONE;
464
465	if (timer_create(which, &sev, &timerid))
466		fatal_error(name, "timer_create()");
467
468	/* Start the timer to expire in 100ms and 100ms intervals */
469	its.it_value.tv_sec = 0;
470	its.it_value.tv_nsec = 100000000;
471	its.it_interval.tv_sec = 0;
472	its.it_interval.tv_nsec = 100000000;
473	timer_settime(timerid, 0, &its, NULL);
474
475	if (clock_gettime(which, &start))
476		fatal_error(name, "clock_gettime()");
477
478	do {
479		if (clock_gettime(which, &now))
480			fatal_error(name, "clock_gettime()");
481	} while (calcdiff_ns(now, start) < NSEC_PER_SEC);
482
483	if (timer_gettime(timerid, &its))
484		fatal_error(name, "timer_gettime()");
485
486	if (timer_delete(timerid))
487		fatal_error(name, "timer_delete()");
488
489	ksft_test_result(its.it_value.tv_sec || its.it_value.tv_nsec,
490			 "check_sigev_none %s\n", name);
491}
492
493static void check_gettime(int which, const char *name)
494{
495	struct itimerspec its, prev;
496	struct timespec start, now;
497	struct sigevent sev;
498	timer_t timerid;
499	int wraps = 0;
500	sigset_t set;
501
502	/* Block the signal */
503	sigemptyset(&set);
504	sigaddset(&set, SIGUSR1);
505	if (sigprocmask(SIG_BLOCK, &set, NULL))
506		fatal_error(name, "sigprocmask(SIG_BLOCK)");
507
508	memset(&sev, 0, sizeof(sev));
509	sev.sigev_notify = SIGEV_SIGNAL;
510	sev.sigev_signo = SIGUSR1;
511
512	if (timer_create(which, &sev, &timerid))
513		fatal_error(name, "timer_create()");
514
515	/* Start the timer to expire in 100ms and 100ms intervals */
516	its.it_value.tv_sec = 0;
517	its.it_value.tv_nsec = 100000000;
518	its.it_interval.tv_sec = 0;
519	its.it_interval.tv_nsec = 100000000;
520	if (timer_settime(timerid, 0, &its, NULL))
521		fatal_error(name, "timer_settime()");
522
523	if (timer_gettime(timerid, &prev))
524		fatal_error(name, "timer_gettime()");
525
526	if (clock_gettime(which, &start))
527		fatal_error(name, "clock_gettime()");
528
529	do {
530		if (clock_gettime(which, &now))
531			fatal_error(name, "clock_gettime()");
532		if (timer_gettime(timerid, &its))
533			fatal_error(name, "timer_gettime()");
534		if (its.it_value.tv_nsec > prev.it_value.tv_nsec)
535			wraps++;
536		prev = its;
537
538	} while (calcdiff_ns(now, start) < NSEC_PER_SEC);
 
 
 
 
539
540	if (timer_delete(timerid))
541		fatal_error(name, "timer_delete()");
 
 
542
543	ksft_test_result(wraps > 1, "check_gettime %s\n", name);
544}
545
546static void check_overrun(int which, const char *name)
547{
548	struct timespec start, now;
549	struct tmrsig tsig = { };
550	struct itimerspec its;
551	struct sigaction sa;
552	struct sigevent sev;
553	timer_t timerid;
554	sigset_t set;
555
556	sa.sa_flags = SA_SIGINFO;
557	sa.sa_sigaction = siginfo_handler;
558	sigemptyset(&sa.sa_mask);
559	if (sigaction(SIGUSR1, &sa, NULL))
560		fatal_error(name, "sigaction()");
561
562	/* Block the signal */
563	sigemptyset(&set);
564	sigaddset(&set, SIGUSR1);
565	if (sigprocmask(SIG_BLOCK, &set, NULL))
566		fatal_error(name, "sigprocmask(SIG_BLOCK)");
567
568	memset(&sev, 0, sizeof(sev));
569	sev.sigev_notify = SIGEV_SIGNAL;
570	sev.sigev_signo = SIGUSR1;
571	sev.sigev_value.sival_ptr = &tsig;
572	if (timer_create(which, &sev, &timerid))
573		fatal_error(name, "timer_create()");
574
575	/* Start the timer to expire in 100ms and 100ms intervals */
576	its.it_value.tv_sec = 0;
577	its.it_value.tv_nsec = 100000000;
578	its.it_interval.tv_sec = 0;
579	its.it_interval.tv_nsec = 100000000;
580	if (timer_settime(timerid, 0, &its, NULL))
581		fatal_error(name, "timer_settime()");
582
583	if (clock_gettime(which, &start))
584		fatal_error(name, "clock_gettime()");
585
586	do {
587		if (clock_gettime(which, &now))
588			fatal_error(name, "clock_gettime()");
589	} while (calcdiff_ns(now, start) < NSEC_PER_SEC);
590
591	/* Unblock it, which should deliver a signal */
592	if (sigprocmask(SIG_UNBLOCK, &set, NULL))
593		fatal_error(name, "sigprocmask(SIG_UNBLOCK)");
594
595	if (timer_delete(timerid))
596		fatal_error(name, "timer_delete()");
597
598	ksft_test_result(tsig.signals == 1 && tsig.overruns == 9,
599			 "check_overrun %s\n", name);
600}
601
602int main(int argc, char **argv)
603{
604	ksft_print_header();
605	ksft_set_plan(18);
606
607	ksft_print_msg("Testing posix timers. False negative may happen on CPU execution \n");
608	ksft_print_msg("based timers if other threads run on the CPU...\n");
609
610	check_itimer(ITIMER_VIRTUAL, "ITIMER_VIRTUAL");
611	check_itimer(ITIMER_PROF, "ITIMER_PROF");
612	check_itimer(ITIMER_REAL, "ITIMER_REAL");
613	check_timer_create(CLOCK_THREAD_CPUTIME_ID, "CLOCK_THREAD_CPUTIME_ID");
614
615	/*
616	 * It's unfortunately hard to reliably test a timer expiration
617	 * on parallel multithread cputime. We could arm it to expire
618	 * on DELAY * nr_threads, with nr_threads busy looping, then wait
619	 * the normal DELAY since the time is elapsing nr_threads faster.
620	 * But for that we need to ensure we have real physical free CPUs
621	 * to ensure true parallelism. So test only one thread until we
622	 * find a better solution.
623	 */
624	check_timer_create(CLOCK_PROCESS_CPUTIME_ID, "CLOCK_PROCESS_CPUTIME_ID");
625	check_timer_distribution();
626
627	check_sig_ign(0);
628	check_sig_ign(1);
629	check_rearm();
630	check_delete();
631	check_sigev_none(CLOCK_MONOTONIC, "CLOCK_MONOTONIC");
632	check_sigev_none(CLOCK_PROCESS_CPUTIME_ID, "CLOCK_PROCESS_CPUTIME_ID");
633	check_gettime(CLOCK_MONOTONIC, "CLOCK_MONOTONIC");
634	check_gettime(CLOCK_PROCESS_CPUTIME_ID, "CLOCK_PROCESS_CPUTIME_ID");
635	check_gettime(CLOCK_THREAD_CPUTIME_ID, "CLOCK_THREAD_CPUTIME_ID");
636	check_overrun(CLOCK_MONOTONIC, "CLOCK_MONOTONIC");
637	check_overrun(CLOCK_PROCESS_CPUTIME_ID, "CLOCK_PROCESS_CPUTIME_ID");
638	check_overrun(CLOCK_THREAD_CPUTIME_ID, "CLOCK_THREAD_CPUTIME_ID");
639
640	ksft_finished();
641}
v4.6
 
  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#include "../kselftest.h"
 19
 20#define DELAY 2
 21#define USECS_PER_SEC 1000000
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 22
 23static volatile int done;
 24
 25/* Busy loop in userspace to elapse ITIMER_VIRTUAL */
 26static void user_loop(void)
 27{
 28	while (!done);
 29}
 30
 31/*
 32 * Try to spend as much time as possible in kernelspace
 33 * to elapse ITIMER_PROF.
 34 */
 35static void kernel_loop(void)
 36{
 37	void *addr = sbrk(0);
 38	int err = 0;
 39
 40	while (!done && !err) {
 41		err = brk(addr + 4096);
 42		err |= brk(addr);
 43	}
 44}
 45
 46/*
 47 * Sleep until ITIMER_REAL expiration.
 48 */
 49static void idle_loop(void)
 50{
 51	pause();
 52}
 53
 54static void sig_handler(int nr)
 55{
 56	done = 1;
 57}
 58
 59/*
 60 * Check the expected timer expiration matches the GTOD elapsed delta since
 61 * we armed the timer. Keep a 0.5 sec error margin due to various jitter.
 62 */
 63static int check_diff(struct timeval start, struct timeval end)
 64{
 65	long long diff;
 66
 67	diff = end.tv_usec - start.tv_usec;
 68	diff += (end.tv_sec - start.tv_sec) * USECS_PER_SEC;
 69
 70	if (abs(diff - DELAY * USECS_PER_SEC) > USECS_PER_SEC / 2) {
 71		printf("Diff too high: %lld..", diff);
 72		return -1;
 73	}
 74
 75	return 0;
 76}
 77
 78static int check_itimer(int which)
 79{
 80	int err;
 81	struct timeval start, end;
 82	struct itimerval val = {
 83		.it_value.tv_sec = DELAY,
 84	};
 85
 86	printf("Check itimer ");
 87
 88	if (which == ITIMER_VIRTUAL)
 89		printf("virtual... ");
 90	else if (which == ITIMER_PROF)
 91		printf("prof... ");
 92	else if (which == ITIMER_REAL)
 93		printf("real... ");
 94
 95	fflush(stdout);
 96
 97	done = 0;
 98
 99	if (which == ITIMER_VIRTUAL)
100		signal(SIGVTALRM, sig_handler);
101	else if (which == ITIMER_PROF)
102		signal(SIGPROF, sig_handler);
103	else if (which == ITIMER_REAL)
104		signal(SIGALRM, sig_handler);
105
106	err = gettimeofday(&start, NULL);
107	if (err < 0) {
108		perror("Can't call gettimeofday()\n");
109		return -1;
110	}
111
112	err = setitimer(which, &val, NULL);
113	if (err < 0) {
114		perror("Can't set timer\n");
115		return -1;
116	}
117
118	if (which == ITIMER_VIRTUAL)
119		user_loop();
120	else if (which == ITIMER_PROF)
121		kernel_loop();
122	else if (which == ITIMER_REAL)
123		idle_loop();
124
125	gettimeofday(&end, NULL);
126	if (err < 0) {
127		perror("Can't call gettimeofday()\n");
128		return -1;
129	}
130
131	if (!check_diff(start, end))
132		printf("[OK]\n");
133	else
134		printf("[FAIL]\n");
135
136	return 0;
137}
138
139static int check_timer_create(int which)
140{
141	int err;
142	timer_t id;
143	struct timeval start, end;
144	struct itimerspec val = {
145		.it_value.tv_sec = DELAY,
146	};
 
147
148	printf("Check timer_create() ");
149	if (which == CLOCK_THREAD_CPUTIME_ID) {
150		printf("per thread... ");
151	} else if (which == CLOCK_PROCESS_CPUTIME_ID) {
152		printf("per process... ");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153	}
154	fflush(stdout);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
156	done = 0;
157	err = timer_create(which, NULL, &id);
158	if (err < 0) {
159		perror("Can't create timer\n");
160		return -1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161	}
162	signal(SIGALRM, sig_handler);
163
164	err = gettimeofday(&start, NULL);
165	if (err < 0) {
166		perror("Can't call gettimeofday()\n");
167		return -1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168	}
169
170	err = timer_settime(id, 0, &val, NULL);
171	if (err < 0) {
172		perror("Can't set timer\n");
173		return -1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
176	user_loop();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
178	gettimeofday(&end, NULL);
179	if (err < 0) {
180		perror("Can't call gettimeofday()\n");
181		return -1;
182	}
183
184	if (!check_diff(start, end))
185		printf("[OK]\n");
186	else
187		printf("[FAIL]\n");
188
189	return 0;
190}
191
192int main(int argc, char **argv)
193{
194	printf("Testing posix timers. False negative may happen on CPU execution \n");
195	printf("based timers if other threads run on the CPU...\n");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
197	if (check_itimer(ITIMER_VIRTUAL) < 0)
198		return ksft_exit_fail();
 
199
200	if (check_itimer(ITIMER_PROF) < 0)
201		return ksft_exit_fail();
 
 
202
203	if (check_itimer(ITIMER_REAL) < 0)
204		return ksft_exit_fail();
205
206	if (check_timer_create(CLOCK_THREAD_CPUTIME_ID) < 0)
207		return ksft_exit_fail();
 
 
208
209	/*
210	 * It's unfortunately hard to reliably test a timer expiration
211	 * on parallel multithread cputime. We could arm it to expire
212	 * on DELAY * nr_threads, with nr_threads busy looping, then wait
213	 * the normal DELAY since the time is elapsing nr_threads faster.
214	 * But for that we need to ensure we have real physical free CPUs
215	 * to ensure true parallelism. So test only one thread until we
216	 * find a better solution.
217	 */
218	if (check_timer_create(CLOCK_PROCESS_CPUTIME_ID) < 0)
219		return ksft_exit_fail();
 
 
 
 
 
 
 
 
 
 
 
 
 
220
221	return ksft_exit_pass();
222}