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 #define DEFAULT_DELAY_NS	(100000)
28 #define MAX_SAMPLES		(10000)
29 #define MAX_BUCKETS		(250)
30 
31 typedef struct {
32 	const int	policy;		/* scheduler policy */
33 	const char	*name;		/* name of scheduler policy */
34 	const char	*opt_name;	/* option name */
35 } stress_policy_t;
36 
37 typedef struct {
38 	int64_t		min_ns;		/* min latency */
39 	int64_t		max_ns;		/* max latency */
40 	int64_t		latencies[MAX_SAMPLES];
41 	size_t		index;		/* index into latencies */
42 	int32_t		min_prio;	/* min priority allowed */
43 	int32_t		max_prio;	/* max priority allowed */
44 	double		ns;		/* total nanosecond latency */
45 	double		latency_mean;	/* average latency */
46 	int64_t		latency_mode;	/* first mode */
47 	double		std_dev;	/* standard deviation */
48 } stress_rt_stats_t;
49 
50 typedef int (*stress_cyclic_func)(const stress_args_t *args, stress_rt_stats_t *rt_stats, uint64_t cyclic_sleep);
51 
52 typedef struct {
53 	const char 		 *name;
54 	const stress_cyclic_func func;
55 } stress_cyclic_method_info_t;
56 
57 static const stress_help_t help[] = {
58 	{ NULL,	"cyclic N",		"start N cyclic real time benchmark stressors" },
59 	{ NULL,	"cyclic-ops N",		"stop after N cyclic timing cycles" },
60 	{ NULL,	"cyclic-method M",	"specify cyclic method M, default is clock_ns" },
61 	{ NULL,	"cyclic-dist N",	"calculate distribution of interval N nanosecs" },
62 	{ NULL,	"cyclic-policy P",	"used rr or fifo scheduling policy" },
63 	{ NULL,	"cyclic-prio N",	"real time scheduling priority 1..100" },
64 	{ NULL,	"cyclic-sleep N",	"sleep time of real time timer in nanosecs" },
65 	{ NULL,	NULL,			NULL }
66 };
67 
68 static const stress_policy_t policies[] = {
69 #if defined(SCHED_DEADLINE)
70 	{ SCHED_DEADLINE, "SCHED_DEADLINE",  "deadline" },
71 #endif
72 #if defined(SCHED_FIFO)
73 	{ SCHED_FIFO,     "SCHED_FIFO",      "fifo" },
74 #endif
75 #if defined(SCHED_RR)
76 	{ SCHED_RR,       "SCHED_RR",        "rr" },
77 #endif
78 };
79 
80 static const size_t num_policies = SIZEOF_ARRAY(policies);
81 
stress_set_cyclic_sleep(const char * opt)82 static int stress_set_cyclic_sleep(const char *opt)
83 {
84 	uint64_t cyclic_sleep;
85 
86 	cyclic_sleep = stress_get_uint64(opt);
87 	stress_check_range("cyclic-sleep", cyclic_sleep,
88 		1, STRESS_NANOSECOND);
89 	return stress_set_setting("cyclic-sleep", TYPE_ID_UINT64, &cyclic_sleep);
90 }
91 
stress_set_cyclic_policy(const char * opt)92 static int stress_set_cyclic_policy(const char *opt)
93 {
94 	size_t policy;
95 
96 	for (policy = 0; policy < num_policies; policy++) {
97 		if (!strcmp(opt, policies[policy].opt_name)) {
98 			stress_set_setting("cyclic-policy", TYPE_ID_SIZE_T, &policy);
99 			return 0;
100 		}
101 	}
102 	(void)fprintf(stderr, "invalid cyclic-policy '%s', policies allowed are:", opt);
103 	for (policy = 0; policy < num_policies; policy++) {
104 		(void)fprintf(stderr, " %s", policies[policy].opt_name);
105 	}
106 	(void)fprintf(stderr, "\n");
107 	return -1;
108 }
109 
stress_set_cyclic_prio(const char * opt)110 static int stress_set_cyclic_prio(const char *opt)
111 {
112 	int32_t cyclic_prio;
113 
114 	cyclic_prio = stress_get_int32(opt);
115 	stress_check_range("cyclic-prio", (uint64_t)cyclic_prio, 1, 100);
116 	return stress_set_setting("cyclic-prio", TYPE_ID_INT32, &cyclic_prio);
117 }
118 
stress_set_cyclic_dist(const char * opt)119 static int stress_set_cyclic_dist(const char *opt)
120 {
121 	uint64_t cyclic_dist;
122 
123 	cyclic_dist = stress_get_uint64(opt);
124 	stress_check_range("cyclic-dist", cyclic_dist, 1, 10000000);
125 	return stress_set_setting("cyclic-dist", TYPE_ID_UINT64, &cyclic_dist);
126 }
127 
128 #if (defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_NANOSLEEP)) ||	\
129     (defined(HAVE_CLOCK_GETTIME) && defined(HAVE_NANOSLEEP)) ||		\
130     (defined(HAVE_CLOCK_GETTIME) && defined(HAVE_PSELECT)) ||		\
131     (defined(HAVE_CLOCK_GETTIME))
stress_cyclic_stats(stress_rt_stats_t * rt_stats,const uint64_t cyclic_sleep,const struct timespec * t1,const struct timespec * t2)132 static void stress_cyclic_stats(
133 	stress_rt_stats_t *rt_stats,
134 	const uint64_t cyclic_sleep,
135 	const struct timespec *t1,
136 	const struct timespec *t2)
137 {
138 	int64_t delta_ns;
139 
140 	delta_ns = ((int64_t)(t2->tv_sec - t1->tv_sec) * STRESS_NANOSECOND) +
141 		   (t2->tv_nsec - t1->tv_nsec);
142 	delta_ns -= cyclic_sleep;
143 
144 	if (rt_stats->index < MAX_SAMPLES)
145 		rt_stats->latencies[rt_stats->index++] = delta_ns;
146 
147 	rt_stats->ns += (double)delta_ns;
148 }
149 #endif
150 
151 #if defined(HAVE_CLOCK_GETTIME) &&	\
152     defined(HAVE_CLOCK_NANOSLEEP)
153 /*
154  *  stress_cyclic_clock_nanosleep()
155  *	measure latencies with clock_nanosleep
156  */
stress_cyclic_clock_nanosleep(const stress_args_t * args,stress_rt_stats_t * rt_stats,const uint64_t cyclic_sleep)157 static int stress_cyclic_clock_nanosleep(
158 	const stress_args_t *args,
159 	stress_rt_stats_t *rt_stats,
160 	const uint64_t cyclic_sleep)
161 {
162 	struct timespec t1, t2, t, trem;
163 	int ret;
164 
165 	(void)args;
166 
167 	t.tv_sec = cyclic_sleep / STRESS_NANOSECOND;
168 	t.tv_nsec = cyclic_sleep % STRESS_NANOSECOND;
169 	(void)clock_gettime(CLOCK_REALTIME, &t1);
170 	ret = clock_nanosleep(CLOCK_REALTIME, 0, &t, &trem);
171 	(void)clock_gettime(CLOCK_REALTIME, &t2);
172 	if (ret == 0)
173 		stress_cyclic_stats(rt_stats, cyclic_sleep, &t1, &t2);
174 	return 0;
175 }
176 #endif
177 
178 #if defined(HAVE_CLOCK_GETTIME)	&&	\
179     defined(HAVE_NANOSLEEP)
180 /*
181  *  stress_cyclic_posix_nanosleep()
182  *	measure latencies with posix nanosleep
183  */
stress_cyclic_posix_nanosleep(const stress_args_t * args,stress_rt_stats_t * rt_stats,const uint64_t cyclic_sleep)184 static int stress_cyclic_posix_nanosleep(
185 	const stress_args_t *args,
186 	stress_rt_stats_t *rt_stats,
187 	const uint64_t cyclic_sleep)
188 {
189 	struct timespec t1, t2, t, trem;
190 	int ret;
191 
192 	(void)args;
193 
194 	t.tv_sec = cyclic_sleep / STRESS_NANOSECOND;
195 	t.tv_nsec = cyclic_sleep % STRESS_NANOSECOND;
196 	(void)clock_gettime(CLOCK_REALTIME, &t1);
197 	ret = nanosleep(&t, &trem);
198 	(void)clock_gettime(CLOCK_REALTIME, &t2);
199 	if (ret == 0)
200 		stress_cyclic_stats(rt_stats, cyclic_sleep, &t1, &t2);
201 	return 0;
202 }
203 #endif
204 
205 #if defined(HAVE_CLOCK_GETTIME)
206 /*
207  *  stress_cyclic_poll()
208  *	measure latencies of heavy polling the clock
209  */
stress_cyclic_poll(const stress_args_t * args,stress_rt_stats_t * rt_stats,const uint64_t cyclic_sleep)210 static int stress_cyclic_poll(
211 	const stress_args_t *args,
212 	stress_rt_stats_t *rt_stats,
213 	const uint64_t cyclic_sleep)
214 {
215 	struct timespec t1, t2;
216 
217 	(void)args;
218 
219 	/* find nearest point to clock roll over */
220 	(void)clock_gettime(CLOCK_REALTIME, &t1);
221 	for (;;) {
222 		(void)clock_gettime(CLOCK_REALTIME, &t2);
223 		if ((t1.tv_sec != t2.tv_sec) || (t1.tv_nsec != t2.tv_nsec))
224 			break;
225 	}
226 	t1 = t2;
227 
228 	for (;;) {
229 		int64_t delta_ns;
230 
231 		(void)clock_gettime(CLOCK_REALTIME, &t2);
232 
233 		delta_ns = ((int64_t)(t2.tv_sec - t1.tv_sec) * STRESS_NANOSECOND) +
234 			   (t2.tv_nsec - t1.tv_nsec);
235 		if (delta_ns >= (int64_t)cyclic_sleep) {
236 			delta_ns -= cyclic_sleep;
237 
238 			if (rt_stats->index < MAX_SAMPLES)
239 				rt_stats->latencies[rt_stats->index++] = delta_ns;
240 
241 			rt_stats->ns += (double)delta_ns;
242 			break;
243 		}
244 	}
245 	return 0;
246 }
247 #endif
248 
249 #if defined(HAVE_PSELECT) &&		\
250     defined(HAVE_CLOCK_GETTIME)
251 /*
252  *  stress_cyclic_pselect()
253  *	measure latencies with pselect sleep
254  */
stress_cyclic_pselect(const stress_args_t * args,stress_rt_stats_t * rt_stats,const uint64_t cyclic_sleep)255 static int stress_cyclic_pselect(
256 	const stress_args_t *args,
257 	stress_rt_stats_t *rt_stats,
258 	const uint64_t cyclic_sleep)
259 {
260 	struct timespec t1, t2, t;
261 	int ret;
262 
263 	(void)args;
264 
265 	t.tv_sec = cyclic_sleep / STRESS_NANOSECOND;
266 	t.tv_nsec = cyclic_sleep % STRESS_NANOSECOND;
267 	(void)clock_gettime(CLOCK_REALTIME, &t1);
268 	ret = pselect(0, NULL, NULL,NULL, &t, NULL);
269 	(void)clock_gettime(CLOCK_REALTIME, &t2);
270 	if (ret == 0)
271 		stress_cyclic_stats(rt_stats, cyclic_sleep, &t1, &t2);
272 	return 0;
273 }
274 #endif
275 
276 #if defined(HAVE_CLOCK_GETTIME) &&	\
277     defined(HAVE_TIMER_CREATE) &&	\
278     defined(HAVE_TIMER_DELETE) &&	\
279     defined(HAVE_TIMER_SETTIME)
280 static struct timespec itimer_time;
281 
stress_cyclic_itimer_handler(int sig)282 static void MLOCKED_TEXT stress_cyclic_itimer_handler(int sig)
283 {
284 	(void)sig;
285 
286 	(void)clock_gettime(CLOCK_REALTIME, &itimer_time);
287 }
288 
289 /*
290  *  stress_cyclic_itimer()
291  *	measure latencies with itimers
292  */
stress_cyclic_itimer(const stress_args_t * args,stress_rt_stats_t * rt_stats,const uint64_t cyclic_sleep)293 static int stress_cyclic_itimer(
294 	const stress_args_t *args,
295 	stress_rt_stats_t *rt_stats,
296 	const uint64_t cyclic_sleep)
297 {
298 	struct itimerspec timer;
299 	struct timespec t1;
300 	int64_t delta_ns;
301 	struct sigaction old_action;
302 	struct sigevent sev;
303 	timer_t timerid;
304 	int ret = -1;
305 
306 	timer.it_interval.tv_sec = timer.it_value.tv_sec = cyclic_sleep / STRESS_NANOSECOND;
307 	timer.it_interval.tv_nsec = timer.it_value.tv_nsec = cyclic_sleep % STRESS_NANOSECOND;
308 
309 	if (stress_sighandler(args->name, SIGRTMIN, stress_cyclic_itimer_handler, &old_action) < 0)
310 		return ret;
311 
312 	(void)memset(&sev, 0, sizeof(sev));
313 	sev.sigev_notify = SIGEV_SIGNAL;
314 	sev.sigev_signo = SIGRTMIN;
315 	sev.sigev_value.sival_ptr = &timerid;
316 	if (timer_create(CLOCK_REALTIME, &sev, &timerid) < 0)
317 		goto restore;
318 
319 	(void)memset(&itimer_time, 0, sizeof(itimer_time));
320 	(void)clock_gettime(CLOCK_REALTIME, &t1);
321 	if (timer_settime(timerid, 0, &timer, NULL) < 0)
322 		goto restore;
323 
324 	(void)pause();
325 	if ((itimer_time.tv_sec == 0) &&
326 	    (itimer_time.tv_nsec == 0))
327 		goto tidy;
328 
329 	delta_ns = ((int64_t)(itimer_time.tv_sec - t1.tv_sec) * STRESS_NANOSECOND) +
330 		(itimer_time.tv_nsec - t1.tv_nsec);
331 	delta_ns -= cyclic_sleep;
332 
333 	if (rt_stats->index < MAX_SAMPLES)
334 		rt_stats->latencies[rt_stats->index++] = delta_ns;
335 
336 	rt_stats->ns += (double)delta_ns;
337 
338 	(void)timer_delete(timerid);
339 
340 	ret = 0;
341 tidy:
342 	/* And cancel timer */
343 	(void)memset(&timer, 0, sizeof(timer));
344 	(void)timer_settime(timerid, 0, &timer, NULL);
345 restore:
346 	stress_sigrestore(args->name, SIGRTMIN, &old_action);
347 	return ret;
348 }
349 #endif
350 
351 #if defined(HAVE_CLOCK_GETTIME)
352 /*
353  *  stress_cyclic_usleep()
354  *	measure latencies with usleep
355  */
stress_cyclic_usleep(const stress_args_t * args,stress_rt_stats_t * rt_stats,const uint64_t cyclic_sleep)356 static int stress_cyclic_usleep(
357 	const stress_args_t *args,
358 	stress_rt_stats_t *rt_stats,
359 	const uint64_t cyclic_sleep)
360 {
361 	struct timespec t1, t2;
362 	const useconds_t usecs = (useconds_t)cyclic_sleep / 1000;
363 	int ret;
364 
365 	(void)args;
366 
367 	(void)clock_gettime(CLOCK_REALTIME, &t1);
368 	ret = usleep(usecs);
369 	(void)clock_gettime(CLOCK_REALTIME, &t2);
370 	if (ret == 0)
371 		stress_cyclic_stats(rt_stats, cyclic_sleep, &t1, &t2);
372 	return 0;
373 }
374 #endif
375 
376 static sigjmp_buf jmp_env;
377 
378 /*
379  *  stress_rlimit_handler()
380  *      rlimit generic handler
381  */
stress_rlimit_handler(int signum)382 static void NORETURN MLOCKED_TEXT stress_rlimit_handler(int signum)
383 {
384 	(void)signum;
385 
386 	keep_stressing_set_flag(false);
387 	siglongjmp(jmp_env, 1);
388 }
389 
390 /*
391  *  stress_cyclic_cmp()
392  *	sort latencies into order, least first
393  */
stress_cyclic_cmp(const void * p1,const void * p2)394 static int stress_cyclic_cmp(const void *p1, const void *p2)
395 {
396 	const int64_t *i1 = (const int64_t *)p1;
397 	const int64_t *i2 = (const int64_t *)p2;
398 
399 	if (*i1 > *i2)
400 		return 1;
401 	else if (*i1 < *i2)
402 		return -1;
403 	return 0;
404 }
405 
406 /*
407  *  stress_rt_stats()
408  *	compute statistics on gathered latencies
409  */
stress_rt_stats(stress_rt_stats_t * rt_stats)410 static void stress_rt_stats(stress_rt_stats_t *rt_stats)
411 {
412 	size_t i;
413 	size_t n = 0, best_n = 0;
414 	int64_t current;
415 	double variance = 0.0;
416 
417 	rt_stats->latency_mean = 0.0;
418 	rt_stats->latency_mode = 0;
419 
420 	for (i = 0; i < rt_stats->index; i++) {
421 		int64_t ns = rt_stats->latencies[i];
422 
423 		if (ns > rt_stats->max_ns)
424 			rt_stats->max_ns = ns;
425 		if (ns < rt_stats->min_ns)
426 			rt_stats->min_ns = ns;
427 
428 		rt_stats->latency_mean += (double)ns;
429 	}
430 	if (rt_stats->index)
431 		rt_stats->latency_mean /= (double)rt_stats->index;
432 
433 	qsort(rt_stats->latencies, rt_stats->index, sizeof(*(rt_stats->latencies)), stress_cyclic_cmp);
434 
435 	current = rt_stats->latency_mode = rt_stats->latencies[0];
436 
437 	for (i = 0; i < rt_stats->index; i++) {
438 		int64_t ns = rt_stats->latencies[i];
439 		double diff;
440 
441 		if (ns == current) {
442 			n++;
443 			if (n > best_n) {
444 				rt_stats->latency_mode = current;
445 				best_n = n;
446 			}
447 		} else {
448 			current = ns;
449 			n = 0;
450 		}
451 		diff = ((double)ns - rt_stats->latency_mean);
452 		variance += (diff * diff);
453 	}
454 	if (rt_stats->index) {
455 		variance /= (double)rt_stats->index;
456 		rt_stats->std_dev = sqrt(variance);
457 	}
458 }
459 
460 /*
461  *  cyclic methods
462  */
463 static const stress_cyclic_method_info_t cyclic_methods[] = {
464 #if defined(HAVE_CLOCK_GETTIME) &&	\
465     defined(HAVE_CLOCK_NANOSLEEP)
466 	{ "clock_ns",	stress_cyclic_clock_nanosleep },
467 #endif
468 
469 #if defined(HAVE_CLOCK_GETTIME) &&	\
470     defined(HAVE_TIMER_CREATE) &&	\
471     defined(HAVE_TIMER_DELETE) &&	\
472     defined(HAVE_TIMER_SETTIME)
473 	{ "itimer",	stress_cyclic_itimer },
474 #endif
475 
476 #if defined(HAVE_CLOCK_GETTIME)
477 	{ "poll",	stress_cyclic_poll },
478 #endif
479 
480 #if defined(HAVE_CLOCK_GETTIME)	&&	\
481     defined(HAVE_NANOSLEEP)
482 	{ "posix_ns",	stress_cyclic_posix_nanosleep },
483 #endif
484 
485 #if defined(HAVE_PSELECT) &&		\
486     defined(HAVE_CLOCK_GETTIME)
487 	{ "pselect",	stress_cyclic_pselect },
488 #endif
489 
490 #if defined(HAVE_CLOCK_GETTIME)
491 	{ "usleep",	stress_cyclic_usleep },
492 #endif
493 
494 	{ NULL,		NULL }
495 };
496 
497 /*
498  *  stress_set_cyclic_method()
499  *	set the default cyclic method
500  */
stress_set_cyclic_method(const char * name)501 static int stress_set_cyclic_method(const char *name)
502 {
503 	stress_cyclic_method_info_t const *info;
504 
505 	for (info = cyclic_methods; info->func; info++) {
506 		if (!strcmp(info->name, name)) {
507 			stress_set_setting("cyclic-method", TYPE_ID_UINTPTR_T, &info);
508 			return 0;
509 		}
510 	}
511 
512 	(void)fprintf(stderr, "cyclic-method must be one of:");
513 	for (info = cyclic_methods; info->func; info++) {
514 		(void)fprintf(stderr, " %s", info->name);
515 	}
516 	(void)fprintf(stderr, "\n");
517 
518 	return -1;
519 }
520 
521 /*
522  *  stress_rt_dist()
523  *	show real time distribution
524  */
stress_rt_dist(const char * name,bool * lock,stress_rt_stats_t * rt_stats,const int64_t cyclic_dist)525 static void stress_rt_dist(
526 	const char *name,
527 	bool *lock,
528 	stress_rt_stats_t *rt_stats,
529 	const int64_t cyclic_dist)
530 {
531 	ssize_t dist_max_size = (cyclic_dist > 0) ?
532 		((ssize_t)rt_stats->max_ns / (ssize_t)cyclic_dist) + 1 : 1;
533 	ssize_t dist_size = STRESS_MINIMUM(MAX_BUCKETS, dist_max_size);
534 	const ssize_t dist_min = STRESS_MINIMUM(5, dist_max_size);
535 	ssize_t i, n;
536 	int64_t dist[dist_size];
537 
538 	if (!cyclic_dist)
539 		return;
540 
541 	(void)memset(dist, 0, sizeof(dist));
542 
543 	for (i = 0; i < (ssize_t)rt_stats->index; i++) {
544 		int64_t lat = rt_stats->latencies[i] / cyclic_dist;
545 
546 		if (lat < (int64_t)dist_size)
547 			dist[lat]++;
548 	}
549 
550 	for (n = dist_size; n >= 1; n--) {
551 		if (dist[n - 1])
552 			break;
553 	}
554 	if (n < dist_min)
555 		n = dist_min;
556 	if (n >= dist_size - 3)
557 		n = dist_size;
558 
559 	pr_inf_lock(lock, "%s: latency distribution (%" PRIu64 " ns intervals):\n", name, cyclic_dist);
560 	pr_inf_lock(lock, "%s: (for the first %zd buckets of %zd)\n", name, dist_size, dist_max_size);
561 	pr_inf_lock(lock, "%s: %12s %10s\n", name, "latency (ns)", "frequency");
562 	for (i = 0; i < n; i++) {
563 		pr_inf_lock(lock, "%s: %12" PRIu64 " %10" PRId64 "\n",
564 			name, cyclic_dist * i, dist[i]);
565 	}
566 
567 	/*
568 	 *  This caters for the case where there are lots of zeros at
569 	 *  the end of the distribution
570 	 */
571 	if (n < dist_size) {
572 		pr_inf_lock(lock, "%s: %12s %10s (all zeros hereafter)\n", name, "..", "..");
573 		pr_inf_lock(lock, "%s: %12s %10s\n", name, "..", "..");
574 		for (i = STRESS_MAXIMUM(dist_size - 3, n); i < dist_size; i++) {
575 			pr_inf_lock(lock, "%s: %12" PRIu64 " %10" PRId64 "\n",
576 				name, cyclic_dist * i, (int64_t)0);
577 		}
578 	}
579 }
580 
581 /*
582  *  stress_cyclic_supported()
583  *      check if we can run this as root
584  */
stress_cyclic_supported(const char * name)585 static int stress_cyclic_supported(const char *name)
586 {
587 	if (!stress_check_capability(SHIM_CAP_SYS_NICE)) {
588 		pr_inf_skip("%s stressor needs to be run with CAP_SYS_NICE "
589 			"set SCHED_RR, SCHED_FIFO or SCHED_DEADLINE priorities, "
590 			"skipping this stressor\n", name);
591 		return -1;
592 	}
593 	return 0;
594 }
595 
stress_cyclic(const stress_args_t * args)596 static int stress_cyclic(const stress_args_t *args)
597 {
598 	const stress_cyclic_method_info_t *cyclic_method = &cyclic_methods[0];
599 	const uint32_t num_instances = args->num_instances;
600 	struct sigaction old_action_xcpu;
601 	struct rlimit rlim;
602 	pid_t pid;
603 	NOCLOBBER uint64_t timeout;
604 	uint64_t cyclic_sleep = DEFAULT_DELAY_NS;
605 	uint64_t cyclic_dist = 0;
606 	int32_t cyclic_prio = INT32_MAX;
607 	int policy;
608 	size_t cyclic_policy = 0;
609 	const double start = stress_time_now();
610 	stress_rt_stats_t *rt_stats;
611 	const size_t page_size = args->page_size;
612 	const size_t size = (sizeof(*rt_stats) + page_size - 1) & (~(page_size - 1));
613 	stress_cyclic_func func;
614 
615 	timeout  = g_opt_timeout;
616 	(void)stress_get_setting("cyclic-sleep", &cyclic_sleep);
617 	(void)stress_get_setting("cyclic-prio", &cyclic_prio);
618 	(void)stress_get_setting("cyclic-policy", &cyclic_policy);
619 	(void)stress_get_setting("cyclic-dist", &cyclic_dist);
620 	(void)stress_get_setting("cyclic-method", &cyclic_method);
621 
622 	func = cyclic_method->func;
623 	policy = policies[cyclic_policy].policy;
624 
625 	if (!args->instance) {
626 		if (num_policies == 0) {
627 			pr_inf_skip("%s: no scheduling policies "
628 				"available, skipping test\n",
629 				args->name);
630 			return EXIT_NOT_IMPLEMENTED;
631 		}
632 	}
633 
634 	if (g_opt_timeout == TIMEOUT_NOT_SET) {
635 		timeout = 60;
636 		pr_inf("%s: timeout has not been set, forcing timeout to "
637 			"be %" PRIu64 " seconds\n", args->name, timeout);
638 	}
639 
640 	if ((num_instances > 1) && (args->instance == 0)) {
641 		pr_inf("%s: for best results, run just 1 instance of "
642 			"this stressor\n", args->name);
643 	}
644 
645 	rt_stats = (stress_rt_stats_t *)mmap(NULL, size, PROT_READ | PROT_WRITE,
646 			MAP_SHARED | MAP_ANONYMOUS, -1, 0);
647 	if (rt_stats == MAP_FAILED) {
648 		pr_inf("%s: mmap of shared policy data failed: %d (%s)\n",
649 			args->name, errno, strerror(errno));
650 		return EXIT_NO_RESOURCE;
651 	}
652 	rt_stats->min_ns = INT64_MAX;
653 	rt_stats->max_ns = INT64_MIN;
654 	rt_stats->ns = 0.0;
655 #if defined(HAVE_SCHED_GET_PRIORITY_MIN)
656 	rt_stats->min_prio = sched_get_priority_min(policy);
657 #else
658 	rt_stats->min_prio = 0;
659 #endif
660 
661 #if defined(HAVE_SCHED_GET_PRIORITY_MAX)
662 	rt_stats->max_prio = sched_get_priority_max(policy);
663 #else
664 	rt_stats->max_prio = 0;
665 #endif
666 	/* If user has set max priority.. */
667 	if (cyclic_prio != INT32_MAX) {
668 		if (rt_stats->max_prio > cyclic_prio) {
669 			rt_stats->max_prio = cyclic_prio;
670 		}
671 	}
672 
673 	if (args->instance == 0)
674 		pr_dbg("%s: using method '%s'\n", args->name, cyclic_method->name);
675 
676 	stress_set_proc_state(args->name, STRESS_STATE_RUN);
677 
678 again:
679 	pid = fork();
680 	if (pid < 0) {
681 		if (stress_redo_fork(errno))
682 			goto again;
683 		if (!keep_stressing(args))
684 			goto finish;
685 		pr_inf("%s: cannot fork, errno=%d (%s)\n",
686 			args->name, errno, strerror(errno));
687 		return EXIT_NO_RESOURCE;
688 	} else if (pid == 0) {
689 #if defined(HAVE_SCHED_GET_PRIORITY_MIN) &&	\
690     defined(HAVE_SCHED_GET_PRIORITY_MAX)
691 		const pid_t mypid = getpid();
692 #endif
693 #if defined(HAVE_ATOMIC)
694 		uint32_t count;
695 #endif
696 		int ret;
697 		NOCLOBBER int rc = EXIT_FAILURE;
698 
699 #if defined(HAVE_ATOMIC)
700 		__sync_fetch_and_add(&g_shared->softlockup_count, 1);
701 
702 		/*
703 		 * Wait until all instances have reached this point
704 		 */
705 		do {
706 			if ((stress_time_now() - start) > (double)timeout)
707 				goto tidy_ok;
708 			(void)usleep(50000);
709 			__atomic_load(&g_shared->softlockup_count, &count, __ATOMIC_RELAXED);
710 		} while (keep_stressing(args) && count < num_instances);
711 #endif
712 
713 		/*
714 		 * We run the stressor as a child so that
715 		 * if we the hard time timits the child is
716 		 * terminated with a SIGKILL and we can
717 		 * catch that with the parent
718 		 */
719 		rlim.rlim_cur = timeout;
720 		rlim.rlim_max = timeout;
721 		(void)setrlimit(RLIMIT_CPU, &rlim);
722 
723 #if defined(RLIMIT_RTTIME)
724 		rlim.rlim_cur = 1000000 * timeout;
725 		rlim.rlim_max = 1000000 * timeout;
726 		(void)setrlimit(RLIMIT_RTTIME, &rlim);
727 #endif
728 
729 		if (stress_sighandler(args->name, SIGXCPU, stress_rlimit_handler, &old_action_xcpu) < 0)
730 			goto tidy;
731 
732 		ret = sigsetjmp(jmp_env, 1);
733 		if (ret)
734 			goto tidy_ok;
735 
736 #if defined(HAVE_SCHED_GET_PRIORITY_MIN) &&	\
737     defined(HAVE_SCHED_GET_PRIORITY_MAX)
738 #if defined(SCHED_DEADLINE)
739 redo_policy:
740 #endif
741 		ret = stress_set_sched(mypid, policy, rt_stats->max_prio, true);
742 		if (ret < 0) {
743 #if defined(SCHED_DEADLINE)
744 			/*
745 			 *  The following occurs if we use an older kernel
746 			 *  that does not support the larger newer attr structure
747 			 *  but userspace does. This currently only occurs with
748 			 *  SCHED_DEADLINE; fall back to the next scheduling policy
749 			 *  which users the older and smaller attr structure.
750 			 */
751 			if ((errno == E2BIG) &&
752 			    (policies[cyclic_policy].policy == SCHED_DEADLINE)) {
753 				cyclic_policy = 1;
754 				policy = policies[cyclic_policy].policy;
755 #if defined(HAVE_SCHED_GET_PRIORITY_MAX)
756 				rt_stats->max_prio = sched_get_priority_max(policy);
757 #else
758 				rt_stats->max_prio = 0;
759 #endif
760 				pr_inf("%s: DEADLINE not supported by kernel, defaulting to %s\n",
761 					args->name, policies[cyclic_policy].name);
762 				goto redo_policy;
763 			}
764 #endif
765 			if (errno != EPERM) {
766 				const char *msg = (errno == EBUSY) ?
767 					", (recommend setting --sched-runtime to less than 90000)" : "";
768 
769 				pr_fail("%s: sched_setscheduler "
770 					"failed: errno=%d (%s) "
771 					"for scheduler policy %s%s\n",
772 					args->name, errno, strerror(errno),
773 					policies[cyclic_policy].name,
774 					msg);
775 			}
776 			goto tidy;
777 		}
778 #endif
779 		do {
780 			func(args, rt_stats, cyclic_sleep);
781 			inc_counter(args);
782 
783 			/* Ensure we NEVER spin forever */
784 			if ((stress_time_now() - start) > (double)timeout)
785 				break;
786 		} while (keep_stressing(args));
787 
788 tidy_ok:
789 		rc = EXIT_SUCCESS;
790 tidy:
791 		(void)fflush(stdout);
792 		_exit(rc);
793 	} else {
794 		int status, ret;
795 
796 		ret = stress_set_sched(args->pid, policy, rt_stats->max_prio, true);
797 		(void)ret;
798 
799 		(void)pause();
800 		(void)kill(pid, SIGKILL);
801 #if defined(HAVE_ATOMIC)
802 		__sync_fetch_and_sub(&g_shared->softlockup_count, 1);
803 #endif
804 
805 		(void)shim_waitpid(pid, &status, 0);
806 	}
807 
808 	stress_rt_stats(rt_stats);
809 
810 	if (args->instance == 0) {
811 		if (rt_stats->index) {
812 			size_t i;
813 			bool lock = false;
814 
815 			static const double percentiles[] = {
816 				25.0,
817 				50.0,
818 				75.0,
819 				90.0,
820 				95.40,
821 				99.0,
822 				99.5,
823 				99.9,
824 				99.99,
825 			};
826 
827 			pr_lock(&lock);
828 			pr_inf_lock(&lock, "%s: sched %s: %" PRIu64 " ns delay, %zd samples\n",
829 				args->name,
830 				policies[cyclic_policy].name,
831 				cyclic_sleep,
832 				rt_stats->index);
833 			pr_inf_lock(&lock, "%s:   mean: %.2f ns, mode: %" PRId64 " ns\n",
834 				args->name,
835 				rt_stats->latency_mean,
836 				rt_stats->latency_mode);
837 			pr_inf_lock(&lock, "%s:   min: %" PRId64 " ns, max: %" PRId64 " ns, std.dev. %.2f\n",
838 				args->name,
839 				rt_stats->min_ns,
840 				rt_stats->max_ns,
841 				rt_stats->std_dev);
842 
843 			pr_inf_lock(&lock, "%s: latency percentiles:\n", args->name);
844 			for (i = 0; i < sizeof(percentiles) / sizeof(percentiles[0]); i++) {
845 				size_t j = (size_t)(((double)rt_stats->index * percentiles[i]) / 100.0);
846 				pr_inf_lock(&lock, "%s:   %5.2f%%: %10" PRId64 " ns\n",
847 					args->name,
848 					percentiles[i],
849 					rt_stats->latencies[j]);
850 			}
851 			stress_rt_dist(args->name, &lock, rt_stats, (int64_t)cyclic_dist);
852 			pr_unlock(&lock);
853 		} else {
854 			pr_inf("%s: %10s: no latency information available\n",
855 				args->name,
856 				policies[cyclic_policy].name);
857 		}
858 	}
859 
860 finish:
861 	stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
862 
863 	(void)munmap((void *)rt_stats, size);
864 
865 	return EXIT_SUCCESS;
866 }
867 
868 static const stress_opt_set_func_t opt_set_funcs[] = {
869 	{ OPT_cyclic_dist,	stress_set_cyclic_dist },
870 	{ OPT_cyclic_method,	stress_set_cyclic_method },
871 	{ OPT_cyclic_policy,	stress_set_cyclic_policy },
872 	{ OPT_cyclic_prio, 	stress_set_cyclic_prio },
873 	{ OPT_cyclic_sleep,	stress_set_cyclic_sleep },
874 	{ 0,			NULL }
875 };
876 
877 stressor_info_t stress_cyclic_info = {
878 	.stressor = stress_cyclic,
879 	.supported = stress_cyclic_supported,
880 	.class = CLASS_SCHEDULER | CLASS_OS,
881 	.opt_set_funcs = opt_set_funcs,
882 	.help = help
883 };
884