xref: /linux-6.15/tools/tracing/rtla/src/utils.c (revision 083d29d3)
1b1696371SDaniel Bristot de Oliveira // SPDX-License-Identifier: GPL-2.0
2b1696371SDaniel Bristot de Oliveira /*
3b1696371SDaniel Bristot de Oliveira  * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <[email protected]>
4b1696371SDaniel Bristot de Oliveira  */
5b1696371SDaniel Bristot de Oliveira 
6272ced25SDaniel Bristot de Oliveira #define _GNU_SOURCE
7*083d29d3STomas Glozar #ifdef HAVE_LIBCPUPOWER_SUPPORT
8*083d29d3STomas Glozar #include <cpuidle.h>
9*083d29d3STomas Glozar #endif /* HAVE_LIBCPUPOWER_SUPPORT */
10dada03dbSDaniel Bristot de Oliveira #include <dirent.h>
11b1696371SDaniel Bristot de Oliveira #include <stdarg.h>
12b1696371SDaniel Bristot de Oliveira #include <stdlib.h>
13b1696371SDaniel Bristot de Oliveira #include <string.h>
14b1696371SDaniel Bristot de Oliveira #include <unistd.h>
15b1696371SDaniel Bristot de Oliveira #include <ctype.h>
16b1696371SDaniel Bristot de Oliveira #include <errno.h>
177d0dc957SDaniel Bristot de Oliveira #include <fcntl.h>
18b1696371SDaniel Bristot de Oliveira #include <sched.h>
19b1696371SDaniel Bristot de Oliveira #include <stdio.h>
20b1696371SDaniel Bristot de Oliveira 
21b1696371SDaniel Bristot de Oliveira #include "utils.h"
22b1696371SDaniel Bristot de Oliveira 
23b1696371SDaniel Bristot de Oliveira #define MAX_MSG_LENGTH	1024
24b1696371SDaniel Bristot de Oliveira int config_debug;
25b1696371SDaniel Bristot de Oliveira 
26b1696371SDaniel Bristot de Oliveira /*
27b1696371SDaniel Bristot de Oliveira  * err_msg - print an error message to the stderr
28b1696371SDaniel Bristot de Oliveira  */
err_msg(const char * fmt,...)29b1696371SDaniel Bristot de Oliveira void err_msg(const char *fmt, ...)
30b1696371SDaniel Bristot de Oliveira {
31b1696371SDaniel Bristot de Oliveira 	char message[MAX_MSG_LENGTH];
32b1696371SDaniel Bristot de Oliveira 	va_list ap;
33b1696371SDaniel Bristot de Oliveira 
34b1696371SDaniel Bristot de Oliveira 	va_start(ap, fmt);
35b1696371SDaniel Bristot de Oliveira 	vsnprintf(message, sizeof(message), fmt, ap);
36b1696371SDaniel Bristot de Oliveira 	va_end(ap);
37b1696371SDaniel Bristot de Oliveira 
38b1696371SDaniel Bristot de Oliveira 	fprintf(stderr, "%s", message);
39b1696371SDaniel Bristot de Oliveira }
40b1696371SDaniel Bristot de Oliveira 
41b1696371SDaniel Bristot de Oliveira /*
42b1696371SDaniel Bristot de Oliveira  * debug_msg - print a debug message to stderr if debug is set
43b1696371SDaniel Bristot de Oliveira  */
debug_msg(const char * fmt,...)44b1696371SDaniel Bristot de Oliveira void debug_msg(const char *fmt, ...)
45b1696371SDaniel Bristot de Oliveira {
46b1696371SDaniel Bristot de Oliveira 	char message[MAX_MSG_LENGTH];
47b1696371SDaniel Bristot de Oliveira 	va_list ap;
48b1696371SDaniel Bristot de Oliveira 
49b1696371SDaniel Bristot de Oliveira 	if (!config_debug)
50b1696371SDaniel Bristot de Oliveira 		return;
51b1696371SDaniel Bristot de Oliveira 
52b1696371SDaniel Bristot de Oliveira 	va_start(ap, fmt);
53b1696371SDaniel Bristot de Oliveira 	vsnprintf(message, sizeof(message), fmt, ap);
54b1696371SDaniel Bristot de Oliveira 	va_end(ap);
55b1696371SDaniel Bristot de Oliveira 
56b1696371SDaniel Bristot de Oliveira 	fprintf(stderr, "%s", message);
57b1696371SDaniel Bristot de Oliveira }
58b1696371SDaniel Bristot de Oliveira 
59b1696371SDaniel Bristot de Oliveira /*
60b1696371SDaniel Bristot de Oliveira  * get_llong_from_str - get a long long int from a string
61b1696371SDaniel Bristot de Oliveira  */
get_llong_from_str(char * start)62b1696371SDaniel Bristot de Oliveira long long get_llong_from_str(char *start)
63b1696371SDaniel Bristot de Oliveira {
64b1696371SDaniel Bristot de Oliveira 	long long value;
65b1696371SDaniel Bristot de Oliveira 	char *end;
66b1696371SDaniel Bristot de Oliveira 
67b1696371SDaniel Bristot de Oliveira 	errno = 0;
68b1696371SDaniel Bristot de Oliveira 	value = strtoll(start, &end, 10);
69b1696371SDaniel Bristot de Oliveira 	if (errno || start == end)
70b1696371SDaniel Bristot de Oliveira 		return -1;
71b1696371SDaniel Bristot de Oliveira 
72b1696371SDaniel Bristot de Oliveira 	return value;
73b1696371SDaniel Bristot de Oliveira }
74b1696371SDaniel Bristot de Oliveira 
75b1696371SDaniel Bristot de Oliveira /*
76b1696371SDaniel Bristot de Oliveira  * get_duration - fill output with a human readable duration since start_time
77b1696371SDaniel Bristot de Oliveira  */
get_duration(time_t start_time,char * output,int output_size)78b1696371SDaniel Bristot de Oliveira void get_duration(time_t start_time, char *output, int output_size)
79b1696371SDaniel Bristot de Oliveira {
80b1696371SDaniel Bristot de Oliveira 	time_t now = time(NULL);
81b1696371SDaniel Bristot de Oliveira 	struct tm *tm_info;
82b1696371SDaniel Bristot de Oliveira 	time_t duration;
83b1696371SDaniel Bristot de Oliveira 
84b1696371SDaniel Bristot de Oliveira 	duration = difftime(now, start_time);
85f35491b8SDaniel Bristot de Oliveira 	tm_info = gmtime(&duration);
86b1696371SDaniel Bristot de Oliveira 
87b1696371SDaniel Bristot de Oliveira 	snprintf(output, output_size, "%3d %02d:%02d:%02d",
88b1696371SDaniel Bristot de Oliveira 			tm_info->tm_yday,
89f35491b8SDaniel Bristot de Oliveira 			tm_info->tm_hour,
90b1696371SDaniel Bristot de Oliveira 			tm_info->tm_min,
91b1696371SDaniel Bristot de Oliveira 			tm_info->tm_sec);
92b1696371SDaniel Bristot de Oliveira }
93b1696371SDaniel Bristot de Oliveira 
94b1696371SDaniel Bristot de Oliveira /*
95272ced25SDaniel Bristot de Oliveira  * parse_cpu_set - parse a cpu_list filling cpu_set_t argument
96272ced25SDaniel Bristot de Oliveira  *
97272ced25SDaniel Bristot de Oliveira  * Receives a cpu list, like 1-3,5 (cpus 1, 2, 3, 5), and then set
98272ced25SDaniel Bristot de Oliveira  * filling cpu_set_t argument.
99272ced25SDaniel Bristot de Oliveira  *
100272ced25SDaniel Bristot de Oliveira  * Returns 1 on success, 0 otherwise.
101272ced25SDaniel Bristot de Oliveira  */
parse_cpu_set(char * cpu_list,cpu_set_t * set)102272ced25SDaniel Bristot de Oliveira int parse_cpu_set(char *cpu_list, cpu_set_t *set)
103272ced25SDaniel Bristot de Oliveira {
104272ced25SDaniel Bristot de Oliveira 	const char *p;
105272ced25SDaniel Bristot de Oliveira 	int end_cpu;
106272ced25SDaniel Bristot de Oliveira 	int nr_cpus;
107272ced25SDaniel Bristot de Oliveira 	int cpu;
108272ced25SDaniel Bristot de Oliveira 	int i;
109272ced25SDaniel Bristot de Oliveira 
110272ced25SDaniel Bristot de Oliveira 	CPU_ZERO(set);
111272ced25SDaniel Bristot de Oliveira 
112272ced25SDaniel Bristot de Oliveira 	nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
113272ced25SDaniel Bristot de Oliveira 
114272ced25SDaniel Bristot de Oliveira 	for (p = cpu_list; *p; ) {
115272ced25SDaniel Bristot de Oliveira 		cpu = atoi(p);
116272ced25SDaniel Bristot de Oliveira 		if (cpu < 0 || (!cpu && *p != '0') || cpu >= nr_cpus)
117272ced25SDaniel Bristot de Oliveira 			goto err;
118272ced25SDaniel Bristot de Oliveira 
119272ced25SDaniel Bristot de Oliveira 		while (isdigit(*p))
120272ced25SDaniel Bristot de Oliveira 			p++;
121272ced25SDaniel Bristot de Oliveira 		if (*p == '-') {
122272ced25SDaniel Bristot de Oliveira 			p++;
123272ced25SDaniel Bristot de Oliveira 			end_cpu = atoi(p);
124272ced25SDaniel Bristot de Oliveira 			if (end_cpu < cpu || (!end_cpu && *p != '0') || end_cpu >= nr_cpus)
125272ced25SDaniel Bristot de Oliveira 				goto err;
126272ced25SDaniel Bristot de Oliveira 			while (isdigit(*p))
127272ced25SDaniel Bristot de Oliveira 				p++;
128272ced25SDaniel Bristot de Oliveira 		} else
129272ced25SDaniel Bristot de Oliveira 			end_cpu = cpu;
130272ced25SDaniel Bristot de Oliveira 
131272ced25SDaniel Bristot de Oliveira 		if (cpu == end_cpu) {
132272ced25SDaniel Bristot de Oliveira 			debug_msg("cpu_set: adding cpu %d\n", cpu);
133272ced25SDaniel Bristot de Oliveira 			CPU_SET(cpu, set);
134272ced25SDaniel Bristot de Oliveira 		} else {
135272ced25SDaniel Bristot de Oliveira 			for (i = cpu; i <= end_cpu; i++) {
136272ced25SDaniel Bristot de Oliveira 				debug_msg("cpu_set: adding cpu %d\n", i);
137272ced25SDaniel Bristot de Oliveira 				CPU_SET(i, set);
138272ced25SDaniel Bristot de Oliveira 			}
139272ced25SDaniel Bristot de Oliveira 		}
140272ced25SDaniel Bristot de Oliveira 
141272ced25SDaniel Bristot de Oliveira 		if (*p == ',')
142272ced25SDaniel Bristot de Oliveira 			p++;
143272ced25SDaniel Bristot de Oliveira 	}
144272ced25SDaniel Bristot de Oliveira 
145272ced25SDaniel Bristot de Oliveira 	return 0;
146272ced25SDaniel Bristot de Oliveira err:
147272ced25SDaniel Bristot de Oliveira 	debug_msg("Error parsing the cpu set %s\n", cpu_list);
148272ced25SDaniel Bristot de Oliveira 	return 1;
149272ced25SDaniel Bristot de Oliveira }
150272ced25SDaniel Bristot de Oliveira 
151272ced25SDaniel Bristot de Oliveira /*
152b1696371SDaniel Bristot de Oliveira  * parse_duration - parse duration with s/m/h/d suffix converting it to seconds
153b1696371SDaniel Bristot de Oliveira  */
parse_seconds_duration(char * val)154b1696371SDaniel Bristot de Oliveira long parse_seconds_duration(char *val)
155b1696371SDaniel Bristot de Oliveira {
156b1696371SDaniel Bristot de Oliveira 	char *end;
157b1696371SDaniel Bristot de Oliveira 	long t;
158b1696371SDaniel Bristot de Oliveira 
159b1696371SDaniel Bristot de Oliveira 	t = strtol(val, &end, 10);
160b1696371SDaniel Bristot de Oliveira 
161b1696371SDaniel Bristot de Oliveira 	if (end) {
162b1696371SDaniel Bristot de Oliveira 		switch (*end) {
163b1696371SDaniel Bristot de Oliveira 		case 's':
164b1696371SDaniel Bristot de Oliveira 		case 'S':
165b1696371SDaniel Bristot de Oliveira 			break;
166b1696371SDaniel Bristot de Oliveira 		case 'm':
167b1696371SDaniel Bristot de Oliveira 		case 'M':
168b1696371SDaniel Bristot de Oliveira 			t *= 60;
169b1696371SDaniel Bristot de Oliveira 			break;
170b1696371SDaniel Bristot de Oliveira 		case 'h':
171b1696371SDaniel Bristot de Oliveira 		case 'H':
172b1696371SDaniel Bristot de Oliveira 			t *= 60 * 60;
173b1696371SDaniel Bristot de Oliveira 			break;
174b1696371SDaniel Bristot de Oliveira 
175b1696371SDaniel Bristot de Oliveira 		case 'd':
176b1696371SDaniel Bristot de Oliveira 		case 'D':
177b1696371SDaniel Bristot de Oliveira 			t *= 24 * 60 * 60;
178b1696371SDaniel Bristot de Oliveira 			break;
179b1696371SDaniel Bristot de Oliveira 		}
180b1696371SDaniel Bristot de Oliveira 	}
181b1696371SDaniel Bristot de Oliveira 
182b1696371SDaniel Bristot de Oliveira 	return t;
183b1696371SDaniel Bristot de Oliveira }
184b1696371SDaniel Bristot de Oliveira 
185b1696371SDaniel Bristot de Oliveira /*
186b1696371SDaniel Bristot de Oliveira  * parse_ns_duration - parse duration with ns/us/ms/s converting it to nanoseconds
187b1696371SDaniel Bristot de Oliveira  */
parse_ns_duration(char * val)188b1696371SDaniel Bristot de Oliveira long parse_ns_duration(char *val)
189b1696371SDaniel Bristot de Oliveira {
190b1696371SDaniel Bristot de Oliveira 	char *end;
191b1696371SDaniel Bristot de Oliveira 	long t;
192b1696371SDaniel Bristot de Oliveira 
193b1696371SDaniel Bristot de Oliveira 	t = strtol(val, &end, 10);
194b1696371SDaniel Bristot de Oliveira 
195b1696371SDaniel Bristot de Oliveira 	if (end) {
196b1696371SDaniel Bristot de Oliveira 		if (!strncmp(end, "ns", 2)) {
197b1696371SDaniel Bristot de Oliveira 			return t;
198b1696371SDaniel Bristot de Oliveira 		} else if (!strncmp(end, "us", 2)) {
199b1696371SDaniel Bristot de Oliveira 			t *= 1000;
200b1696371SDaniel Bristot de Oliveira 			return t;
201b1696371SDaniel Bristot de Oliveira 		} else if (!strncmp(end, "ms", 2)) {
202b1696371SDaniel Bristot de Oliveira 			t *= 1000 * 1000;
203b1696371SDaniel Bristot de Oliveira 			return t;
204b1696371SDaniel Bristot de Oliveira 		} else if (!strncmp(end, "s", 1)) {
205b1696371SDaniel Bristot de Oliveira 			t *= 1000 * 1000 * 1000;
206b1696371SDaniel Bristot de Oliveira 			return t;
207b1696371SDaniel Bristot de Oliveira 		}
208b1696371SDaniel Bristot de Oliveira 		return -1;
209b1696371SDaniel Bristot de Oliveira 	}
210b1696371SDaniel Bristot de Oliveira 
211b1696371SDaniel Bristot de Oliveira 	return t;
212b1696371SDaniel Bristot de Oliveira }
213b1696371SDaniel Bristot de Oliveira 
214b1696371SDaniel Bristot de Oliveira /*
215b1696371SDaniel Bristot de Oliveira  * This is a set of helper functions to use SCHED_DEADLINE.
216b1696371SDaniel Bristot de Oliveira  */
217099a8401SJan Stancek #ifndef __NR_sched_setattr
218b1696371SDaniel Bristot de Oliveira # ifdef __x86_64__
219b1696371SDaniel Bristot de Oliveira #  define __NR_sched_setattr	314
220b1696371SDaniel Bristot de Oliveira # elif __i386__
221b1696371SDaniel Bristot de Oliveira #  define __NR_sched_setattr	351
222b1696371SDaniel Bristot de Oliveira # elif __arm__
223b1696371SDaniel Bristot de Oliveira #  define __NR_sched_setattr	380
224dd0b15bdSAndreas Schwab # elif __aarch64__ || __riscv
225b1696371SDaniel Bristot de Oliveira #  define __NR_sched_setattr	274
226b1696371SDaniel Bristot de Oliveira # elif __powerpc__
227b1696371SDaniel Bristot de Oliveira #  define __NR_sched_setattr	355
228b1696371SDaniel Bristot de Oliveira # elif __s390x__
229b1696371SDaniel Bristot de Oliveira #  define __NR_sched_setattr	345
230099a8401SJan Stancek # endif
231b1696371SDaniel Bristot de Oliveira #endif
232b1696371SDaniel Bristot de Oliveira 
233b1696371SDaniel Bristot de Oliveira #define SCHED_DEADLINE		6
234b1696371SDaniel Bristot de Oliveira 
syscall_sched_setattr(pid_t pid,const struct sched_attr * attr,unsigned int flags)2350eecee34SJan Stancek static inline int syscall_sched_setattr(pid_t pid, const struct sched_attr *attr,
236b1696371SDaniel Bristot de Oliveira 				unsigned int flags) {
237b1696371SDaniel Bristot de Oliveira 	return syscall(__NR_sched_setattr, pid, attr, flags);
238b1696371SDaniel Bristot de Oliveira }
239b1696371SDaniel Bristot de Oliveira 
__set_sched_attr(int pid,struct sched_attr * attr)240b1696371SDaniel Bristot de Oliveira int __set_sched_attr(int pid, struct sched_attr *attr)
241b1696371SDaniel Bristot de Oliveira {
242b1696371SDaniel Bristot de Oliveira 	int flags = 0;
243b1696371SDaniel Bristot de Oliveira 	int retval;
244b1696371SDaniel Bristot de Oliveira 
2450eecee34SJan Stancek 	retval = syscall_sched_setattr(pid, attr, flags);
246b1696371SDaniel Bristot de Oliveira 	if (retval < 0) {
247941a53c3SDaniel Bristot de Oliveira 		err_msg("Failed to set sched attributes to the pid %d: %s\n",
248b1696371SDaniel Bristot de Oliveira 			pid, strerror(errno));
249b1696371SDaniel Bristot de Oliveira 		return 1;
250b1696371SDaniel Bristot de Oliveira 	}
251b1696371SDaniel Bristot de Oliveira 
252b1696371SDaniel Bristot de Oliveira 	return 0;
253b1696371SDaniel Bristot de Oliveira }
254dada03dbSDaniel Bristot de Oliveira 
255b1696371SDaniel Bristot de Oliveira /*
256dada03dbSDaniel Bristot de Oliveira  * procfs_is_workload_pid - check if a procfs entry contains a comm_prefix* comm
257b1696371SDaniel Bristot de Oliveira  *
258dada03dbSDaniel Bristot de Oliveira  * Check if the procfs entry is a directory of a process, and then check if the
259dada03dbSDaniel Bristot de Oliveira  * process has a comm with the prefix set in char *comm_prefix. As the
260dada03dbSDaniel Bristot de Oliveira  * current users of this function only check for kernel threads, there is no
261dada03dbSDaniel Bristot de Oliveira  * need to check for the threads for the process.
262dada03dbSDaniel Bristot de Oliveira  *
263dada03dbSDaniel Bristot de Oliveira  * Return: True if the proc_entry contains a comm file with comm_prefix*.
264dada03dbSDaniel Bristot de Oliveira  * Otherwise returns false.
265dada03dbSDaniel Bristot de Oliveira  */
procfs_is_workload_pid(const char * comm_prefix,struct dirent * proc_entry)266dada03dbSDaniel Bristot de Oliveira static int procfs_is_workload_pid(const char *comm_prefix, struct dirent *proc_entry)
267dada03dbSDaniel Bristot de Oliveira {
268dada03dbSDaniel Bristot de Oliveira 	char buffer[MAX_PATH];
269dada03dbSDaniel Bristot de Oliveira 	int comm_fd, retval;
270dada03dbSDaniel Bristot de Oliveira 	char *t_name;
271dada03dbSDaniel Bristot de Oliveira 
272dada03dbSDaniel Bristot de Oliveira 	if (proc_entry->d_type != DT_DIR)
273dada03dbSDaniel Bristot de Oliveira 		return 0;
274dada03dbSDaniel Bristot de Oliveira 
275dada03dbSDaniel Bristot de Oliveira 	if (*proc_entry->d_name == '.')
276dada03dbSDaniel Bristot de Oliveira 		return 0;
277dada03dbSDaniel Bristot de Oliveira 
278dada03dbSDaniel Bristot de Oliveira 	/* check if the string is a pid */
279dada03dbSDaniel Bristot de Oliveira 	for (t_name = proc_entry->d_name; t_name; t_name++) {
280dada03dbSDaniel Bristot de Oliveira 		if (!isdigit(*t_name))
281dada03dbSDaniel Bristot de Oliveira 			break;
282dada03dbSDaniel Bristot de Oliveira 	}
283dada03dbSDaniel Bristot de Oliveira 
284dada03dbSDaniel Bristot de Oliveira 	if (*t_name != '\0')
285dada03dbSDaniel Bristot de Oliveira 		return 0;
286dada03dbSDaniel Bristot de Oliveira 
287dada03dbSDaniel Bristot de Oliveira 	snprintf(buffer, MAX_PATH, "/proc/%s/comm", proc_entry->d_name);
288dada03dbSDaniel Bristot de Oliveira 	comm_fd = open(buffer, O_RDONLY);
289dada03dbSDaniel Bristot de Oliveira 	if (comm_fd < 0)
290dada03dbSDaniel Bristot de Oliveira 		return 0;
291dada03dbSDaniel Bristot de Oliveira 
292dada03dbSDaniel Bristot de Oliveira 	memset(buffer, 0, MAX_PATH);
293dada03dbSDaniel Bristot de Oliveira 	retval = read(comm_fd, buffer, MAX_PATH);
294dada03dbSDaniel Bristot de Oliveira 
295dada03dbSDaniel Bristot de Oliveira 	close(comm_fd);
296dada03dbSDaniel Bristot de Oliveira 
297dada03dbSDaniel Bristot de Oliveira 	if (retval <= 0)
298dada03dbSDaniel Bristot de Oliveira 		return 0;
299dada03dbSDaniel Bristot de Oliveira 
300dada03dbSDaniel Bristot de Oliveira 	retval = strncmp(comm_prefix, buffer, strlen(comm_prefix));
301dada03dbSDaniel Bristot de Oliveira 	if (retval)
302dada03dbSDaniel Bristot de Oliveira 		return 0;
303dada03dbSDaniel Bristot de Oliveira 
304dada03dbSDaniel Bristot de Oliveira 	/* comm already have \n */
305dada03dbSDaniel Bristot de Oliveira 	debug_msg("Found workload pid:%s comm:%s", proc_entry->d_name, buffer);
306dada03dbSDaniel Bristot de Oliveira 
307dada03dbSDaniel Bristot de Oliveira 	return 1;
308dada03dbSDaniel Bristot de Oliveira }
309dada03dbSDaniel Bristot de Oliveira 
310dada03dbSDaniel Bristot de Oliveira /*
311dada03dbSDaniel Bristot de Oliveira  * set_comm_sched_attr - set sched params to threads starting with char *comm_prefix
312dada03dbSDaniel Bristot de Oliveira  *
313dada03dbSDaniel Bristot de Oliveira  * This function uses procfs to list the currently running threads and then set the
314dada03dbSDaniel Bristot de Oliveira  * sched_attr *attr to the threads that start with char *comm_prefix. It is
315b1696371SDaniel Bristot de Oliveira  * mainly used to set the priority to the kernel threads created by the
316b1696371SDaniel Bristot de Oliveira  * tracers.
317b1696371SDaniel Bristot de Oliveira  */
set_comm_sched_attr(const char * comm_prefix,struct sched_attr * attr)318dada03dbSDaniel Bristot de Oliveira int set_comm_sched_attr(const char *comm_prefix, struct sched_attr *attr)
319b1696371SDaniel Bristot de Oliveira {
320dada03dbSDaniel Bristot de Oliveira 	struct dirent *proc_entry;
321dada03dbSDaniel Bristot de Oliveira 	DIR *procfs;
322b1696371SDaniel Bristot de Oliveira 	int retval;
323b1696371SDaniel Bristot de Oliveira 
324dada03dbSDaniel Bristot de Oliveira 	if (strlen(comm_prefix) >= MAX_PATH) {
325dada03dbSDaniel Bristot de Oliveira 		err_msg("Command prefix is too long: %d < strlen(%s)\n",
326dada03dbSDaniel Bristot de Oliveira 			MAX_PATH, comm_prefix);
327dada03dbSDaniel Bristot de Oliveira 		return 1;
328b1696371SDaniel Bristot de Oliveira 	}
329b1696371SDaniel Bristot de Oliveira 
330dada03dbSDaniel Bristot de Oliveira 	procfs = opendir("/proc");
331dada03dbSDaniel Bristot de Oliveira 	if (!procfs) {
332dada03dbSDaniel Bristot de Oliveira 		err_msg("Could not open procfs\n");
333dada03dbSDaniel Bristot de Oliveira 		return 1;
334dada03dbSDaniel Bristot de Oliveira 	}
335b1696371SDaniel Bristot de Oliveira 
336dada03dbSDaniel Bristot de Oliveira 	while ((proc_entry = readdir(procfs))) {
337dada03dbSDaniel Bristot de Oliveira 
338dada03dbSDaniel Bristot de Oliveira 		retval = procfs_is_workload_pid(comm_prefix, proc_entry);
339dada03dbSDaniel Bristot de Oliveira 		if (!retval)
340b1696371SDaniel Bristot de Oliveira 			continue;
341dada03dbSDaniel Bristot de Oliveira 
342dada03dbSDaniel Bristot de Oliveira 		/* procfs_is_workload_pid confirmed it is a pid */
343dada03dbSDaniel Bristot de Oliveira 		retval = __set_sched_attr(atoi(proc_entry->d_name), attr);
344dada03dbSDaniel Bristot de Oliveira 		if (retval) {
345dada03dbSDaniel Bristot de Oliveira 			err_msg("Error setting sched attributes for pid:%s\n", proc_entry->d_name);
346b1696371SDaniel Bristot de Oliveira 			goto out_err;
347b1696371SDaniel Bristot de Oliveira 		}
348b1696371SDaniel Bristot de Oliveira 
349dada03dbSDaniel Bristot de Oliveira 		debug_msg("Set sched attributes for pid:%s\n", proc_entry->d_name);
350dada03dbSDaniel Bristot de Oliveira 	}
351b1696371SDaniel Bristot de Oliveira 	return 0;
352b1696371SDaniel Bristot de Oliveira 
353b1696371SDaniel Bristot de Oliveira out_err:
354dada03dbSDaniel Bristot de Oliveira 	closedir(procfs);
355b1696371SDaniel Bristot de Oliveira 	return 1;
356b1696371SDaniel Bristot de Oliveira }
357b1696371SDaniel Bristot de Oliveira 
358b1696371SDaniel Bristot de Oliveira #define INVALID_VAL	(~0L)
get_long_ns_after_colon(char * start)359b1696371SDaniel Bristot de Oliveira static long get_long_ns_after_colon(char *start)
360b1696371SDaniel Bristot de Oliveira {
361b1696371SDaniel Bristot de Oliveira 	long val = INVALID_VAL;
362b1696371SDaniel Bristot de Oliveira 
363b1696371SDaniel Bristot de Oliveira 	/* find the ":" */
364b1696371SDaniel Bristot de Oliveira 	start = strstr(start, ":");
365b1696371SDaniel Bristot de Oliveira 	if (!start)
366b1696371SDaniel Bristot de Oliveira 		return -1;
367b1696371SDaniel Bristot de Oliveira 
368b1696371SDaniel Bristot de Oliveira 	/* skip ":" */
369b1696371SDaniel Bristot de Oliveira 	start++;
370b1696371SDaniel Bristot de Oliveira 	val = parse_ns_duration(start);
371b1696371SDaniel Bristot de Oliveira 
372b1696371SDaniel Bristot de Oliveira 	return val;
373b1696371SDaniel Bristot de Oliveira }
374b1696371SDaniel Bristot de Oliveira 
get_long_after_colon(char * start)375b1696371SDaniel Bristot de Oliveira static long get_long_after_colon(char *start)
376b1696371SDaniel Bristot de Oliveira {
377b1696371SDaniel Bristot de Oliveira 	long val = INVALID_VAL;
378b1696371SDaniel Bristot de Oliveira 
379b1696371SDaniel Bristot de Oliveira 	/* find the ":" */
380b1696371SDaniel Bristot de Oliveira 	start = strstr(start, ":");
381b1696371SDaniel Bristot de Oliveira 	if (!start)
382b1696371SDaniel Bristot de Oliveira 		return -1;
383b1696371SDaniel Bristot de Oliveira 
384b1696371SDaniel Bristot de Oliveira 	/* skip ":" */
385b1696371SDaniel Bristot de Oliveira 	start++;
386b1696371SDaniel Bristot de Oliveira 	val = get_llong_from_str(start);
387b1696371SDaniel Bristot de Oliveira 
388b1696371SDaniel Bristot de Oliveira 	return val;
389b1696371SDaniel Bristot de Oliveira }
390b1696371SDaniel Bristot de Oliveira 
391b1696371SDaniel Bristot de Oliveira /*
392b1696371SDaniel Bristot de Oliveira  * parse priority in the format:
393b1696371SDaniel Bristot de Oliveira  * SCHED_OTHER:
394b1696371SDaniel Bristot de Oliveira  *		o:<prio>
395b1696371SDaniel Bristot de Oliveira  *		O:<prio>
396b1696371SDaniel Bristot de Oliveira  * SCHED_RR:
397b1696371SDaniel Bristot de Oliveira  *		r:<prio>
398b1696371SDaniel Bristot de Oliveira  *		R:<prio>
399b1696371SDaniel Bristot de Oliveira  * SCHED_FIFO:
400b1696371SDaniel Bristot de Oliveira  *		f:<prio>
401b1696371SDaniel Bristot de Oliveira  *		F:<prio>
402b1696371SDaniel Bristot de Oliveira  * SCHED_DEADLINE:
403b1696371SDaniel Bristot de Oliveira  *		d:runtime:period
404b1696371SDaniel Bristot de Oliveira  *		D:runtime:period
405b1696371SDaniel Bristot de Oliveira  */
parse_prio(char * arg,struct sched_attr * sched_param)406b1696371SDaniel Bristot de Oliveira int parse_prio(char *arg, struct sched_attr *sched_param)
407b1696371SDaniel Bristot de Oliveira {
408b1696371SDaniel Bristot de Oliveira 	long prio;
409b1696371SDaniel Bristot de Oliveira 	long runtime;
410b1696371SDaniel Bristot de Oliveira 	long period;
411b1696371SDaniel Bristot de Oliveira 
412b1696371SDaniel Bristot de Oliveira 	memset(sched_param, 0, sizeof(*sched_param));
413b1696371SDaniel Bristot de Oliveira 	sched_param->size = sizeof(*sched_param);
414b1696371SDaniel Bristot de Oliveira 
415b1696371SDaniel Bristot de Oliveira 	switch (arg[0]) {
416b1696371SDaniel Bristot de Oliveira 	case 'd':
417b1696371SDaniel Bristot de Oliveira 	case 'D':
418b1696371SDaniel Bristot de Oliveira 		/* d:runtime:period */
419b1696371SDaniel Bristot de Oliveira 		if (strlen(arg) < 4)
420b1696371SDaniel Bristot de Oliveira 			return -1;
421b1696371SDaniel Bristot de Oliveira 
422b1696371SDaniel Bristot de Oliveira 		runtime = get_long_ns_after_colon(arg);
423b1696371SDaniel Bristot de Oliveira 		if (runtime == INVALID_VAL)
424b1696371SDaniel Bristot de Oliveira 			return -1;
425b1696371SDaniel Bristot de Oliveira 
426b1696371SDaniel Bristot de Oliveira 		period = get_long_ns_after_colon(&arg[2]);
427b1696371SDaniel Bristot de Oliveira 		if (period == INVALID_VAL)
428b1696371SDaniel Bristot de Oliveira 			return -1;
429b1696371SDaniel Bristot de Oliveira 
430b1696371SDaniel Bristot de Oliveira 		if (runtime > period)
431b1696371SDaniel Bristot de Oliveira 			return -1;
432b1696371SDaniel Bristot de Oliveira 
433b1696371SDaniel Bristot de Oliveira 		sched_param->sched_policy   = SCHED_DEADLINE;
434b1696371SDaniel Bristot de Oliveira 		sched_param->sched_runtime  = runtime;
435b1696371SDaniel Bristot de Oliveira 		sched_param->sched_deadline = period;
436b1696371SDaniel Bristot de Oliveira 		sched_param->sched_period   = period;
437b1696371SDaniel Bristot de Oliveira 		break;
438b1696371SDaniel Bristot de Oliveira 	case 'f':
439b1696371SDaniel Bristot de Oliveira 	case 'F':
440b1696371SDaniel Bristot de Oliveira 		/* f:prio */
441b1696371SDaniel Bristot de Oliveira 		prio = get_long_after_colon(arg);
442b1696371SDaniel Bristot de Oliveira 		if (prio == INVALID_VAL)
443b1696371SDaniel Bristot de Oliveira 			return -1;
444b1696371SDaniel Bristot de Oliveira 
445b1696371SDaniel Bristot de Oliveira 		if (prio < sched_get_priority_min(SCHED_FIFO))
446b1696371SDaniel Bristot de Oliveira 			return -1;
447b1696371SDaniel Bristot de Oliveira 		if (prio > sched_get_priority_max(SCHED_FIFO))
448b1696371SDaniel Bristot de Oliveira 			return -1;
449b1696371SDaniel Bristot de Oliveira 
450b1696371SDaniel Bristot de Oliveira 		sched_param->sched_policy   = SCHED_FIFO;
451b1696371SDaniel Bristot de Oliveira 		sched_param->sched_priority = prio;
452b1696371SDaniel Bristot de Oliveira 		break;
453b1696371SDaniel Bristot de Oliveira 	case 'r':
454b1696371SDaniel Bristot de Oliveira 	case 'R':
455b1696371SDaniel Bristot de Oliveira 		/* r:prio */
456b1696371SDaniel Bristot de Oliveira 		prio = get_long_after_colon(arg);
457b1696371SDaniel Bristot de Oliveira 		if (prio == INVALID_VAL)
458b1696371SDaniel Bristot de Oliveira 			return -1;
459b1696371SDaniel Bristot de Oliveira 
460b1696371SDaniel Bristot de Oliveira 		if (prio < sched_get_priority_min(SCHED_RR))
461b1696371SDaniel Bristot de Oliveira 			return -1;
462b1696371SDaniel Bristot de Oliveira 		if (prio > sched_get_priority_max(SCHED_RR))
463b1696371SDaniel Bristot de Oliveira 			return -1;
464b1696371SDaniel Bristot de Oliveira 
465b1696371SDaniel Bristot de Oliveira 		sched_param->sched_policy   = SCHED_RR;
466b1696371SDaniel Bristot de Oliveira 		sched_param->sched_priority = prio;
467b1696371SDaniel Bristot de Oliveira 		break;
468b1696371SDaniel Bristot de Oliveira 	case 'o':
469b1696371SDaniel Bristot de Oliveira 	case 'O':
470b1696371SDaniel Bristot de Oliveira 		/* o:prio */
471b1696371SDaniel Bristot de Oliveira 		prio = get_long_after_colon(arg);
472b1696371SDaniel Bristot de Oliveira 		if (prio == INVALID_VAL)
473b1696371SDaniel Bristot de Oliveira 			return -1;
474b1696371SDaniel Bristot de Oliveira 
47514f08c97Slimingming3 		if (prio < MIN_NICE)
476b1696371SDaniel Bristot de Oliveira 			return -1;
47714f08c97Slimingming3 		if (prio > MAX_NICE)
478b1696371SDaniel Bristot de Oliveira 			return -1;
479b1696371SDaniel Bristot de Oliveira 
480b1696371SDaniel Bristot de Oliveira 		sched_param->sched_policy   = SCHED_OTHER;
48114f08c97Slimingming3 		sched_param->sched_nice = prio;
482b1696371SDaniel Bristot de Oliveira 		break;
483b1696371SDaniel Bristot de Oliveira 	default:
484b1696371SDaniel Bristot de Oliveira 		return -1;
485b1696371SDaniel Bristot de Oliveira 	}
486b1696371SDaniel Bristot de Oliveira 	return 0;
487b1696371SDaniel Bristot de Oliveira }
4887d0dc957SDaniel Bristot de Oliveira 
4897d0dc957SDaniel Bristot de Oliveira /*
4907d0dc957SDaniel Bristot de Oliveira  * set_cpu_dma_latency - set the /dev/cpu_dma_latecy
4917d0dc957SDaniel Bristot de Oliveira  *
4927d0dc957SDaniel Bristot de Oliveira  * This is used to reduce the exit from idle latency. The value
4937d0dc957SDaniel Bristot de Oliveira  * will be reset once the file descriptor of /dev/cpu_dma_latecy
4947d0dc957SDaniel Bristot de Oliveira  * is closed.
4957d0dc957SDaniel Bristot de Oliveira  *
4967d0dc957SDaniel Bristot de Oliveira  * Return: the /dev/cpu_dma_latecy file descriptor
4977d0dc957SDaniel Bristot de Oliveira  */
set_cpu_dma_latency(int32_t latency)4987d0dc957SDaniel Bristot de Oliveira int set_cpu_dma_latency(int32_t latency)
4997d0dc957SDaniel Bristot de Oliveira {
5007d0dc957SDaniel Bristot de Oliveira 	int retval;
5017d0dc957SDaniel Bristot de Oliveira 	int fd;
5027d0dc957SDaniel Bristot de Oliveira 
5037d0dc957SDaniel Bristot de Oliveira 	fd = open("/dev/cpu_dma_latency", O_RDWR);
5047d0dc957SDaniel Bristot de Oliveira 	if (fd < 0) {
5057d0dc957SDaniel Bristot de Oliveira 		err_msg("Error opening /dev/cpu_dma_latency\n");
5067d0dc957SDaniel Bristot de Oliveira 		return -1;
5077d0dc957SDaniel Bristot de Oliveira 	}
5087d0dc957SDaniel Bristot de Oliveira 
5097d0dc957SDaniel Bristot de Oliveira 	retval = write(fd, &latency, 4);
5107d0dc957SDaniel Bristot de Oliveira 	if (retval < 1) {
5117d0dc957SDaniel Bristot de Oliveira 		err_msg("Error setting /dev/cpu_dma_latency\n");
5127d0dc957SDaniel Bristot de Oliveira 		close(fd);
5137d0dc957SDaniel Bristot de Oliveira 		return -1;
5147d0dc957SDaniel Bristot de Oliveira 	}
5157d0dc957SDaniel Bristot de Oliveira 
5167d0dc957SDaniel Bristot de Oliveira 	debug_msg("Set /dev/cpu_dma_latency to %d\n", latency);
5177d0dc957SDaniel Bristot de Oliveira 
5187d0dc957SDaniel Bristot de Oliveira 	return fd;
5197d0dc957SDaniel Bristot de Oliveira }
520a957cbc0SDaniel Bristot de Oliveira 
521*083d29d3STomas Glozar #ifdef HAVE_LIBCPUPOWER_SUPPORT
522*083d29d3STomas Glozar static unsigned int **saved_cpu_idle_disable_state;
523*083d29d3STomas Glozar static size_t saved_cpu_idle_disable_state_alloc_ctr;
524*083d29d3STomas Glozar 
525*083d29d3STomas Glozar /*
526*083d29d3STomas Glozar  * save_cpu_idle_state_disable - save disable for all idle states of a cpu
527*083d29d3STomas Glozar  *
528*083d29d3STomas Glozar  * Saves the current disable of all idle states of a cpu, to be subsequently
529*083d29d3STomas Glozar  * restored via restore_cpu_idle_disable_state.
530*083d29d3STomas Glozar  *
531*083d29d3STomas Glozar  * Return: idle state count on success, negative on error
532*083d29d3STomas Glozar  */
save_cpu_idle_disable_state(unsigned int cpu)533*083d29d3STomas Glozar int save_cpu_idle_disable_state(unsigned int cpu)
534*083d29d3STomas Glozar {
535*083d29d3STomas Glozar 	unsigned int nr_states;
536*083d29d3STomas Glozar 	unsigned int state;
537*083d29d3STomas Glozar 	int disabled;
538*083d29d3STomas Glozar 	int nr_cpus;
539*083d29d3STomas Glozar 
540*083d29d3STomas Glozar 	nr_states = cpuidle_state_count(cpu);
541*083d29d3STomas Glozar 
542*083d29d3STomas Glozar 	if (nr_states == 0)
543*083d29d3STomas Glozar 		return 0;
544*083d29d3STomas Glozar 
545*083d29d3STomas Glozar 	if (saved_cpu_idle_disable_state == NULL) {
546*083d29d3STomas Glozar 		nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
547*083d29d3STomas Glozar 		saved_cpu_idle_disable_state = calloc(nr_cpus, sizeof(unsigned int *));
548*083d29d3STomas Glozar 		if (!saved_cpu_idle_disable_state)
549*083d29d3STomas Glozar 			return -1;
550*083d29d3STomas Glozar 	}
551*083d29d3STomas Glozar 
552*083d29d3STomas Glozar 	saved_cpu_idle_disable_state[cpu] = calloc(nr_states, sizeof(unsigned int));
553*083d29d3STomas Glozar 	if (!saved_cpu_idle_disable_state[cpu])
554*083d29d3STomas Glozar 		return -1;
555*083d29d3STomas Glozar 	saved_cpu_idle_disable_state_alloc_ctr++;
556*083d29d3STomas Glozar 
557*083d29d3STomas Glozar 	for (state = 0; state < nr_states; state++) {
558*083d29d3STomas Glozar 		disabled = cpuidle_is_state_disabled(cpu, state);
559*083d29d3STomas Glozar 		if (disabled < 0)
560*083d29d3STomas Glozar 			return disabled;
561*083d29d3STomas Glozar 		saved_cpu_idle_disable_state[cpu][state] = disabled;
562*083d29d3STomas Glozar 	}
563*083d29d3STomas Glozar 
564*083d29d3STomas Glozar 	return nr_states;
565*083d29d3STomas Glozar }
566*083d29d3STomas Glozar 
567*083d29d3STomas Glozar /*
568*083d29d3STomas Glozar  * restore_cpu_idle_disable_state - restore disable for all idle states of a cpu
569*083d29d3STomas Glozar  *
570*083d29d3STomas Glozar  * Restores the current disable state of all idle states of a cpu that was
571*083d29d3STomas Glozar  * previously saved by save_cpu_idle_disable_state.
572*083d29d3STomas Glozar  *
573*083d29d3STomas Glozar  * Return: idle state count on success, negative on error
574*083d29d3STomas Glozar  */
restore_cpu_idle_disable_state(unsigned int cpu)575*083d29d3STomas Glozar int restore_cpu_idle_disable_state(unsigned int cpu)
576*083d29d3STomas Glozar {
577*083d29d3STomas Glozar 	unsigned int nr_states;
578*083d29d3STomas Glozar 	unsigned int state;
579*083d29d3STomas Glozar 	int disabled;
580*083d29d3STomas Glozar 	int result;
581*083d29d3STomas Glozar 
582*083d29d3STomas Glozar 	nr_states = cpuidle_state_count(cpu);
583*083d29d3STomas Glozar 
584*083d29d3STomas Glozar 	if (nr_states == 0)
585*083d29d3STomas Glozar 		return 0;
586*083d29d3STomas Glozar 
587*083d29d3STomas Glozar 	if (!saved_cpu_idle_disable_state)
588*083d29d3STomas Glozar 		return -1;
589*083d29d3STomas Glozar 
590*083d29d3STomas Glozar 	for (state = 0; state < nr_states; state++) {
591*083d29d3STomas Glozar 		if (!saved_cpu_idle_disable_state[cpu])
592*083d29d3STomas Glozar 			return -1;
593*083d29d3STomas Glozar 		disabled = saved_cpu_idle_disable_state[cpu][state];
594*083d29d3STomas Glozar 		result = cpuidle_state_disable(cpu, state, disabled);
595*083d29d3STomas Glozar 		if (result < 0)
596*083d29d3STomas Glozar 			return result;
597*083d29d3STomas Glozar 	}
598*083d29d3STomas Glozar 
599*083d29d3STomas Glozar 	free(saved_cpu_idle_disable_state[cpu]);
600*083d29d3STomas Glozar 	saved_cpu_idle_disable_state[cpu] = NULL;
601*083d29d3STomas Glozar 	saved_cpu_idle_disable_state_alloc_ctr--;
602*083d29d3STomas Glozar 	if (saved_cpu_idle_disable_state_alloc_ctr == 0) {
603*083d29d3STomas Glozar 		free(saved_cpu_idle_disable_state);
604*083d29d3STomas Glozar 		saved_cpu_idle_disable_state = NULL;
605*083d29d3STomas Glozar 	}
606*083d29d3STomas Glozar 
607*083d29d3STomas Glozar 	return nr_states;
608*083d29d3STomas Glozar }
609*083d29d3STomas Glozar 
610*083d29d3STomas Glozar /*
611*083d29d3STomas Glozar  * free_cpu_idle_disable_states - free saved idle state disable for all cpus
612*083d29d3STomas Glozar  *
613*083d29d3STomas Glozar  * Frees the memory used for storing cpu idle state disable for all cpus
614*083d29d3STomas Glozar  * and states.
615*083d29d3STomas Glozar  *
616*083d29d3STomas Glozar  * Normally, the memory is freed automatically in
617*083d29d3STomas Glozar  * restore_cpu_idle_disable_state; this is mostly for cleaning up after an
618*083d29d3STomas Glozar  * error.
619*083d29d3STomas Glozar  */
free_cpu_idle_disable_states(void)620*083d29d3STomas Glozar void free_cpu_idle_disable_states(void)
621*083d29d3STomas Glozar {
622*083d29d3STomas Glozar 	int cpu;
623*083d29d3STomas Glozar 	int nr_cpus;
624*083d29d3STomas Glozar 
625*083d29d3STomas Glozar 	if (!saved_cpu_idle_disable_state)
626*083d29d3STomas Glozar 		return;
627*083d29d3STomas Glozar 
628*083d29d3STomas Glozar 	nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
629*083d29d3STomas Glozar 
630*083d29d3STomas Glozar 	for (cpu = 0; cpu < nr_cpus; cpu++) {
631*083d29d3STomas Glozar 		free(saved_cpu_idle_disable_state[cpu]);
632*083d29d3STomas Glozar 		saved_cpu_idle_disable_state[cpu] = NULL;
633*083d29d3STomas Glozar 	}
634*083d29d3STomas Glozar 
635*083d29d3STomas Glozar 	free(saved_cpu_idle_disable_state);
636*083d29d3STomas Glozar 	saved_cpu_idle_disable_state = NULL;
637*083d29d3STomas Glozar }
638*083d29d3STomas Glozar 
639*083d29d3STomas Glozar /*
640*083d29d3STomas Glozar  * set_deepest_cpu_idle_state - limit idle state of cpu
641*083d29d3STomas Glozar  *
642*083d29d3STomas Glozar  * Disables all idle states deeper than the one given in
643*083d29d3STomas Glozar  * deepest_state (assuming states with higher number are deeper).
644*083d29d3STomas Glozar  *
645*083d29d3STomas Glozar  * This is used to reduce the exit from idle latency. Unlike
646*083d29d3STomas Glozar  * set_cpu_dma_latency, it can disable idle states per cpu.
647*083d29d3STomas Glozar  *
648*083d29d3STomas Glozar  * Return: idle state count on success, negative on error
649*083d29d3STomas Glozar  */
set_deepest_cpu_idle_state(unsigned int cpu,unsigned int deepest_state)650*083d29d3STomas Glozar int set_deepest_cpu_idle_state(unsigned int cpu, unsigned int deepest_state)
651*083d29d3STomas Glozar {
652*083d29d3STomas Glozar 	unsigned int nr_states;
653*083d29d3STomas Glozar 	unsigned int state;
654*083d29d3STomas Glozar 	int result;
655*083d29d3STomas Glozar 
656*083d29d3STomas Glozar 	nr_states = cpuidle_state_count(cpu);
657*083d29d3STomas Glozar 
658*083d29d3STomas Glozar 	for (state = deepest_state + 1; state < nr_states; state++) {
659*083d29d3STomas Glozar 		result = cpuidle_state_disable(cpu, state, 1);
660*083d29d3STomas Glozar 		if (result < 0)
661*083d29d3STomas Glozar 			return result;
662*083d29d3STomas Glozar 	}
663*083d29d3STomas Glozar 
664*083d29d3STomas Glozar 	return nr_states;
665*083d29d3STomas Glozar }
666*083d29d3STomas Glozar #endif /* HAVE_LIBCPUPOWER_SUPPORT */
667*083d29d3STomas Glozar 
668a957cbc0SDaniel Bristot de Oliveira #define _STR(x) #x
669a957cbc0SDaniel Bristot de Oliveira #define STR(x) _STR(x)
670a957cbc0SDaniel Bristot de Oliveira 
671a957cbc0SDaniel Bristot de Oliveira /*
672a957cbc0SDaniel Bristot de Oliveira  * find_mount - find a the mount point of a given fs
673a957cbc0SDaniel Bristot de Oliveira  *
674a957cbc0SDaniel Bristot de Oliveira  * Returns 0 if mount is not found, otherwise return 1 and fill mp
675a957cbc0SDaniel Bristot de Oliveira  * with the mount point.
676a957cbc0SDaniel Bristot de Oliveira  */
find_mount(const char * fs,char * mp,int sizeof_mp)677a957cbc0SDaniel Bristot de Oliveira static const int find_mount(const char *fs, char *mp, int sizeof_mp)
678a957cbc0SDaniel Bristot de Oliveira {
67930369084SDaniel Bristot de Oliveira 	char mount_point[MAX_PATH+1];
680a957cbc0SDaniel Bristot de Oliveira 	char type[100];
681696444a5SColin Ian King 	int found = 0;
682a957cbc0SDaniel Bristot de Oliveira 	FILE *fp;
683a957cbc0SDaniel Bristot de Oliveira 
684a957cbc0SDaniel Bristot de Oliveira 	fp = fopen("/proc/mounts", "r");
685a957cbc0SDaniel Bristot de Oliveira 	if (!fp)
686a957cbc0SDaniel Bristot de Oliveira 		return 0;
687a957cbc0SDaniel Bristot de Oliveira 
688a957cbc0SDaniel Bristot de Oliveira 	while (fscanf(fp, "%*s %" STR(MAX_PATH) "s %99s %*s %*d %*d\n",	mount_point, type) == 2) {
689a957cbc0SDaniel Bristot de Oliveira 		if (strcmp(type, fs) == 0) {
690a957cbc0SDaniel Bristot de Oliveira 			found = 1;
691a957cbc0SDaniel Bristot de Oliveira 			break;
692a957cbc0SDaniel Bristot de Oliveira 		}
693a957cbc0SDaniel Bristot de Oliveira 	}
694a957cbc0SDaniel Bristot de Oliveira 	fclose(fp);
695a957cbc0SDaniel Bristot de Oliveira 
696a957cbc0SDaniel Bristot de Oliveira 	if (!found)
697a957cbc0SDaniel Bristot de Oliveira 		return 0;
698a957cbc0SDaniel Bristot de Oliveira 
699a957cbc0SDaniel Bristot de Oliveira 	memset(mp, 0, sizeof_mp);
700a957cbc0SDaniel Bristot de Oliveira 	strncpy(mp, mount_point, sizeof_mp - 1);
701a957cbc0SDaniel Bristot de Oliveira 
702a957cbc0SDaniel Bristot de Oliveira 	debug_msg("Fs %s found at %s\n", fs, mp);
703a957cbc0SDaniel Bristot de Oliveira 	return 1;
704a957cbc0SDaniel Bristot de Oliveira }
705a957cbc0SDaniel Bristot de Oliveira 
706a957cbc0SDaniel Bristot de Oliveira /*
707a957cbc0SDaniel Bristot de Oliveira  * get_self_cgroup - get the current thread cgroup path
708a957cbc0SDaniel Bristot de Oliveira  *
709a957cbc0SDaniel Bristot de Oliveira  * Parse /proc/$$/cgroup file to get the thread's cgroup. As an example of line to parse:
710a957cbc0SDaniel Bristot de Oliveira  *
711a957cbc0SDaniel Bristot de Oliveira  * 0::/user.slice/user-0.slice/session-3.scope'\n'
712a957cbc0SDaniel Bristot de Oliveira  *
713a957cbc0SDaniel Bristot de Oliveira  * This function is interested in the content after the second : and before the '\n'.
714a957cbc0SDaniel Bristot de Oliveira  *
715a957cbc0SDaniel Bristot de Oliveira  * Returns 1 if a string was found, 0 otherwise.
716a957cbc0SDaniel Bristot de Oliveira  */
get_self_cgroup(char * self_cg,int sizeof_self_cg)717a957cbc0SDaniel Bristot de Oliveira static int get_self_cgroup(char *self_cg, int sizeof_self_cg)
718a957cbc0SDaniel Bristot de Oliveira {
719a957cbc0SDaniel Bristot de Oliveira 	char path[MAX_PATH], *start;
720a957cbc0SDaniel Bristot de Oliveira 	int fd, retval;
721a957cbc0SDaniel Bristot de Oliveira 
722a957cbc0SDaniel Bristot de Oliveira 	snprintf(path, MAX_PATH, "/proc/%d/cgroup", getpid());
723a957cbc0SDaniel Bristot de Oliveira 
724a957cbc0SDaniel Bristot de Oliveira 	fd = open(path, O_RDONLY);
725a957cbc0SDaniel Bristot de Oliveira 	if (fd < 0)
726a957cbc0SDaniel Bristot de Oliveira 		return 0;
727a957cbc0SDaniel Bristot de Oliveira 
728a957cbc0SDaniel Bristot de Oliveira 	retval = read(fd, path, MAX_PATH);
729a957cbc0SDaniel Bristot de Oliveira 
730a957cbc0SDaniel Bristot de Oliveira 	close(fd);
731a957cbc0SDaniel Bristot de Oliveira 
732a957cbc0SDaniel Bristot de Oliveira 	if (retval <= 0)
733a957cbc0SDaniel Bristot de Oliveira 		return 0;
734a957cbc0SDaniel Bristot de Oliveira 
735a957cbc0SDaniel Bristot de Oliveira 	start = path;
736a957cbc0SDaniel Bristot de Oliveira 
737a957cbc0SDaniel Bristot de Oliveira 	start = strstr(start, ":");
738a957cbc0SDaniel Bristot de Oliveira 	if (!start)
739a957cbc0SDaniel Bristot de Oliveira 		return 0;
740a957cbc0SDaniel Bristot de Oliveira 
741a957cbc0SDaniel Bristot de Oliveira 	/* skip ":" */
742a957cbc0SDaniel Bristot de Oliveira 	start++;
743a957cbc0SDaniel Bristot de Oliveira 
744a957cbc0SDaniel Bristot de Oliveira 	start = strstr(start, ":");
745a957cbc0SDaniel Bristot de Oliveira 	if (!start)
746a957cbc0SDaniel Bristot de Oliveira 		return 0;
747a957cbc0SDaniel Bristot de Oliveira 
748a957cbc0SDaniel Bristot de Oliveira 	/* skip ":" */
749a957cbc0SDaniel Bristot de Oliveira 	start++;
750a957cbc0SDaniel Bristot de Oliveira 
751a957cbc0SDaniel Bristot de Oliveira 	if (strlen(start) >= sizeof_self_cg)
752a957cbc0SDaniel Bristot de Oliveira 		return 0;
753a957cbc0SDaniel Bristot de Oliveira 
754a957cbc0SDaniel Bristot de Oliveira 	snprintf(self_cg, sizeof_self_cg, "%s", start);
755a957cbc0SDaniel Bristot de Oliveira 
756a957cbc0SDaniel Bristot de Oliveira 	/* Swap '\n' with '\0' */
757a957cbc0SDaniel Bristot de Oliveira 	start = strstr(self_cg, "\n");
758a957cbc0SDaniel Bristot de Oliveira 
759a957cbc0SDaniel Bristot de Oliveira 	/* there must be '\n' */
760a957cbc0SDaniel Bristot de Oliveira 	if (!start)
761a957cbc0SDaniel Bristot de Oliveira 		return 0;
762a957cbc0SDaniel Bristot de Oliveira 
763a957cbc0SDaniel Bristot de Oliveira 	/* ok, it found a string after the second : and before the \n */
764a957cbc0SDaniel Bristot de Oliveira 	*start = '\0';
765a957cbc0SDaniel Bristot de Oliveira 
766a957cbc0SDaniel Bristot de Oliveira 	return 1;
767a957cbc0SDaniel Bristot de Oliveira }
768a957cbc0SDaniel Bristot de Oliveira 
769cdca4f4eSDaniel Bristot de Oliveira /*
770cdca4f4eSDaniel Bristot de Oliveira  * set_comm_cgroup - Set cgroup to pid_t pid
771cdca4f4eSDaniel Bristot de Oliveira  *
772cdca4f4eSDaniel Bristot de Oliveira  * If cgroup argument is not NULL, the threads will move to the given cgroup.
773cdca4f4eSDaniel Bristot de Oliveira  * Otherwise, the cgroup of the calling, i.e., rtla, thread will be used.
774cdca4f4eSDaniel Bristot de Oliveira  *
775cdca4f4eSDaniel Bristot de Oliveira  * Supports cgroup v2.
776cdca4f4eSDaniel Bristot de Oliveira  *
777cdca4f4eSDaniel Bristot de Oliveira  * Returns 1 on success, 0 otherwise.
778cdca4f4eSDaniel Bristot de Oliveira  */
set_pid_cgroup(pid_t pid,const char * cgroup)779cdca4f4eSDaniel Bristot de Oliveira int set_pid_cgroup(pid_t pid, const char *cgroup)
780cdca4f4eSDaniel Bristot de Oliveira {
781cdca4f4eSDaniel Bristot de Oliveira 	char cgroup_path[MAX_PATH - strlen("/cgroup.procs")];
782cdca4f4eSDaniel Bristot de Oliveira 	char cgroup_procs[MAX_PATH];
783cdca4f4eSDaniel Bristot de Oliveira 	char pid_str[24];
784cdca4f4eSDaniel Bristot de Oliveira 	int retval;
785cdca4f4eSDaniel Bristot de Oliveira 	int cg_fd;
786cdca4f4eSDaniel Bristot de Oliveira 
787cdca4f4eSDaniel Bristot de Oliveira 	retval = find_mount("cgroup2", cgroup_path, sizeof(cgroup_path));
788cdca4f4eSDaniel Bristot de Oliveira 	if (!retval) {
789cdca4f4eSDaniel Bristot de Oliveira 		err_msg("Did not find cgroupv2 mount point\n");
790cdca4f4eSDaniel Bristot de Oliveira 		return 0;
791cdca4f4eSDaniel Bristot de Oliveira 	}
792cdca4f4eSDaniel Bristot de Oliveira 
793cdca4f4eSDaniel Bristot de Oliveira 	if (!cgroup) {
794cdca4f4eSDaniel Bristot de Oliveira 		retval = get_self_cgroup(&cgroup_path[strlen(cgroup_path)],
795cdca4f4eSDaniel Bristot de Oliveira 				sizeof(cgroup_path) - strlen(cgroup_path));
796cdca4f4eSDaniel Bristot de Oliveira 		if (!retval) {
797cdca4f4eSDaniel Bristot de Oliveira 			err_msg("Did not find self cgroup\n");
798cdca4f4eSDaniel Bristot de Oliveira 			return 0;
799cdca4f4eSDaniel Bristot de Oliveira 		}
800cdca4f4eSDaniel Bristot de Oliveira 	} else {
801cdca4f4eSDaniel Bristot de Oliveira 		snprintf(&cgroup_path[strlen(cgroup_path)],
802cdca4f4eSDaniel Bristot de Oliveira 				sizeof(cgroup_path) - strlen(cgroup_path), "%s/", cgroup);
803cdca4f4eSDaniel Bristot de Oliveira 	}
804cdca4f4eSDaniel Bristot de Oliveira 
805cdca4f4eSDaniel Bristot de Oliveira 	snprintf(cgroup_procs, MAX_PATH, "%s/cgroup.procs", cgroup_path);
806cdca4f4eSDaniel Bristot de Oliveira 
807cdca4f4eSDaniel Bristot de Oliveira 	debug_msg("Using cgroup path at: %s\n", cgroup_procs);
808cdca4f4eSDaniel Bristot de Oliveira 
809cdca4f4eSDaniel Bristot de Oliveira 	cg_fd = open(cgroup_procs, O_RDWR);
810cdca4f4eSDaniel Bristot de Oliveira 	if (cg_fd < 0)
811cdca4f4eSDaniel Bristot de Oliveira 		return 0;
812cdca4f4eSDaniel Bristot de Oliveira 
813cdca4f4eSDaniel Bristot de Oliveira 	snprintf(pid_str, sizeof(pid_str), "%d\n", pid);
814cdca4f4eSDaniel Bristot de Oliveira 
815cdca4f4eSDaniel Bristot de Oliveira 	retval = write(cg_fd, pid_str, strlen(pid_str));
816cdca4f4eSDaniel Bristot de Oliveira 	if (retval < 0)
817cdca4f4eSDaniel Bristot de Oliveira 		err_msg("Error setting cgroup attributes for pid:%s - %s\n",
818cdca4f4eSDaniel Bristot de Oliveira 				pid_str, strerror(errno));
819cdca4f4eSDaniel Bristot de Oliveira 	else
820cdca4f4eSDaniel Bristot de Oliveira 		debug_msg("Set cgroup attributes for pid:%s\n", pid_str);
821cdca4f4eSDaniel Bristot de Oliveira 
822cdca4f4eSDaniel Bristot de Oliveira 	close(cg_fd);
823cdca4f4eSDaniel Bristot de Oliveira 
824cdca4f4eSDaniel Bristot de Oliveira 	return (retval >= 0);
825cdca4f4eSDaniel Bristot de Oliveira }
826cdca4f4eSDaniel Bristot de Oliveira 
827a957cbc0SDaniel Bristot de Oliveira /**
828a957cbc0SDaniel Bristot de Oliveira  * set_comm_cgroup - Set cgroup to threads starting with char *comm_prefix
829a957cbc0SDaniel Bristot de Oliveira  *
830a957cbc0SDaniel Bristot de Oliveira  * If cgroup argument is not NULL, the threads will move to the given cgroup.
831a957cbc0SDaniel Bristot de Oliveira  * Otherwise, the cgroup of the calling, i.e., rtla, thread will be used.
832a957cbc0SDaniel Bristot de Oliveira  *
833a957cbc0SDaniel Bristot de Oliveira  * Supports cgroup v2.
834a957cbc0SDaniel Bristot de Oliveira  *
835a957cbc0SDaniel Bristot de Oliveira  * Returns 1 on success, 0 otherwise.
836a957cbc0SDaniel Bristot de Oliveira  */
set_comm_cgroup(const char * comm_prefix,const char * cgroup)837a957cbc0SDaniel Bristot de Oliveira int set_comm_cgroup(const char *comm_prefix, const char *cgroup)
838a957cbc0SDaniel Bristot de Oliveira {
839a957cbc0SDaniel Bristot de Oliveira 	char cgroup_path[MAX_PATH - strlen("/cgroup.procs")];
840a957cbc0SDaniel Bristot de Oliveira 	char cgroup_procs[MAX_PATH];
841a957cbc0SDaniel Bristot de Oliveira 	struct dirent *proc_entry;
842a957cbc0SDaniel Bristot de Oliveira 	DIR *procfs;
843a957cbc0SDaniel Bristot de Oliveira 	int retval;
844a957cbc0SDaniel Bristot de Oliveira 	int cg_fd;
845a957cbc0SDaniel Bristot de Oliveira 
846a957cbc0SDaniel Bristot de Oliveira 	if (strlen(comm_prefix) >= MAX_PATH) {
847a957cbc0SDaniel Bristot de Oliveira 		err_msg("Command prefix is too long: %d < strlen(%s)\n",
848a957cbc0SDaniel Bristot de Oliveira 			MAX_PATH, comm_prefix);
849a957cbc0SDaniel Bristot de Oliveira 		return 0;
850a957cbc0SDaniel Bristot de Oliveira 	}
851a957cbc0SDaniel Bristot de Oliveira 
852a957cbc0SDaniel Bristot de Oliveira 	retval = find_mount("cgroup2", cgroup_path, sizeof(cgroup_path));
853a957cbc0SDaniel Bristot de Oliveira 	if (!retval) {
854a957cbc0SDaniel Bristot de Oliveira 		err_msg("Did not find cgroupv2 mount point\n");
855a957cbc0SDaniel Bristot de Oliveira 		return 0;
856a957cbc0SDaniel Bristot de Oliveira 	}
857a957cbc0SDaniel Bristot de Oliveira 
858a957cbc0SDaniel Bristot de Oliveira 	if (!cgroup) {
859a957cbc0SDaniel Bristot de Oliveira 		retval = get_self_cgroup(&cgroup_path[strlen(cgroup_path)],
860a957cbc0SDaniel Bristot de Oliveira 				sizeof(cgroup_path) - strlen(cgroup_path));
861a957cbc0SDaniel Bristot de Oliveira 		if (!retval) {
862a957cbc0SDaniel Bristot de Oliveira 			err_msg("Did not find self cgroup\n");
863a957cbc0SDaniel Bristot de Oliveira 			return 0;
864a957cbc0SDaniel Bristot de Oliveira 		}
865a957cbc0SDaniel Bristot de Oliveira 	} else {
866a957cbc0SDaniel Bristot de Oliveira 		snprintf(&cgroup_path[strlen(cgroup_path)],
867a957cbc0SDaniel Bristot de Oliveira 				sizeof(cgroup_path) - strlen(cgroup_path), "%s/", cgroup);
868a957cbc0SDaniel Bristot de Oliveira 	}
869a957cbc0SDaniel Bristot de Oliveira 
870a957cbc0SDaniel Bristot de Oliveira 	snprintf(cgroup_procs, MAX_PATH, "%s/cgroup.procs", cgroup_path);
871a957cbc0SDaniel Bristot de Oliveira 
872a957cbc0SDaniel Bristot de Oliveira 	debug_msg("Using cgroup path at: %s\n", cgroup_procs);
873a957cbc0SDaniel Bristot de Oliveira 
874a957cbc0SDaniel Bristot de Oliveira 	cg_fd = open(cgroup_procs, O_RDWR);
875a957cbc0SDaniel Bristot de Oliveira 	if (cg_fd < 0)
876a957cbc0SDaniel Bristot de Oliveira 		return 0;
877a957cbc0SDaniel Bristot de Oliveira 
878a957cbc0SDaniel Bristot de Oliveira 	procfs = opendir("/proc");
879a957cbc0SDaniel Bristot de Oliveira 	if (!procfs) {
880a957cbc0SDaniel Bristot de Oliveira 		err_msg("Could not open procfs\n");
881a957cbc0SDaniel Bristot de Oliveira 		goto out_cg;
882a957cbc0SDaniel Bristot de Oliveira 	}
883a957cbc0SDaniel Bristot de Oliveira 
884a957cbc0SDaniel Bristot de Oliveira 	while ((proc_entry = readdir(procfs))) {
885a957cbc0SDaniel Bristot de Oliveira 
886a957cbc0SDaniel Bristot de Oliveira 		retval = procfs_is_workload_pid(comm_prefix, proc_entry);
887a957cbc0SDaniel Bristot de Oliveira 		if (!retval)
888a957cbc0SDaniel Bristot de Oliveira 			continue;
889a957cbc0SDaniel Bristot de Oliveira 
890a957cbc0SDaniel Bristot de Oliveira 		retval = write(cg_fd, proc_entry->d_name, strlen(proc_entry->d_name));
891a957cbc0SDaniel Bristot de Oliveira 		if (retval < 0) {
892a957cbc0SDaniel Bristot de Oliveira 			err_msg("Error setting cgroup attributes for pid:%s - %s\n",
893a957cbc0SDaniel Bristot de Oliveira 				proc_entry->d_name, strerror(errno));
894a957cbc0SDaniel Bristot de Oliveira 			goto out_procfs;
895a957cbc0SDaniel Bristot de Oliveira 		}
896a957cbc0SDaniel Bristot de Oliveira 
897a957cbc0SDaniel Bristot de Oliveira 		debug_msg("Set cgroup attributes for pid:%s\n", proc_entry->d_name);
898a957cbc0SDaniel Bristot de Oliveira 	}
899a957cbc0SDaniel Bristot de Oliveira 
900a957cbc0SDaniel Bristot de Oliveira 	closedir(procfs);
901a957cbc0SDaniel Bristot de Oliveira 	close(cg_fd);
902a957cbc0SDaniel Bristot de Oliveira 	return 1;
903a957cbc0SDaniel Bristot de Oliveira 
904a957cbc0SDaniel Bristot de Oliveira out_procfs:
905a957cbc0SDaniel Bristot de Oliveira 	closedir(procfs);
906a957cbc0SDaniel Bristot de Oliveira out_cg:
907a957cbc0SDaniel Bristot de Oliveira 	close(cg_fd);
908a957cbc0SDaniel Bristot de Oliveira 	return 0;
909a957cbc0SDaniel Bristot de Oliveira }
910c58a3f8cSDaniel Bristot de Oliveira 
911c58a3f8cSDaniel Bristot de Oliveira /**
912c58a3f8cSDaniel Bristot de Oliveira  * auto_house_keeping - Automatically move rtla out of measurement threads
913c58a3f8cSDaniel Bristot de Oliveira  *
914c58a3f8cSDaniel Bristot de Oliveira  * Try to move rtla away from the tracer, if possible.
915c58a3f8cSDaniel Bristot de Oliveira  *
916c58a3f8cSDaniel Bristot de Oliveira  * Returns 1 on success, 0 otherwise.
917c58a3f8cSDaniel Bristot de Oliveira  */
auto_house_keeping(cpu_set_t * monitored_cpus)918c58a3f8cSDaniel Bristot de Oliveira int auto_house_keeping(cpu_set_t *monitored_cpus)
919c58a3f8cSDaniel Bristot de Oliveira {
920c58a3f8cSDaniel Bristot de Oliveira 	cpu_set_t rtla_cpus, house_keeping_cpus;
921c58a3f8cSDaniel Bristot de Oliveira 	int retval;
922c58a3f8cSDaniel Bristot de Oliveira 
923c58a3f8cSDaniel Bristot de Oliveira 	/* first get the CPUs in which rtla can actually run. */
924c58a3f8cSDaniel Bristot de Oliveira 	retval = sched_getaffinity(getpid(), sizeof(rtla_cpus), &rtla_cpus);
925c58a3f8cSDaniel Bristot de Oliveira 	if (retval == -1) {
926c58a3f8cSDaniel Bristot de Oliveira 		debug_msg("Could not get rtla affinity, rtla might run with the threads!\n");
927c58a3f8cSDaniel Bristot de Oliveira 		return 0;
928c58a3f8cSDaniel Bristot de Oliveira 	}
929c58a3f8cSDaniel Bristot de Oliveira 
930c58a3f8cSDaniel Bristot de Oliveira 	/* then check if the existing setup is already good. */
931c58a3f8cSDaniel Bristot de Oliveira 	CPU_AND(&house_keeping_cpus, &rtla_cpus, monitored_cpus);
932c58a3f8cSDaniel Bristot de Oliveira 	if (!CPU_COUNT(&house_keeping_cpus)) {
933c58a3f8cSDaniel Bristot de Oliveira 		debug_msg("rtla and the monitored CPUs do not share CPUs.");
934c58a3f8cSDaniel Bristot de Oliveira 		debug_msg("Skipping auto house-keeping\n");
935c58a3f8cSDaniel Bristot de Oliveira 		return 1;
936c58a3f8cSDaniel Bristot de Oliveira 	}
937c58a3f8cSDaniel Bristot de Oliveira 
938c58a3f8cSDaniel Bristot de Oliveira 	/* remove the intersection */
939c58a3f8cSDaniel Bristot de Oliveira 	CPU_XOR(&house_keeping_cpus, &rtla_cpus, monitored_cpus);
940c58a3f8cSDaniel Bristot de Oliveira 
941c58a3f8cSDaniel Bristot de Oliveira 	/* get only those that rtla can run */
942c58a3f8cSDaniel Bristot de Oliveira 	CPU_AND(&house_keeping_cpus, &house_keeping_cpus, &rtla_cpus);
943c58a3f8cSDaniel Bristot de Oliveira 
944c58a3f8cSDaniel Bristot de Oliveira 	/* is there any cpu left? */
945c58a3f8cSDaniel Bristot de Oliveira 	if (!CPU_COUNT(&house_keeping_cpus)) {
946c58a3f8cSDaniel Bristot de Oliveira 		debug_msg("Could not find any CPU for auto house-keeping\n");
947c58a3f8cSDaniel Bristot de Oliveira 		return 0;
948c58a3f8cSDaniel Bristot de Oliveira 	}
949c58a3f8cSDaniel Bristot de Oliveira 
950c58a3f8cSDaniel Bristot de Oliveira 	retval = sched_setaffinity(getpid(), sizeof(house_keeping_cpus), &house_keeping_cpus);
951c58a3f8cSDaniel Bristot de Oliveira 	if (retval == -1) {
952c58a3f8cSDaniel Bristot de Oliveira 		debug_msg("Could not set affinity for auto house-keeping\n");
953c58a3f8cSDaniel Bristot de Oliveira 		return 0;
954c58a3f8cSDaniel Bristot de Oliveira 	}
955c58a3f8cSDaniel Bristot de Oliveira 
956c58a3f8cSDaniel Bristot de Oliveira 	debug_msg("rtla automatically moved to an auto house-keeping cpu set\n");
957c58a3f8cSDaniel Bristot de Oliveira 
958c58a3f8cSDaniel Bristot de Oliveira 	return 1;
959c58a3f8cSDaniel Bristot de Oliveira }
960