/* * stress_timer_handler() * catch timer signal and cancel if no more runs flagged */ static void MLOCKED_TEXT stress_timer_handler(int sig) { struct itimerspec timer; sigset_t mask; (void)sig; if (!stress_timer_keep_stressing()) goto cancel; timer_counter++; if (sigpending(&mask) == 0) if (sigismember(&mask, SIGINT)) goto cancel; /* High freq timer, check periodically for timeout */ if ((timer_counter & 65535) == 0) if ((time_now() - start) > (double)g_opt_timeout) goto cancel; if (g_keep_stressing_flag) { int ret = timer_getoverrun(timerid); if (ret > 0) overruns += ret; stress_timer_set(&timer); return; } cancel: g_keep_stressing_flag = false; /* Cancel timer if we detect no more runs */ (void)memset(&timer, 0, sizeof(timer)); (void)timer_settime(timerid, 0, &timer, NULL); }
/* * stress_timer * stress timers */ int stress_timer( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { struct sigaction new_action; struct sigevent sev; struct itimerspec timer; (void)instance; if (!set_timer_freq) { if (opt_flags & OPT_FLAGS_MAXIMIZE) opt_timer_freq = MAX_TIMER_FREQ; if (opt_flags & OPT_FLAGS_MINIMIZE) opt_timer_freq = MIN_TIMER_FREQ; } rate_ns = opt_timer_freq ? 1000000000 / opt_timer_freq : 1000000000; new_action.sa_flags = 0; new_action.sa_handler = stress_timer_handler; sigemptyset(&new_action.sa_mask); if (sigaction(SIGRTMIN, &new_action, NULL) < 0) { pr_failed_err(name, "sigaction"); return EXIT_FAILURE; } sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIGRTMIN; sev.sigev_value.sival_ptr = &timerid; if (timer_create(CLOCK_REALTIME, &sev, &timerid) < 0) { pr_failed_err(name, "timer_create"); return EXIT_FAILURE; } stress_timer_set(&timer); if (timer_settime(timerid, 0, &timer, NULL) < 0) { pr_failed_err(name, "timer_settime"); return EXIT_FAILURE; } do { struct timespec req; req.tv_sec = 0; req.tv_nsec = 10000000; (void)nanosleep(&req, NULL); *counter = timer_counter; } while (opt_do_run && (!max_ops || timer_counter < max_ops)); if (timer_delete(timerid) < 0) { pr_failed_err(name, "timer_delete"); return EXIT_FAILURE; } pr_dbg(stderr, "%s: %" PRIu64 " timer overruns (instance %" PRIu32 ")\n", name, overruns, instance); return EXIT_SUCCESS; }
/* * stress_timer * stress timers */ static int stress_timer(const args_t *args) { struct sigevent sev; struct itimerspec timer; sigset_t mask; uint64_t timer_freq = DEFAULT_TIMER_FREQ; (void)sigemptyset(&mask); (void)sigaddset(&mask, SIGINT); (void)sigprocmask(SIG_SETMASK, &mask, NULL); max_ops = args->max_ops; start = time_now(); if (!get_setting("timer-freq", &timer_freq)) { if (g_opt_flags & OPT_FLAGS_MAXIMIZE) timer_freq = MAX_TIMER_FREQ; if (g_opt_flags & OPT_FLAGS_MINIMIZE) timer_freq = MIN_TIMER_FREQ; } rate_ns = timer_freq ? 1000000000.0 / timer_freq : 1000000000.0; if (stress_sighandler(args->name, SIGRTMIN, stress_timer_handler, NULL) < 0) return EXIT_FAILURE; sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIGRTMIN; sev.sigev_value.sival_ptr = &timerid; if (timer_create(CLOCK_REALTIME, &sev, &timerid) < 0) { pr_fail_err("timer_create"); return EXIT_FAILURE; } stress_timer_set(&timer); if (timer_settime(timerid, 0, &timer, NULL) < 0) { pr_fail_err("timer_settime"); return EXIT_FAILURE; } do { struct timespec req; req.tv_sec = 0; req.tv_nsec = 10000000; (void)nanosleep(&req, NULL); set_counter(args, timer_counter); } while (keep_stressing()); if (timer_delete(timerid) < 0) { pr_fail_err("timer_delete"); return EXIT_FAILURE; } pr_dbg("%s: %" PRIu64 " timer overruns (instance %" PRIu32 ")\n", args->name, overruns, args->instance); return EXIT_SUCCESS; }
/* * stress_timer_handler() * catch timer signal and cancel if no more runs flagged */ static void MLOCKED stress_timer_handler(int sig) { struct itimerspec timer; int ret; (void)sig; timer_counter++; ret = timer_getoverrun(timerid); if (ret > 0) overruns += ret; if (opt_do_run) { stress_timer_set(&timer); } else { /* Cancel timer if we detect no more runs */ timer.it_value.tv_sec = 0; timer.it_value.tv_nsec = 0; timer.it_interval.tv_sec = 0; timer.it_interval.tv_nsec = 0; } (void)timer_settime(timerid, 0, &timer, NULL); }