xref: /linux/tools/tracing/rtla/src/utils.c (revision b105ffc19d5e53058cba68a9b8b7915216f0bf46)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org>
4  */
5 
6 #define _GNU_SOURCE
7 #ifdef HAVE_LIBCPUPOWER_SUPPORT
8 #include <cpuidle.h>
9 #endif /* HAVE_LIBCPUPOWER_SUPPORT */
10 #include <dirent.h>
11 #include <stdarg.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <ctype.h>
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <sched.h>
19 #include <stdio.h>
20 #include <limits.h>
21 
22 #include "common.h"
23 
24 #define MAX_MSG_LENGTH	1024
25 bool config_debug;
26 
27 /*
28  * err_msg - print an error message to the stderr
29  */
30 void err_msg(const char *fmt, ...)
31 {
32 	char message[MAX_MSG_LENGTH];
33 	va_list ap;
34 
35 	va_start(ap, fmt);
36 	vsnprintf(message, sizeof(message), fmt, ap);
37 	va_end(ap);
38 
39 	fprintf(stderr, "%s", message);
40 }
41 
42 /*
43  * debug_msg - print a debug message to stderr if debug is set
44  */
45 void debug_msg(const char *fmt, ...)
46 {
47 	char message[MAX_MSG_LENGTH];
48 	va_list ap;
49 
50 	if (!config_debug)
51 		return;
52 
53 	va_start(ap, fmt);
54 	vsnprintf(message, sizeof(message), fmt, ap);
55 	va_end(ap);
56 
57 	fprintf(stderr, "%s", message);
58 }
59 
60 /*
61  * fatal - print an error message and EOL to stderr and exit with ERROR
62  */
63 void fatal(const char *fmt, ...)
64 {
65 	va_list ap;
66 
67 	va_start(ap, fmt);
68 	vfprintf(stderr, fmt, ap);
69 	va_end(ap);
70 	fprintf(stderr, "\n");
71 
72 	exit(ERROR);
73 }
74 
75 /*
76  * get_llong_from_str - get a long long int from a string
77  */
78 long long get_llong_from_str(char *start)
79 {
80 	long long value;
81 	char *end;
82 
83 	errno = 0;
84 	value = strtoll(start, &end, 10);
85 	if (errno || start == end)
86 		return -1;
87 
88 	return value;
89 }
90 
91 /*
92  * get_duration - fill output with a human readable duration since start_time
93  */
94 void get_duration(time_t start_time, char *output, int output_size)
95 {
96 	time_t now = time(NULL);
97 	struct tm *tm_info;
98 	time_t duration;
99 
100 	duration = difftime(now, start_time);
101 	tm_info = gmtime(&duration);
102 
103 	snprintf(output, output_size, "%3d %02d:%02d:%02d",
104 			tm_info->tm_yday,
105 			tm_info->tm_hour,
106 			tm_info->tm_min,
107 			tm_info->tm_sec);
108 }
109 
110 /*
111  * cpu_list_iterate - parse a cpu list and call a function on each element
112  *
113  * If callback returns a non-zero value, the iteration is stopped.
114  *
115  * Returns the number of cpus in the list (including duplicates) on success,
116  * callback return value on break, and -1 on error.
117  */
118 int cpu_list_iterate(const char *cpu_list, int (*callback)(int, void *), void *data)
119 {
120 	const char *p;
121 	int i, cpu, end_cpu, count = 0, retval;
122 
123 	for (p = cpu_list; *p && *p != '\n'; ) {
124 		cpu = atoi(p);
125 		if (cpu < 0 || (!cpu && *p != '0'))
126 			return -1;
127 
128 		while (isdigit(*p))
129 			p++;
130 		if (*p == '-') {
131 			p++;
132 			end_cpu = atoi(p);
133 			if (end_cpu < cpu || (!end_cpu && *p != '0'))
134 				return -1;
135 			while (isdigit(*p))
136 				p++;
137 		} else
138 			end_cpu = cpu;
139 
140 		for (i = cpu; i <= end_cpu; i++) {
141 			retval = callback(i, data);
142 			if (retval)
143 				return retval;
144 			++count;
145 		}
146 
147 		if (*p == ',')
148 			p++;
149 	}
150 
151 	return count;
152 }
153 
154 static int max_cpu_callback(int i, void *data)
155 {
156 	int *max_cpu = data;
157 
158 	if (i > *max_cpu)
159 		*max_cpu = i;
160 
161 	return 0;
162 }
163 
164 /*
165  * get_max_cpu_from_list - get the maximum CPU in a CPU list
166  *
167  * Returns maximum CPU number, or -1 on error
168  */
169 int get_max_cpu_from_list(const char *cpu_list)
170 {
171 	int max_cpu = -1;
172 
173 	if (cpu_list_iterate(cpu_list, max_cpu_callback, &max_cpu) < 0)
174 		return -1;
175 
176 	return max_cpu;
177 }
178 
179 
180 static int tmp_cpu_set_callback(int i, void *data)
181 {
182 	bool *cpu_set = data;
183 
184 	cpu_set[i] = true;
185 
186 	return 0;
187 }
188 
189 /*
190  * get_possible_cpus - get the number of possible CPUs from sysfs
191  *
192  * Parse /sys/devices/system/cpu/possible to determine the number of
193  * possible CPUs. Only contiguous zero-based CPUs lists are accepted.
194  *
195  * Returns the number of possible CPUs, or a negative value on error:
196  * - -1 if the file is unreadable,
197  * - -2 if parsing failed,
198  * - -3 if the cpu list is non-zero-based or non-contiguous.
199  */
200 int get_possible_cpus(void)
201 {
202 	char *str = NULL;
203 	size_t len = 0;
204 	int nr_cpus = 0, max_cpu = -1, i;
205 	FILE *fp;
206 	bool *cpu_set;
207 
208 	fp = fopen("/sys/devices/system/cpu/possible", "r");
209 	if (!fp)
210 		return -1;
211 
212 	if (getline(&str, &len, fp) < 1) {
213 		/* cpu string should be at least 1 character */
214 		if (str)
215 			free(str);
216 		fclose(fp);
217 		return -1;
218 	}
219 
220 	fclose(fp);
221 
222 	/* get maximum cpu number */
223 	if (cpu_list_iterate(str, max_cpu_callback, &max_cpu) < 0) {
224 		free(str);
225 		return -2;
226 	}
227 
228 	if (max_cpu < 0 || max_cpu == INT_MAX) {
229 		/* empty or bogus cpu list */
230 		free(str);
231 		return -2;
232 	}
233 
234 	/* get max cpu using dynamic array, as nr_cpus might be > 1024 */
235 	cpu_set = calloc(max_cpu + 1, sizeof(bool));
236 	if (!cpu_set) {
237 		free(str);
238 		return -2;
239 	}
240 	if (cpu_list_iterate(str, tmp_cpu_set_callback, cpu_set) < 0) {
241 		free(str);
242 		free(cpu_set);
243 		return -2;
244 	}
245 	for (i = 0; i <= max_cpu; i++) {
246 		if (cpu_set[i])
247 			++nr_cpus;
248 	}
249 	free(cpu_set);
250 
251 	free(str);
252 
253 	if (max_cpu >= nr_cpus)
254 		/* rtla assumes cpu < nr_cpus for all cpus */
255 		return -3;
256 
257 	return nr_cpus;
258 }
259 
260 static int cpu_set_callback(int i, void *data)
261 {
262 	cpu_set_t *set = data;
263 
264 	if (i >= nr_cpus || i >= CPU_SETSIZE)
265 		return -1;
266 
267 	debug_msg("cpu_set: adding cpu %d\n", i);
268 	CPU_SET(i, set);
269 
270 	return 0;
271 }
272 
273 /*
274  * parse_cpu_set - parse a cpu_list filling cpu_set_t argument
275  *
276  * Receives a cpu list, like 1-3,5 (cpus 1, 2, 3, 5), and then set
277  * filling cpu_set_t argument.
278  *
279  * Returns 0 on success, 1 otherwise.
280  */
281 int parse_cpu_set(char *cpu_list, cpu_set_t *set)
282 {
283 	CPU_ZERO(set);
284 
285 	if (cpu_list_iterate(cpu_list, cpu_set_callback, set) < 0) {
286 		debug_msg("Error parsing the cpu set %s\n", cpu_list);
287 		return 1;
288 	}
289 
290 	return 0;
291 }
292 
293 /*
294  * parse_stack_format - parse the stack format
295  *
296  * Return: the stack format on success, -1 otherwise.
297  */
298 int parse_stack_format(char *arg)
299 {
300 	if (!strcmp(arg, "truncate"))
301 		return STACK_FORMAT_TRUNCATE;
302 	if (!strcmp(arg, "skip"))
303 		return STACK_FORMAT_SKIP;
304 	if (!strcmp(arg, "full"))
305 		return STACK_FORMAT_FULL;
306 
307 	debug_msg("Error parsing the stack format %s\n", arg);
308 	return -1;
309 }
310 
311 /*
312  * parse_duration - parse duration with s/m/h/d suffix converting it to seconds
313  */
314 long parse_seconds_duration(char *val)
315 {
316 	char *end;
317 	long t;
318 
319 	t = strtol(val, &end, 10);
320 
321 	if (end) {
322 		switch (*end) {
323 		case 's':
324 		case 'S':
325 			break;
326 		case 'm':
327 		case 'M':
328 			t *= 60;
329 			break;
330 		case 'h':
331 		case 'H':
332 			t *= 60 * 60;
333 			break;
334 
335 		case 'd':
336 		case 'D':
337 			t *= 24 * 60 * 60;
338 			break;
339 		}
340 	}
341 
342 	return t;
343 }
344 
345 /*
346  * match_time_unit - check if str starts with unit followed by end-of-string or ':'
347  *
348  * This allows the time unit parser to work both in standalone duration strings
349  * like "100ms" and in colon-delimited SCHED_DEADLINE specifications like
350  * "d:10ms:100ms", while still rejecting malformed input like "100msx".
351  */
352 static bool match_time_unit(const char *str, const char *unit)
353 {
354 	size_t len = strlen(unit);
355 
356 	return strncmp(str, unit, len) == 0 &&
357 	       (str[len] == '\0' || str[len] == ':');
358 }
359 
360 /*
361  * parse_ns_duration - parse duration with ns/us/ms/s converting it to nanoseconds
362  */
363 long parse_ns_duration(char *val)
364 {
365 	char *end;
366 	long t;
367 
368 	t = strtol(val, &end, 10);
369 
370 	if (end) {
371 		if (match_time_unit(end, "ns")) {
372 			return t;
373 		} else if (match_time_unit(end, "us")) {
374 			t *= 1000;
375 			return t;
376 		} else if (match_time_unit(end, "ms")) {
377 			t *= 1000 * 1000;
378 			return t;
379 		} else if (match_time_unit(end, "s")) {
380 			t *= 1000 * 1000 * 1000;
381 			return t;
382 		}
383 		return -1;
384 	}
385 
386 	return t;
387 }
388 
389 /*
390  * This is a set of helper functions to use SCHED_DEADLINE.
391  */
392 #ifndef __NR_sched_setattr
393 # ifdef __x86_64__
394 #  define __NR_sched_setattr	314
395 # elif __i386__
396 #  define __NR_sched_setattr	351
397 # elif __arm__
398 #  define __NR_sched_setattr	380
399 # elif __aarch64__ || __riscv
400 #  define __NR_sched_setattr	274
401 # elif __powerpc__
402 #  define __NR_sched_setattr	355
403 # elif __s390x__
404 #  define __NR_sched_setattr	345
405 # elif __loongarch__
406 #  define __NR_sched_setattr	274
407 # endif
408 #endif
409 
410 #define SCHED_DEADLINE		6
411 
412 static inline int syscall_sched_setattr(pid_t pid, const struct sched_attr *attr,
413 				unsigned int flags) {
414 	return syscall(__NR_sched_setattr, pid, attr, flags);
415 }
416 
417 int __set_sched_attr(int pid, struct sched_attr *attr)
418 {
419 	int flags = 0;
420 	int retval;
421 
422 	retval = syscall_sched_setattr(pid, attr, flags);
423 	if (retval < 0) {
424 		err_msg("Failed to set sched attributes to the pid %d: %s\n",
425 			pid, strerror(errno));
426 		return 1;
427 	}
428 
429 	return 0;
430 }
431 
432 /*
433  * procfs_is_workload_pid - check if a procfs entry contains a comm_prefix* comm
434  *
435  * Check if the procfs entry is a directory of a process, and then check if the
436  * process has a comm with the prefix set in char *comm_prefix. As the
437  * current users of this function only check for kernel threads, there is no
438  * need to check for the threads for the process.
439  *
440  * Return: True if the proc_entry contains a comm file with comm_prefix*.
441  * Otherwise returns false.
442  */
443 static int procfs_is_workload_pid(const char *comm_prefix, struct dirent *proc_entry)
444 {
445 	char buffer[MAX_PATH];
446 	int comm_fd, retval;
447 	char *t_name;
448 
449 	if (proc_entry->d_type != DT_DIR)
450 		return 0;
451 
452 	if (*proc_entry->d_name == '.')
453 		return 0;
454 
455 	/* check if the string is a pid */
456 	for (t_name = proc_entry->d_name; *t_name; t_name++) {
457 		if (!isdigit(*t_name))
458 			break;
459 	}
460 
461 	if (*t_name != '\0')
462 		return 0;
463 
464 	snprintf(buffer, MAX_PATH, "/proc/%s/comm", proc_entry->d_name);
465 	comm_fd = open(buffer, O_RDONLY);
466 	if (comm_fd < 0)
467 		return 0;
468 
469 	memset(buffer, 0, MAX_PATH);
470 	retval = read(comm_fd, buffer, MAX_PATH);
471 
472 	close(comm_fd);
473 
474 	if (retval <= 0)
475 		return 0;
476 
477 	buffer[MAX_PATH-1] = '\0';
478 	if (!str_has_prefix(buffer, comm_prefix))
479 		return 0;
480 
481 	/* comm already have \n */
482 	debug_msg("Found workload pid:%s comm:%s", proc_entry->d_name, buffer);
483 
484 	return 1;
485 }
486 
487 /*
488  * set_comm_sched_attr - set sched params to threads starting with char *comm_prefix
489  *
490  * This function uses procfs to list the currently running threads and then set the
491  * sched_attr *attr to the threads that start with char *comm_prefix. It is
492  * mainly used to set the priority to the kernel threads created by the
493  * tracers.
494  */
495 int set_comm_sched_attr(const char *comm_prefix, struct sched_attr *attr)
496 {
497 	struct dirent *proc_entry;
498 	DIR *procfs;
499 	int retval;
500 	int pid;
501 
502 	if (strlen(comm_prefix) >= MAX_PATH) {
503 		err_msg("Command prefix is too long: %d < strlen(%s)\n",
504 			MAX_PATH, comm_prefix);
505 		return 1;
506 	}
507 
508 	procfs = opendir("/proc");
509 	if (!procfs) {
510 		err_msg("Could not open procfs\n");
511 		return 1;
512 	}
513 
514 	while ((proc_entry = readdir(procfs))) {
515 
516 		retval = procfs_is_workload_pid(comm_prefix, proc_entry);
517 		if (!retval)
518 			continue;
519 
520 		if (strtoi(proc_entry->d_name, &pid)) {
521 			err_msg("'%s' is not a valid pid", proc_entry->d_name);
522 			retval = 1;
523 			goto out;
524 		}
525 		/* procfs_is_workload_pid confirmed it is a pid */
526 		retval = __set_sched_attr(pid, attr);
527 		if (retval) {
528 			err_msg("Error setting sched attributes for pid:%s\n", proc_entry->d_name);
529 			goto out;
530 		}
531 
532 		debug_msg("Set sched attributes for pid:%s\n", proc_entry->d_name);
533 	}
534 
535 	retval = 0;
536 out:
537 	closedir(procfs);
538 	return retval;
539 }
540 
541 #define INVALID_VAL	(~0L)
542 static long get_long_ns_after_colon(char *start)
543 {
544 	long val = INVALID_VAL;
545 
546 	/* find the ":" */
547 	start = strstr(start, ":");
548 	if (!start)
549 		return -1;
550 
551 	/* skip ":" */
552 	start++;
553 	val = parse_ns_duration(start);
554 
555 	return val;
556 }
557 
558 static long get_long_after_colon(char *start)
559 {
560 	long val = INVALID_VAL;
561 
562 	/* find the ":" */
563 	start = strstr(start, ":");
564 	if (!start)
565 		return -1;
566 
567 	/* skip ":" */
568 	start++;
569 	val = get_llong_from_str(start);
570 
571 	return val;
572 }
573 
574 /*
575  * parse priority in the format:
576  * SCHED_OTHER:
577  *		o:<prio>
578  *		O:<prio>
579  * SCHED_RR:
580  *		r:<prio>
581  *		R:<prio>
582  * SCHED_FIFO:
583  *		f:<prio>
584  *		F:<prio>
585  * SCHED_DEADLINE:
586  *		d:runtime:period
587  *		D:runtime:period
588  */
589 int parse_prio(char *arg, struct sched_attr *sched_param)
590 {
591 	long prio;
592 	long runtime;
593 	long period;
594 
595 	memset(sched_param, 0, sizeof(*sched_param));
596 	sched_param->size = sizeof(*sched_param);
597 
598 	switch (arg[0]) {
599 	case 'd':
600 	case 'D':
601 		/* d:runtime:period */
602 		if (strlen(arg) < 4)
603 			return -1;
604 
605 		runtime = get_long_ns_after_colon(arg);
606 		if (runtime == INVALID_VAL)
607 			return -1;
608 
609 		period = get_long_ns_after_colon(&arg[2]);
610 		if (period == INVALID_VAL)
611 			return -1;
612 
613 		if (runtime > period)
614 			return -1;
615 
616 		sched_param->sched_policy   = SCHED_DEADLINE;
617 		sched_param->sched_runtime  = runtime;
618 		sched_param->sched_deadline = period;
619 		sched_param->sched_period   = period;
620 		break;
621 	case 'f':
622 	case 'F':
623 		/* f:prio */
624 		prio = get_long_after_colon(arg);
625 		if (prio == INVALID_VAL)
626 			return -1;
627 
628 		if (prio < sched_get_priority_min(SCHED_FIFO))
629 			return -1;
630 		if (prio > sched_get_priority_max(SCHED_FIFO))
631 			return -1;
632 
633 		sched_param->sched_policy   = SCHED_FIFO;
634 		sched_param->sched_priority = prio;
635 		break;
636 	case 'r':
637 	case 'R':
638 		/* r:prio */
639 		prio = get_long_after_colon(arg);
640 		if (prio == INVALID_VAL)
641 			return -1;
642 
643 		if (prio < sched_get_priority_min(SCHED_RR))
644 			return -1;
645 		if (prio > sched_get_priority_max(SCHED_RR))
646 			return -1;
647 
648 		sched_param->sched_policy   = SCHED_RR;
649 		sched_param->sched_priority = prio;
650 		break;
651 	case 'o':
652 	case 'O':
653 		/* o:prio */
654 		prio = get_long_after_colon(arg);
655 		if (prio == INVALID_VAL)
656 			return -1;
657 
658 		if (prio < MIN_NICE)
659 			return -1;
660 		if (prio > MAX_NICE)
661 			return -1;
662 
663 		sched_param->sched_policy   = SCHED_OTHER;
664 		sched_param->sched_nice = prio;
665 		break;
666 	default:
667 		return -1;
668 	}
669 	return 0;
670 }
671 
672 /*
673  * set_cpu_dma_latency - set the /dev/cpu_dma_latecy
674  *
675  * This is used to reduce the exit from idle latency. The value
676  * will be reset once the file descriptor of /dev/cpu_dma_latecy
677  * is closed.
678  *
679  * Return: the /dev/cpu_dma_latecy file descriptor
680  */
681 int set_cpu_dma_latency(int32_t latency)
682 {
683 	int retval;
684 	int fd;
685 
686 	fd = open("/dev/cpu_dma_latency", O_RDWR);
687 	if (fd < 0) {
688 		err_msg("Error opening /dev/cpu_dma_latency\n");
689 		return -1;
690 	}
691 
692 	retval = write(fd, &latency, 4);
693 	if (retval < 1) {
694 		err_msg("Error setting /dev/cpu_dma_latency\n");
695 		close(fd);
696 		return -1;
697 	}
698 
699 	debug_msg("Set /dev/cpu_dma_latency to %d\n", latency);
700 
701 	return fd;
702 }
703 
704 #ifdef HAVE_LIBCPUPOWER_SUPPORT
705 static unsigned int **saved_cpu_idle_disable_state;
706 static size_t saved_cpu_idle_disable_state_alloc_ctr;
707 
708 /*
709  * save_cpu_idle_state_disable - save disable for all idle states of a cpu
710  *
711  * Saves the current disable of all idle states of a cpu, to be subsequently
712  * restored via restore_cpu_idle_disable_state.
713  *
714  * Return: idle state count on success, negative on error
715  */
716 int save_cpu_idle_disable_state(unsigned int cpu)
717 {
718 	unsigned int nr_states;
719 	unsigned int state;
720 	int disabled;
721 
722 	nr_states = cpuidle_state_count(cpu);
723 
724 	if (nr_states == 0)
725 		return 0;
726 
727 	if (saved_cpu_idle_disable_state == NULL) {
728 		saved_cpu_idle_disable_state = calloc(nr_cpus, sizeof(unsigned int *));
729 		if (!saved_cpu_idle_disable_state)
730 			return -1;
731 	}
732 
733 	saved_cpu_idle_disable_state[cpu] = calloc(nr_states, sizeof(unsigned int));
734 	if (!saved_cpu_idle_disable_state[cpu])
735 		return -1;
736 	saved_cpu_idle_disable_state_alloc_ctr++;
737 
738 	for (state = 0; state < nr_states; state++) {
739 		disabled = cpuidle_is_state_disabled(cpu, state);
740 		if (disabled < 0)
741 			return disabled;
742 		saved_cpu_idle_disable_state[cpu][state] = disabled;
743 	}
744 
745 	return nr_states;
746 }
747 
748 /*
749  * restore_cpu_idle_disable_state - restore disable for all idle states of a cpu
750  *
751  * Restores the current disable state of all idle states of a cpu that was
752  * previously saved by save_cpu_idle_disable_state.
753  *
754  * Return: idle state count on success, negative on error
755  */
756 int restore_cpu_idle_disable_state(unsigned int cpu)
757 {
758 	unsigned int nr_states;
759 	unsigned int state;
760 	int disabled;
761 	int result;
762 
763 	nr_states = cpuidle_state_count(cpu);
764 
765 	if (nr_states == 0)
766 		return 0;
767 
768 	if (!saved_cpu_idle_disable_state)
769 		return -1;
770 
771 	for (state = 0; state < nr_states; state++) {
772 		if (!saved_cpu_idle_disable_state[cpu])
773 			return -1;
774 		disabled = saved_cpu_idle_disable_state[cpu][state];
775 		result = cpuidle_state_disable(cpu, state, disabled);
776 		if (result < 0)
777 			return result;
778 	}
779 
780 	free(saved_cpu_idle_disable_state[cpu]);
781 	saved_cpu_idle_disable_state[cpu] = NULL;
782 	saved_cpu_idle_disable_state_alloc_ctr--;
783 	if (saved_cpu_idle_disable_state_alloc_ctr == 0) {
784 		free(saved_cpu_idle_disable_state);
785 		saved_cpu_idle_disable_state = NULL;
786 	}
787 
788 	return nr_states;
789 }
790 
791 /*
792  * free_cpu_idle_disable_states - free saved idle state disable for all cpus
793  *
794  * Frees the memory used for storing cpu idle state disable for all cpus
795  * and states.
796  *
797  * Normally, the memory is freed automatically in
798  * restore_cpu_idle_disable_state; this is mostly for cleaning up after an
799  * error.
800  */
801 void free_cpu_idle_disable_states(void)
802 {
803 	int cpu;
804 
805 	if (!saved_cpu_idle_disable_state)
806 		return;
807 
808 	for (cpu = 0; cpu < nr_cpus; cpu++) {
809 		free(saved_cpu_idle_disable_state[cpu]);
810 		saved_cpu_idle_disable_state[cpu] = NULL;
811 	}
812 
813 	free(saved_cpu_idle_disable_state);
814 	saved_cpu_idle_disable_state = NULL;
815 }
816 
817 /*
818  * set_deepest_cpu_idle_state - limit idle state of cpu
819  *
820  * Disables all idle states deeper than the one given in
821  * deepest_state (assuming states with higher number are deeper).
822  *
823  * This is used to reduce the exit from idle latency. Unlike
824  * set_cpu_dma_latency, it can disable idle states per cpu.
825  *
826  * Return: idle state count on success, negative on error
827  */
828 int set_deepest_cpu_idle_state(unsigned int cpu, unsigned int deepest_state)
829 {
830 	unsigned int nr_states;
831 	unsigned int state;
832 	int result;
833 
834 	nr_states = cpuidle_state_count(cpu);
835 
836 	for (state = deepest_state + 1; state < nr_states; state++) {
837 		result = cpuidle_state_disable(cpu, state, 1);
838 		if (result < 0)
839 			return result;
840 	}
841 
842 	return nr_states;
843 }
844 #endif /* HAVE_LIBCPUPOWER_SUPPORT */
845 
846 #define _STR(x) #x
847 #define STR(x) _STR(x)
848 
849 /*
850  * find_mount - find a the mount point of a given fs
851  *
852  * Returns 0 if mount is not found, otherwise return 1 and fill mp
853  * with the mount point.
854  */
855 static const int find_mount(const char *fs, char *mp, int sizeof_mp)
856 {
857 	char mount_point[MAX_PATH+1];
858 	char type[100];
859 	int found = 0;
860 	FILE *fp;
861 
862 	fp = fopen("/proc/mounts", "r");
863 	if (!fp)
864 		return 0;
865 
866 	while (fscanf(fp, "%*s %" STR(MAX_PATH) "s %99s %*s %*d %*d\n",	mount_point, type) == 2) {
867 		if (strcmp(type, fs) == 0) {
868 			found = 1;
869 			break;
870 		}
871 	}
872 	fclose(fp);
873 
874 	if (!found)
875 		return 0;
876 
877 	memset(mp, 0, sizeof_mp);
878 	strncpy(mp, mount_point, sizeof_mp - 1);
879 
880 	debug_msg("Fs %s found at %s\n", fs, mp);
881 	return 1;
882 }
883 
884 /*
885  * get_self_cgroup - get the current thread cgroup path
886  *
887  * Parse /proc/$$/cgroup file to get the thread's cgroup. As an example of line to parse:
888  *
889  * 0::/user.slice/user-0.slice/session-3.scope'\n'
890  *
891  * This function is interested in the content after the second : and before the '\n'.
892  *
893  * Returns 1 if a string was found, 0 otherwise.
894  */
895 static int get_self_cgroup(char *self_cg, int sizeof_self_cg)
896 {
897 	char path[MAX_PATH], *start;
898 	int fd, retval;
899 
900 	snprintf(path, MAX_PATH, "/proc/%d/cgroup", getpid());
901 
902 	fd = open(path, O_RDONLY);
903 	if (fd < 0)
904 		return 0;
905 
906 	memset(path, 0, sizeof(path));
907 	retval = read(fd, path, MAX_PATH);
908 
909 	close(fd);
910 
911 	if (retval <= 0)
912 		return 0;
913 
914 	path[MAX_PATH-1] = '\0';
915 	start = path;
916 
917 	start = strstr(start, ":");
918 	if (!start)
919 		return 0;
920 
921 	/* skip ":" */
922 	start++;
923 
924 	start = strstr(start, ":");
925 	if (!start)
926 		return 0;
927 
928 	/* skip ":" */
929 	start++;
930 
931 	if (strlen(start) >= sizeof_self_cg)
932 		return 0;
933 
934 	snprintf(self_cg, sizeof_self_cg, "%s", start);
935 
936 	/* Swap '\n' with '\0' */
937 	start = strstr(self_cg, "\n");
938 
939 	/* there must be '\n' */
940 	if (!start)
941 		return 0;
942 
943 	/* ok, it found a string after the second : and before the \n */
944 	*start = '\0';
945 
946 	return 1;
947 }
948 
949 /*
950  * open_cgroup_procs - Open the cgroup.procs file for the given cgroup
951  *
952  * If cgroup argument is not NULL, the cgroup.procs file for that cgroup
953  * will be opened. Otherwise, the cgroup of the calling, i.e., rtla, thread
954  * will be used.
955  *
956  * Supports cgroup v2.
957  *
958  * Returns the file descriptor on success, -1 otherwise.
959  */
960 static int open_cgroup_procs(const char *cgroup)
961 {
962 	char cgroup_path[MAX_PATH - strlen("/cgroup.procs")];
963 	char cgroup_procs[MAX_PATH];
964 	int retval;
965 	int cg_fd;
966 	size_t cg_path_len;
967 
968 	retval = find_mount("cgroup2", cgroup_path, sizeof(cgroup_path));
969 	if (!retval) {
970 		err_msg("Did not find cgroupv2 mount point\n");
971 		return -1;
972 	}
973 
974 	cg_path_len = strlen(cgroup_path);
975 
976 	if (!cgroup) {
977 		retval = get_self_cgroup(&cgroup_path[cg_path_len],
978 				sizeof(cgroup_path) - cg_path_len);
979 		if (!retval) {
980 			err_msg("Did not find self cgroup\n");
981 			return -1;
982 		}
983 	} else {
984 		snprintf(&cgroup_path[cg_path_len],
985 				sizeof(cgroup_path) - cg_path_len, "%s/", cgroup);
986 	}
987 
988 	snprintf(cgroup_procs, MAX_PATH, "%s/cgroup.procs", cgroup_path);
989 
990 	debug_msg("Using cgroup path at: %s\n", cgroup_procs);
991 
992 	cg_fd = open(cgroup_procs, O_RDWR);
993 	if (cg_fd < 0)
994 		return -1;
995 
996 	return cg_fd;
997 }
998 
999 /*
1000  * set_pid_cgroup - Set cgroup to pid_t pid
1001  *
1002  * If cgroup argument is not NULL, the threads will move to the given cgroup.
1003  * Otherwise, the cgroup of the calling, i.e., rtla, thread will be used.
1004  *
1005  * Supports cgroup v2.
1006  *
1007  * Returns 1 on success, 0 otherwise.
1008  */
1009 int set_pid_cgroup(pid_t pid, const char *cgroup)
1010 {
1011 	char pid_str[24];
1012 	int retval;
1013 	int cg_fd;
1014 
1015 	cg_fd = open_cgroup_procs(cgroup);
1016 	if (cg_fd < 0)
1017 		return 0;
1018 
1019 	snprintf(pid_str, sizeof(pid_str), "%d\n", pid);
1020 
1021 	retval = write(cg_fd, pid_str, strlen(pid_str));
1022 	if (retval < 0)
1023 		err_msg("Error setting cgroup attributes for pid:%s - %s\n",
1024 				pid_str, strerror(errno));
1025 	else
1026 		debug_msg("Set cgroup attributes for pid:%s\n", pid_str);
1027 
1028 	close(cg_fd);
1029 
1030 	return (retval >= 0);
1031 }
1032 
1033 /**
1034  * set_comm_cgroup - Set cgroup to threads starting with char *comm_prefix
1035  *
1036  * If cgroup argument is not NULL, the threads will move to the given cgroup.
1037  * Otherwise, the cgroup of the calling, i.e., rtla, thread will be used.
1038  *
1039  * Supports cgroup v2.
1040  *
1041  * Returns 1 on success, 0 otherwise.
1042  */
1043 int set_comm_cgroup(const char *comm_prefix, const char *cgroup)
1044 {
1045 	struct dirent *proc_entry;
1046 	DIR *procfs;
1047 	int retval;
1048 	int cg_fd;
1049 
1050 	if (strlen(comm_prefix) >= MAX_PATH) {
1051 		err_msg("Command prefix is too long: %d < strlen(%s)\n",
1052 			MAX_PATH, comm_prefix);
1053 		return 0;
1054 	}
1055 
1056 	cg_fd = open_cgroup_procs(cgroup);
1057 	if (cg_fd < 0)
1058 		return 0;
1059 
1060 	procfs = opendir("/proc");
1061 	if (!procfs) {
1062 		err_msg("Could not open procfs\n");
1063 		goto out_cg;
1064 	}
1065 
1066 	while ((proc_entry = readdir(procfs))) {
1067 
1068 		retval = procfs_is_workload_pid(comm_prefix, proc_entry);
1069 		if (!retval)
1070 			continue;
1071 
1072 		retval = write(cg_fd, proc_entry->d_name, strlen(proc_entry->d_name));
1073 		if (retval < 0) {
1074 			err_msg("Error setting cgroup attributes for pid:%s - %s\n",
1075 				proc_entry->d_name, strerror(errno));
1076 			goto out_procfs;
1077 		}
1078 
1079 		debug_msg("Set cgroup attributes for pid:%s\n", proc_entry->d_name);
1080 	}
1081 
1082 	closedir(procfs);
1083 	close(cg_fd);
1084 	return 1;
1085 
1086 out_procfs:
1087 	closedir(procfs);
1088 out_cg:
1089 	close(cg_fd);
1090 	return 0;
1091 }
1092 
1093 /**
1094  * auto_house_keeping - Automatically move rtla out of measurement threads
1095  *
1096  * Try to move rtla away from the tracer, if possible.
1097  *
1098  * Returns 1 on success, 0 otherwise.
1099  */
1100 int auto_house_keeping(cpu_set_t *monitored_cpus)
1101 {
1102 	cpu_set_t rtla_cpus, house_keeping_cpus;
1103 	int retval;
1104 
1105 	/* first get the CPUs in which rtla can actually run. */
1106 	retval = sched_getaffinity(getpid(), sizeof(rtla_cpus), &rtla_cpus);
1107 	if (retval == -1) {
1108 		debug_msg("Could not get rtla affinity, rtla might run with the threads!\n");
1109 		return 0;
1110 	}
1111 
1112 	/* then check if the existing setup is already good. */
1113 	CPU_AND(&house_keeping_cpus, &rtla_cpus, monitored_cpus);
1114 	if (!CPU_COUNT(&house_keeping_cpus)) {
1115 		debug_msg("rtla and the monitored CPUs do not share CPUs.");
1116 		debug_msg("Skipping auto house-keeping\n");
1117 		return 1;
1118 	}
1119 
1120 	/* remove the intersection */
1121 	CPU_XOR(&house_keeping_cpus, &rtla_cpus, monitored_cpus);
1122 
1123 	/* get only those that rtla can run */
1124 	CPU_AND(&house_keeping_cpus, &house_keeping_cpus, &rtla_cpus);
1125 
1126 	/* is there any cpu left? */
1127 	if (!CPU_COUNT(&house_keeping_cpus)) {
1128 		debug_msg("Could not find any CPU for auto house-keeping\n");
1129 		return 0;
1130 	}
1131 
1132 	retval = sched_setaffinity(getpid(), sizeof(house_keeping_cpus), &house_keeping_cpus);
1133 	if (retval == -1) {
1134 		debug_msg("Could not set affinity for auto house-keeping\n");
1135 		return 0;
1136 	}
1137 
1138 	debug_msg("rtla automatically moved to an auto house-keeping cpu set\n");
1139 
1140 	return 1;
1141 }
1142 
1143 /*
1144  * strtoi - convert string to integer with error checking
1145  *
1146  * Returns 0 on success, -1 if conversion fails or result is out of int range.
1147  */
1148 int strtoi(const char *s, int *res)
1149 {
1150 	char *end_ptr;
1151 	long lres;
1152 
1153 	if (!*s)
1154 		return -1;
1155 
1156 	errno = 0;
1157 	lres = strtol(s, &end_ptr, 0);
1158 	if (errno || *end_ptr || lres > INT_MAX || lres < INT_MIN)
1159 		return -1;
1160 
1161 	*res = (int) lres;
1162 	return 0;
1163 }
1164 
1165 static inline void fatal_alloc(void)
1166 {
1167 	fatal("Error allocating memory\n");
1168 }
1169 
1170 void *calloc_fatal(size_t n, size_t size)
1171 {
1172 	void *p = calloc(n, size);
1173 
1174 	if (!p)
1175 		fatal_alloc();
1176 
1177 	return p;
1178 }
1179 
1180 void *reallocarray_fatal(void *p, size_t n, size_t size)
1181 {
1182 	p = reallocarray(p, n, size);
1183 
1184 	if (!p)
1185 		fatal_alloc();
1186 
1187 	return p;
1188 }
1189 
1190 char *strdup_fatal(const char *s)
1191 {
1192 	char *p = strdup(s);
1193 
1194 	if (!p)
1195 		fatal_alloc();
1196 
1197 	return p;
1198 }
1199