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