1 /*
2 * Copyright (C) 2013-2021 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 * This code is a complete clean re-write of the stress tool by
19 * Colin Ian King <colin.king@canonical.com> and attempts to be
20 * backwardly compatible with the stress tool by Amos Waterland
21 * <apw@rossby.metr.ou.edu> but has more stress tests and more
22 * functionality.
23 *
24 */
25 #include "stress-ng.h"
26
27 static const stress_help_t help[] = {
28 { "T N", "timer N", "start N workers producing timer events" },
29 { NULL, "timer-ops N", "stop after N timer bogo events" },
30 { NULL, "timer-freq F", "run timer(s) at F Hz, range 1 to 1000000000" },
31 { NULL, "timer-rand", "enable random timer frequency" },
32 { NULL, NULL, NULL }
33 };
34
35 #if defined(HAVE_LIB_RT) && \
36 defined(HAVE_TIMER_CREATE) && \
37 defined(HAVE_TIMER_DELETE) && \
38 defined(HAVE_TIMER_GETOVERRUN) && \
39 defined(HAVE_TIMER_SETTIME)
40 static volatile uint64_t timer_counter = 0;
41 static uint64_t max_ops;
42 static timer_t timerid;
43 static uint64_t overruns = 0;
44 static double rate_ns;
45 static double start;
46 #endif
47
48 /*
49 * stress_set_timer_freq()
50 * set timer frequency from given option
51 */
stress_set_timer_freq(const char * opt)52 static int stress_set_timer_freq(const char *opt)
53 {
54 uint64_t timer_freq;
55
56 timer_freq = stress_get_uint64(opt);
57 stress_check_range("timer-freq", timer_freq,
58 MIN_TIMER_FREQ, MAX_TIMER_FREQ);
59 return stress_set_setting("timer-freq", TYPE_ID_UINT64, &timer_freq);
60 }
61
stress_set_timer_rand(const char * opt)62 static int stress_set_timer_rand(const char *opt)
63 {
64 bool timer_rand = true;
65
66 (void)opt;
67 return stress_set_setting("timer-rand", TYPE_ID_BOOL, &timer_rand);
68 }
69
70 static const stress_opt_set_func_t opt_set_funcs[] = {
71 { OPT_timer_freq, stress_set_timer_freq },
72 { OPT_timer_rand, stress_set_timer_rand },
73 { 0, NULL }
74 };
75
76 #if defined(HAVE_LIB_RT) && \
77 defined(HAVE_TIMER_CREATE) && \
78 defined(HAVE_TIMER_DELETE) && \
79 defined(HAVE_TIMER_GETOVERRUN) && \
80 defined(HAVE_TIMER_SETTIME)
81
82 /*
83 * stress_timer_set()
84 * set timer, ensure it is never zero
85 */
stress_timer_set(struct itimerspec * timer)86 static void stress_timer_set(struct itimerspec *timer)
87 {
88 double rate;
89 bool timer_rand = false;
90
91 (void)stress_get_setting("timer-rand", &timer_rand);
92
93 if (timer_rand) {
94 /* Mix in some random variation */
95 double r = ((double)(stress_mwc32() % 10000) - 5000.0) / 40000.0;
96 rate = rate_ns + (rate_ns * r);
97 } else {
98 rate = rate_ns;
99 }
100
101 timer->it_value.tv_sec = (time_t)rate / STRESS_NANOSECOND;
102 timer->it_value.tv_nsec = (suseconds_t)rate % STRESS_NANOSECOND;
103 if (timer->it_value.tv_sec == 0 &&
104 timer->it_value.tv_nsec < 1)
105 timer->it_value.tv_nsec = 1;
106
107 timer->it_interval.tv_sec = timer->it_value.tv_sec;
108 timer->it_interval.tv_nsec = timer->it_value.tv_nsec;
109 }
110
111 /*
112 * stress_timer_keep_stressing(args)
113 * returns true if we can keep on running a stressor
114 */
stress_timer_keep_stressing(void)115 static bool HOT OPTIMIZE3 stress_timer_keep_stressing(void)
116 {
117 return (LIKELY(keep_stressing_flag()) &&
118 LIKELY(!max_ops || (timer_counter < max_ops)));
119 }
120
121 /*
122 * stress_proc_self_timer_read()
123 * exercise read of /proc/self/timers, Linux only
124 */
stress_proc_self_timer_read(void)125 static inline void stress_proc_self_timer_read(void)
126 {
127 #if defined(__linux__)
128 char buf[1024];
129 ssize_t n;
130
131 n = system_read("/proc/self/timers", buf, sizeof(buf));
132 (void)n;
133 #endif
134 }
135
136 /*
137 * stress_timer_handler()
138 * catch timer signal and cancel if no more runs flagged
139 */
stress_timer_handler(int sig)140 static void MLOCKED_TEXT stress_timer_handler(int sig)
141 {
142 struct itimerspec timer;
143 sigset_t mask;
144
145 (void)sig;
146
147 if (!stress_timer_keep_stressing())
148 goto cancel;
149 timer_counter++;
150
151 if (sigpending(&mask) == 0)
152 if (sigismember(&mask, SIGINT))
153 goto cancel;
154 /* High freq timer, check periodically for timeout */
155 if ((timer_counter & 65535) == 0) {
156 if ((stress_time_now() - start) > (double)g_opt_timeout)
157 goto cancel;
158 stress_proc_self_timer_read();
159 }
160 if (keep_stressing_flag()) {
161 int ret = timer_getoverrun(timerid);
162
163 if (ret > 0)
164 overruns += (uint64_t)ret;
165 stress_timer_set(&timer);
166 (void)timer_settime(timerid, 0, &timer, NULL);
167 return;
168 }
169
170 cancel:
171 keep_stressing_set_flag(false);
172 /* Cancel timer if we detect no more runs */
173 (void)memset(&timer, 0, sizeof(timer));
174 (void)timer_settime(timerid, 0, &timer, NULL);
175 }
176
177 /*
178 * stress_timer
179 * stress timers
180 */
stress_timer(const stress_args_t * args)181 static int stress_timer(const stress_args_t *args)
182 {
183 struct sigevent sev;
184 struct itimerspec timer;
185 sigset_t mask;
186 uint64_t timer_freq = DEFAULT_TIMER_FREQ;
187 int n = 0;
188
189 (void)sigemptyset(&mask);
190 (void)sigaddset(&mask, SIGINT);
191 (void)sigprocmask(SIG_SETMASK, &mask, NULL);
192
193 max_ops = args->max_ops;
194 start = stress_time_now();
195
196 if (!stress_get_setting("timer-freq", &timer_freq)) {
197 if (g_opt_flags & OPT_FLAGS_MAXIMIZE)
198 timer_freq = MAX_TIMER_FREQ;
199 if (g_opt_flags & OPT_FLAGS_MINIMIZE)
200 timer_freq = MIN_TIMER_FREQ;
201 }
202 rate_ns = timer_freq ? (double)STRESS_NANOSECOND / (double)timer_freq :
203 (double)STRESS_NANOSECOND;
204
205 if (stress_sighandler(args->name, SIGRTMIN, stress_timer_handler, NULL) < 0)
206 return EXIT_FAILURE;
207
208 (void)memset(&sev, 0, sizeof(sev));
209 sev.sigev_notify = SIGEV_SIGNAL;
210 sev.sigev_signo = SIGRTMIN;
211 sev.sigev_value.sival_ptr = &timerid;
212 if (timer_create(CLOCK_REALTIME, &sev, &timerid) < 0) {
213 pr_fail("%s: timer_create failed, errno=%d (%s)\n",
214 args->name, errno, strerror(errno));
215 return EXIT_FAILURE;
216 }
217
218 stress_timer_set(&timer);
219 if (timer_settime(timerid, 0, &timer, NULL) < 0) {
220 pr_fail("%s: timer_settime failed, errno=%d (%s)\n",
221 args->name, errno, strerror(errno));
222 return EXIT_FAILURE;
223 }
224
225 stress_set_proc_state(args->name, STRESS_STATE_RUN);
226
227 do {
228 struct timespec req;
229
230 if (n++ >= 1024) {
231 int ret;
232
233 n = 0;
234
235 /* Exercise nanosleep on non-permitted timespec object values */
236 (void)memset(&req, 0, sizeof(req));
237 req.tv_sec = -1;
238 ret= nanosleep(&req, NULL);
239 (void)ret;
240
241 (void)memset(&req, 0, sizeof(req));
242 req.tv_nsec = STRESS_NANOSECOND;
243 ret = nanosleep(&req, NULL);
244 (void)ret;
245 }
246
247 req.tv_sec = 0;
248 req.tv_nsec = 10000000;
249 (void)nanosleep(&req, NULL);
250 set_counter(args, timer_counter);
251
252 } while (keep_stressing(args));
253
254 if (timer_delete(timerid) < 0) {
255 pr_fail("%s: timer_delete failed, errno=%d (%s)\n",
256 args->name, errno, strerror(errno));
257 return EXIT_FAILURE;
258 }
259 pr_dbg("%s: %" PRIu64 " timer overruns (instance %" PRIu32 ")\n",
260 args->name, overruns, args->instance);
261
262 stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
263 #if defined(__linux__)
264 /* Some BSD flavours segfault on duplicated timer_delete calls */
265 {
266 int ret;
267
268 /* Re-delete already deleted timer */
269 ret = timer_delete(timerid);
270 (void)ret;
271
272 /*
273 * The manual states that EINVAL is returned when
274 * an invalid timerid is used, in practice this
275 * will most probably segfault librt, so ignore this
276 * test case for now.
277 *
278 ret = timer_delete((timer_t)stress_mwc32());
279 (void)ret;
280 */
281 }
282 #endif
283
284 return EXIT_SUCCESS;
285 }
286
287 stressor_info_t stress_timer_info = {
288 .stressor = stress_timer,
289 .class = CLASS_INTERRUPT | CLASS_OS,
290 .opt_set_funcs = opt_set_funcs,
291 .help = help
292 };
293 #else
294 stressor_info_t stress_timer_info = {
295 .stressor = stress_not_implemented,
296 .class = CLASS_INTERRUPT | CLASS_OS,
297 .opt_set_funcs = opt_set_funcs,
298 .help = help
299 };
300 #endif
301