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