162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org> 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#define _GNU_SOURCE 762306a36Sopenharmony_ci#include <dirent.h> 862306a36Sopenharmony_ci#include <stdarg.h> 962306a36Sopenharmony_ci#include <stdlib.h> 1062306a36Sopenharmony_ci#include <string.h> 1162306a36Sopenharmony_ci#include <unistd.h> 1262306a36Sopenharmony_ci#include <ctype.h> 1362306a36Sopenharmony_ci#include <errno.h> 1462306a36Sopenharmony_ci#include <fcntl.h> 1562306a36Sopenharmony_ci#include <sched.h> 1662306a36Sopenharmony_ci#include <stdio.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include "utils.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define MAX_MSG_LENGTH 1024 2162306a36Sopenharmony_ciint config_debug; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* 2462306a36Sopenharmony_ci * err_msg - print an error message to the stderr 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_civoid err_msg(const char *fmt, ...) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci char message[MAX_MSG_LENGTH]; 2962306a36Sopenharmony_ci va_list ap; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci va_start(ap, fmt); 3262306a36Sopenharmony_ci vsnprintf(message, sizeof(message), fmt, ap); 3362306a36Sopenharmony_ci va_end(ap); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci fprintf(stderr, "%s", message); 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/* 3962306a36Sopenharmony_ci * debug_msg - print a debug message to stderr if debug is set 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_civoid debug_msg(const char *fmt, ...) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci char message[MAX_MSG_LENGTH]; 4462306a36Sopenharmony_ci va_list ap; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci if (!config_debug) 4762306a36Sopenharmony_ci return; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci va_start(ap, fmt); 5062306a36Sopenharmony_ci vsnprintf(message, sizeof(message), fmt, ap); 5162306a36Sopenharmony_ci va_end(ap); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci fprintf(stderr, "%s", message); 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* 5762306a36Sopenharmony_ci * get_llong_from_str - get a long long int from a string 5862306a36Sopenharmony_ci */ 5962306a36Sopenharmony_cilong long get_llong_from_str(char *start) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci long long value; 6262306a36Sopenharmony_ci char *end; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci errno = 0; 6562306a36Sopenharmony_ci value = strtoll(start, &end, 10); 6662306a36Sopenharmony_ci if (errno || start == end) 6762306a36Sopenharmony_ci return -1; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci return value; 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci/* 7362306a36Sopenharmony_ci * get_duration - fill output with a human readable duration since start_time 7462306a36Sopenharmony_ci */ 7562306a36Sopenharmony_civoid get_duration(time_t start_time, char *output, int output_size) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci time_t now = time(NULL); 7862306a36Sopenharmony_ci struct tm *tm_info; 7962306a36Sopenharmony_ci time_t duration; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci duration = difftime(now, start_time); 8262306a36Sopenharmony_ci tm_info = gmtime(&duration); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci snprintf(output, output_size, "%3d %02d:%02d:%02d", 8562306a36Sopenharmony_ci tm_info->tm_yday, 8662306a36Sopenharmony_ci tm_info->tm_hour, 8762306a36Sopenharmony_ci tm_info->tm_min, 8862306a36Sopenharmony_ci tm_info->tm_sec); 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/* 9262306a36Sopenharmony_ci * parse_cpu_set - parse a cpu_list filling cpu_set_t argument 9362306a36Sopenharmony_ci * 9462306a36Sopenharmony_ci * Receives a cpu list, like 1-3,5 (cpus 1, 2, 3, 5), and then set 9562306a36Sopenharmony_ci * filling cpu_set_t argument. 9662306a36Sopenharmony_ci * 9762306a36Sopenharmony_ci * Returns 1 on success, 0 otherwise. 9862306a36Sopenharmony_ci */ 9962306a36Sopenharmony_ciint parse_cpu_set(char *cpu_list, cpu_set_t *set) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci const char *p; 10262306a36Sopenharmony_ci int end_cpu; 10362306a36Sopenharmony_ci int nr_cpus; 10462306a36Sopenharmony_ci int cpu; 10562306a36Sopenharmony_ci int i; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci CPU_ZERO(set); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci nr_cpus = sysconf(_SC_NPROCESSORS_CONF); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci for (p = cpu_list; *p; ) { 11262306a36Sopenharmony_ci cpu = atoi(p); 11362306a36Sopenharmony_ci if (cpu < 0 || (!cpu && *p != '0') || cpu >= nr_cpus) 11462306a36Sopenharmony_ci goto err; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci while (isdigit(*p)) 11762306a36Sopenharmony_ci p++; 11862306a36Sopenharmony_ci if (*p == '-') { 11962306a36Sopenharmony_ci p++; 12062306a36Sopenharmony_ci end_cpu = atoi(p); 12162306a36Sopenharmony_ci if (end_cpu < cpu || (!end_cpu && *p != '0') || end_cpu >= nr_cpus) 12262306a36Sopenharmony_ci goto err; 12362306a36Sopenharmony_ci while (isdigit(*p)) 12462306a36Sopenharmony_ci p++; 12562306a36Sopenharmony_ci } else 12662306a36Sopenharmony_ci end_cpu = cpu; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci if (cpu == end_cpu) { 12962306a36Sopenharmony_ci debug_msg("cpu_set: adding cpu %d\n", cpu); 13062306a36Sopenharmony_ci CPU_SET(cpu, set); 13162306a36Sopenharmony_ci } else { 13262306a36Sopenharmony_ci for (i = cpu; i <= end_cpu; i++) { 13362306a36Sopenharmony_ci debug_msg("cpu_set: adding cpu %d\n", i); 13462306a36Sopenharmony_ci CPU_SET(i, set); 13562306a36Sopenharmony_ci } 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci if (*p == ',') 13962306a36Sopenharmony_ci p++; 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci return 0; 14362306a36Sopenharmony_cierr: 14462306a36Sopenharmony_ci debug_msg("Error parsing the cpu set %s\n", cpu_list); 14562306a36Sopenharmony_ci return 1; 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci/* 14962306a36Sopenharmony_ci * parse_duration - parse duration with s/m/h/d suffix converting it to seconds 15062306a36Sopenharmony_ci */ 15162306a36Sopenharmony_cilong parse_seconds_duration(char *val) 15262306a36Sopenharmony_ci{ 15362306a36Sopenharmony_ci char *end; 15462306a36Sopenharmony_ci long t; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci t = strtol(val, &end, 10); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci if (end) { 15962306a36Sopenharmony_ci switch (*end) { 16062306a36Sopenharmony_ci case 's': 16162306a36Sopenharmony_ci case 'S': 16262306a36Sopenharmony_ci break; 16362306a36Sopenharmony_ci case 'm': 16462306a36Sopenharmony_ci case 'M': 16562306a36Sopenharmony_ci t *= 60; 16662306a36Sopenharmony_ci break; 16762306a36Sopenharmony_ci case 'h': 16862306a36Sopenharmony_ci case 'H': 16962306a36Sopenharmony_ci t *= 60 * 60; 17062306a36Sopenharmony_ci break; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci case 'd': 17362306a36Sopenharmony_ci case 'D': 17462306a36Sopenharmony_ci t *= 24 * 60 * 60; 17562306a36Sopenharmony_ci break; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci return t; 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci/* 18362306a36Sopenharmony_ci * parse_ns_duration - parse duration with ns/us/ms/s converting it to nanoseconds 18462306a36Sopenharmony_ci */ 18562306a36Sopenharmony_cilong parse_ns_duration(char *val) 18662306a36Sopenharmony_ci{ 18762306a36Sopenharmony_ci char *end; 18862306a36Sopenharmony_ci long t; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci t = strtol(val, &end, 10); 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci if (end) { 19362306a36Sopenharmony_ci if (!strncmp(end, "ns", 2)) { 19462306a36Sopenharmony_ci return t; 19562306a36Sopenharmony_ci } else if (!strncmp(end, "us", 2)) { 19662306a36Sopenharmony_ci t *= 1000; 19762306a36Sopenharmony_ci return t; 19862306a36Sopenharmony_ci } else if (!strncmp(end, "ms", 2)) { 19962306a36Sopenharmony_ci t *= 1000 * 1000; 20062306a36Sopenharmony_ci return t; 20162306a36Sopenharmony_ci } else if (!strncmp(end, "s", 1)) { 20262306a36Sopenharmony_ci t *= 1000 * 1000 * 1000; 20362306a36Sopenharmony_ci return t; 20462306a36Sopenharmony_ci } 20562306a36Sopenharmony_ci return -1; 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci return t; 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci/* 21262306a36Sopenharmony_ci * This is a set of helper functions to use SCHED_DEADLINE. 21362306a36Sopenharmony_ci */ 21462306a36Sopenharmony_ci#ifdef __x86_64__ 21562306a36Sopenharmony_ci# define __NR_sched_setattr 314 21662306a36Sopenharmony_ci# define __NR_sched_getattr 315 21762306a36Sopenharmony_ci#elif __i386__ 21862306a36Sopenharmony_ci# define __NR_sched_setattr 351 21962306a36Sopenharmony_ci# define __NR_sched_getattr 352 22062306a36Sopenharmony_ci#elif __arm__ 22162306a36Sopenharmony_ci# define __NR_sched_setattr 380 22262306a36Sopenharmony_ci# define __NR_sched_getattr 381 22362306a36Sopenharmony_ci#elif __aarch64__ || __riscv 22462306a36Sopenharmony_ci# define __NR_sched_setattr 274 22562306a36Sopenharmony_ci# define __NR_sched_getattr 275 22662306a36Sopenharmony_ci#elif __powerpc__ 22762306a36Sopenharmony_ci# define __NR_sched_setattr 355 22862306a36Sopenharmony_ci# define __NR_sched_getattr 356 22962306a36Sopenharmony_ci#elif __s390x__ 23062306a36Sopenharmony_ci# define __NR_sched_setattr 345 23162306a36Sopenharmony_ci# define __NR_sched_getattr 346 23262306a36Sopenharmony_ci#endif 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci#define SCHED_DEADLINE 6 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cistatic inline int sched_setattr(pid_t pid, const struct sched_attr *attr, 23762306a36Sopenharmony_ci unsigned int flags) { 23862306a36Sopenharmony_ci return syscall(__NR_sched_setattr, pid, attr, flags); 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ciint __set_sched_attr(int pid, struct sched_attr *attr) 24262306a36Sopenharmony_ci{ 24362306a36Sopenharmony_ci int flags = 0; 24462306a36Sopenharmony_ci int retval; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci retval = sched_setattr(pid, attr, flags); 24762306a36Sopenharmony_ci if (retval < 0) { 24862306a36Sopenharmony_ci err_msg("Failed to set sched attributes to the pid %d: %s\n", 24962306a36Sopenharmony_ci pid, strerror(errno)); 25062306a36Sopenharmony_ci return 1; 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci return 0; 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci/* 25762306a36Sopenharmony_ci * procfs_is_workload_pid - check if a procfs entry contains a comm_prefix* comm 25862306a36Sopenharmony_ci * 25962306a36Sopenharmony_ci * Check if the procfs entry is a directory of a process, and then check if the 26062306a36Sopenharmony_ci * process has a comm with the prefix set in char *comm_prefix. As the 26162306a36Sopenharmony_ci * current users of this function only check for kernel threads, there is no 26262306a36Sopenharmony_ci * need to check for the threads for the process. 26362306a36Sopenharmony_ci * 26462306a36Sopenharmony_ci * Return: True if the proc_entry contains a comm file with comm_prefix*. 26562306a36Sopenharmony_ci * Otherwise returns false. 26662306a36Sopenharmony_ci */ 26762306a36Sopenharmony_cistatic int procfs_is_workload_pid(const char *comm_prefix, struct dirent *proc_entry) 26862306a36Sopenharmony_ci{ 26962306a36Sopenharmony_ci char buffer[MAX_PATH]; 27062306a36Sopenharmony_ci int comm_fd, retval; 27162306a36Sopenharmony_ci char *t_name; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci if (proc_entry->d_type != DT_DIR) 27462306a36Sopenharmony_ci return 0; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci if (*proc_entry->d_name == '.') 27762306a36Sopenharmony_ci return 0; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci /* check if the string is a pid */ 28062306a36Sopenharmony_ci for (t_name = proc_entry->d_name; t_name; t_name++) { 28162306a36Sopenharmony_ci if (!isdigit(*t_name)) 28262306a36Sopenharmony_ci break; 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci if (*t_name != '\0') 28662306a36Sopenharmony_ci return 0; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci snprintf(buffer, MAX_PATH, "/proc/%s/comm", proc_entry->d_name); 28962306a36Sopenharmony_ci comm_fd = open(buffer, O_RDONLY); 29062306a36Sopenharmony_ci if (comm_fd < 0) 29162306a36Sopenharmony_ci return 0; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci memset(buffer, 0, MAX_PATH); 29462306a36Sopenharmony_ci retval = read(comm_fd, buffer, MAX_PATH); 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci close(comm_fd); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci if (retval <= 0) 29962306a36Sopenharmony_ci return 0; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci retval = strncmp(comm_prefix, buffer, strlen(comm_prefix)); 30262306a36Sopenharmony_ci if (retval) 30362306a36Sopenharmony_ci return 0; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci /* comm already have \n */ 30662306a36Sopenharmony_ci debug_msg("Found workload pid:%s comm:%s", proc_entry->d_name, buffer); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci return 1; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci/* 31262306a36Sopenharmony_ci * set_comm_sched_attr - set sched params to threads starting with char *comm_prefix 31362306a36Sopenharmony_ci * 31462306a36Sopenharmony_ci * This function uses procfs to list the currently running threads and then set the 31562306a36Sopenharmony_ci * sched_attr *attr to the threads that start with char *comm_prefix. It is 31662306a36Sopenharmony_ci * mainly used to set the priority to the kernel threads created by the 31762306a36Sopenharmony_ci * tracers. 31862306a36Sopenharmony_ci */ 31962306a36Sopenharmony_ciint set_comm_sched_attr(const char *comm_prefix, struct sched_attr *attr) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci struct dirent *proc_entry; 32262306a36Sopenharmony_ci DIR *procfs; 32362306a36Sopenharmony_ci int retval; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci if (strlen(comm_prefix) >= MAX_PATH) { 32662306a36Sopenharmony_ci err_msg("Command prefix is too long: %d < strlen(%s)\n", 32762306a36Sopenharmony_ci MAX_PATH, comm_prefix); 32862306a36Sopenharmony_ci return 1; 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci procfs = opendir("/proc"); 33262306a36Sopenharmony_ci if (!procfs) { 33362306a36Sopenharmony_ci err_msg("Could not open procfs\n"); 33462306a36Sopenharmony_ci return 1; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci while ((proc_entry = readdir(procfs))) { 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci retval = procfs_is_workload_pid(comm_prefix, proc_entry); 34062306a36Sopenharmony_ci if (!retval) 34162306a36Sopenharmony_ci continue; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci /* procfs_is_workload_pid confirmed it is a pid */ 34462306a36Sopenharmony_ci retval = __set_sched_attr(atoi(proc_entry->d_name), attr); 34562306a36Sopenharmony_ci if (retval) { 34662306a36Sopenharmony_ci err_msg("Error setting sched attributes for pid:%s\n", proc_entry->d_name); 34762306a36Sopenharmony_ci goto out_err; 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci debug_msg("Set sched attributes for pid:%s\n", proc_entry->d_name); 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci return 0; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ciout_err: 35562306a36Sopenharmony_ci closedir(procfs); 35662306a36Sopenharmony_ci return 1; 35762306a36Sopenharmony_ci} 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci#define INVALID_VAL (~0L) 36062306a36Sopenharmony_cistatic long get_long_ns_after_colon(char *start) 36162306a36Sopenharmony_ci{ 36262306a36Sopenharmony_ci long val = INVALID_VAL; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci /* find the ":" */ 36562306a36Sopenharmony_ci start = strstr(start, ":"); 36662306a36Sopenharmony_ci if (!start) 36762306a36Sopenharmony_ci return -1; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci /* skip ":" */ 37062306a36Sopenharmony_ci start++; 37162306a36Sopenharmony_ci val = parse_ns_duration(start); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci return val; 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cistatic long get_long_after_colon(char *start) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci long val = INVALID_VAL; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci /* find the ":" */ 38162306a36Sopenharmony_ci start = strstr(start, ":"); 38262306a36Sopenharmony_ci if (!start) 38362306a36Sopenharmony_ci return -1; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci /* skip ":" */ 38662306a36Sopenharmony_ci start++; 38762306a36Sopenharmony_ci val = get_llong_from_str(start); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci return val; 39062306a36Sopenharmony_ci} 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci/* 39362306a36Sopenharmony_ci * parse priority in the format: 39462306a36Sopenharmony_ci * SCHED_OTHER: 39562306a36Sopenharmony_ci * o:<prio> 39662306a36Sopenharmony_ci * O:<prio> 39762306a36Sopenharmony_ci * SCHED_RR: 39862306a36Sopenharmony_ci * r:<prio> 39962306a36Sopenharmony_ci * R:<prio> 40062306a36Sopenharmony_ci * SCHED_FIFO: 40162306a36Sopenharmony_ci * f:<prio> 40262306a36Sopenharmony_ci * F:<prio> 40362306a36Sopenharmony_ci * SCHED_DEADLINE: 40462306a36Sopenharmony_ci * d:runtime:period 40562306a36Sopenharmony_ci * D:runtime:period 40662306a36Sopenharmony_ci */ 40762306a36Sopenharmony_ciint parse_prio(char *arg, struct sched_attr *sched_param) 40862306a36Sopenharmony_ci{ 40962306a36Sopenharmony_ci long prio; 41062306a36Sopenharmony_ci long runtime; 41162306a36Sopenharmony_ci long period; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci memset(sched_param, 0, sizeof(*sched_param)); 41462306a36Sopenharmony_ci sched_param->size = sizeof(*sched_param); 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci switch (arg[0]) { 41762306a36Sopenharmony_ci case 'd': 41862306a36Sopenharmony_ci case 'D': 41962306a36Sopenharmony_ci /* d:runtime:period */ 42062306a36Sopenharmony_ci if (strlen(arg) < 4) 42162306a36Sopenharmony_ci return -1; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci runtime = get_long_ns_after_colon(arg); 42462306a36Sopenharmony_ci if (runtime == INVALID_VAL) 42562306a36Sopenharmony_ci return -1; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci period = get_long_ns_after_colon(&arg[2]); 42862306a36Sopenharmony_ci if (period == INVALID_VAL) 42962306a36Sopenharmony_ci return -1; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci if (runtime > period) 43262306a36Sopenharmony_ci return -1; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci sched_param->sched_policy = SCHED_DEADLINE; 43562306a36Sopenharmony_ci sched_param->sched_runtime = runtime; 43662306a36Sopenharmony_ci sched_param->sched_deadline = period; 43762306a36Sopenharmony_ci sched_param->sched_period = period; 43862306a36Sopenharmony_ci break; 43962306a36Sopenharmony_ci case 'f': 44062306a36Sopenharmony_ci case 'F': 44162306a36Sopenharmony_ci /* f:prio */ 44262306a36Sopenharmony_ci prio = get_long_after_colon(arg); 44362306a36Sopenharmony_ci if (prio == INVALID_VAL) 44462306a36Sopenharmony_ci return -1; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci if (prio < sched_get_priority_min(SCHED_FIFO)) 44762306a36Sopenharmony_ci return -1; 44862306a36Sopenharmony_ci if (prio > sched_get_priority_max(SCHED_FIFO)) 44962306a36Sopenharmony_ci return -1; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci sched_param->sched_policy = SCHED_FIFO; 45262306a36Sopenharmony_ci sched_param->sched_priority = prio; 45362306a36Sopenharmony_ci break; 45462306a36Sopenharmony_ci case 'r': 45562306a36Sopenharmony_ci case 'R': 45662306a36Sopenharmony_ci /* r:prio */ 45762306a36Sopenharmony_ci prio = get_long_after_colon(arg); 45862306a36Sopenharmony_ci if (prio == INVALID_VAL) 45962306a36Sopenharmony_ci return -1; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci if (prio < sched_get_priority_min(SCHED_RR)) 46262306a36Sopenharmony_ci return -1; 46362306a36Sopenharmony_ci if (prio > sched_get_priority_max(SCHED_RR)) 46462306a36Sopenharmony_ci return -1; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci sched_param->sched_policy = SCHED_RR; 46762306a36Sopenharmony_ci sched_param->sched_priority = prio; 46862306a36Sopenharmony_ci break; 46962306a36Sopenharmony_ci case 'o': 47062306a36Sopenharmony_ci case 'O': 47162306a36Sopenharmony_ci /* o:prio */ 47262306a36Sopenharmony_ci prio = get_long_after_colon(arg); 47362306a36Sopenharmony_ci if (prio == INVALID_VAL) 47462306a36Sopenharmony_ci return -1; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci if (prio < MIN_NICE) 47762306a36Sopenharmony_ci return -1; 47862306a36Sopenharmony_ci if (prio > MAX_NICE) 47962306a36Sopenharmony_ci return -1; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci sched_param->sched_policy = SCHED_OTHER; 48262306a36Sopenharmony_ci sched_param->sched_nice = prio; 48362306a36Sopenharmony_ci break; 48462306a36Sopenharmony_ci default: 48562306a36Sopenharmony_ci return -1; 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci return 0; 48862306a36Sopenharmony_ci} 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci/* 49162306a36Sopenharmony_ci * set_cpu_dma_latency - set the /dev/cpu_dma_latecy 49262306a36Sopenharmony_ci * 49362306a36Sopenharmony_ci * This is used to reduce the exit from idle latency. The value 49462306a36Sopenharmony_ci * will be reset once the file descriptor of /dev/cpu_dma_latecy 49562306a36Sopenharmony_ci * is closed. 49662306a36Sopenharmony_ci * 49762306a36Sopenharmony_ci * Return: the /dev/cpu_dma_latecy file descriptor 49862306a36Sopenharmony_ci */ 49962306a36Sopenharmony_ciint set_cpu_dma_latency(int32_t latency) 50062306a36Sopenharmony_ci{ 50162306a36Sopenharmony_ci int retval; 50262306a36Sopenharmony_ci int fd; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci fd = open("/dev/cpu_dma_latency", O_RDWR); 50562306a36Sopenharmony_ci if (fd < 0) { 50662306a36Sopenharmony_ci err_msg("Error opening /dev/cpu_dma_latency\n"); 50762306a36Sopenharmony_ci return -1; 50862306a36Sopenharmony_ci } 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci retval = write(fd, &latency, 4); 51162306a36Sopenharmony_ci if (retval < 1) { 51262306a36Sopenharmony_ci err_msg("Error setting /dev/cpu_dma_latency\n"); 51362306a36Sopenharmony_ci close(fd); 51462306a36Sopenharmony_ci return -1; 51562306a36Sopenharmony_ci } 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci debug_msg("Set /dev/cpu_dma_latency to %d\n", latency); 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci return fd; 52062306a36Sopenharmony_ci} 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci#define _STR(x) #x 52362306a36Sopenharmony_ci#define STR(x) _STR(x) 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci/* 52662306a36Sopenharmony_ci * find_mount - find a the mount point of a given fs 52762306a36Sopenharmony_ci * 52862306a36Sopenharmony_ci * Returns 0 if mount is not found, otherwise return 1 and fill mp 52962306a36Sopenharmony_ci * with the mount point. 53062306a36Sopenharmony_ci */ 53162306a36Sopenharmony_cistatic const int find_mount(const char *fs, char *mp, int sizeof_mp) 53262306a36Sopenharmony_ci{ 53362306a36Sopenharmony_ci char mount_point[MAX_PATH+1]; 53462306a36Sopenharmony_ci char type[100]; 53562306a36Sopenharmony_ci int found = 0; 53662306a36Sopenharmony_ci FILE *fp; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci fp = fopen("/proc/mounts", "r"); 53962306a36Sopenharmony_ci if (!fp) 54062306a36Sopenharmony_ci return 0; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci while (fscanf(fp, "%*s %" STR(MAX_PATH) "s %99s %*s %*d %*d\n", mount_point, type) == 2) { 54362306a36Sopenharmony_ci if (strcmp(type, fs) == 0) { 54462306a36Sopenharmony_ci found = 1; 54562306a36Sopenharmony_ci break; 54662306a36Sopenharmony_ci } 54762306a36Sopenharmony_ci } 54862306a36Sopenharmony_ci fclose(fp); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci if (!found) 55162306a36Sopenharmony_ci return 0; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci memset(mp, 0, sizeof_mp); 55462306a36Sopenharmony_ci strncpy(mp, mount_point, sizeof_mp - 1); 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci debug_msg("Fs %s found at %s\n", fs, mp); 55762306a36Sopenharmony_ci return 1; 55862306a36Sopenharmony_ci} 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci/* 56162306a36Sopenharmony_ci * get_self_cgroup - get the current thread cgroup path 56262306a36Sopenharmony_ci * 56362306a36Sopenharmony_ci * Parse /proc/$$/cgroup file to get the thread's cgroup. As an example of line to parse: 56462306a36Sopenharmony_ci * 56562306a36Sopenharmony_ci * 0::/user.slice/user-0.slice/session-3.scope'\n' 56662306a36Sopenharmony_ci * 56762306a36Sopenharmony_ci * This function is interested in the content after the second : and before the '\n'. 56862306a36Sopenharmony_ci * 56962306a36Sopenharmony_ci * Returns 1 if a string was found, 0 otherwise. 57062306a36Sopenharmony_ci */ 57162306a36Sopenharmony_cistatic int get_self_cgroup(char *self_cg, int sizeof_self_cg) 57262306a36Sopenharmony_ci{ 57362306a36Sopenharmony_ci char path[MAX_PATH], *start; 57462306a36Sopenharmony_ci int fd, retval; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci snprintf(path, MAX_PATH, "/proc/%d/cgroup", getpid()); 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci fd = open(path, O_RDONLY); 57962306a36Sopenharmony_ci if (fd < 0) 58062306a36Sopenharmony_ci return 0; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci retval = read(fd, path, MAX_PATH); 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci close(fd); 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci if (retval <= 0) 58762306a36Sopenharmony_ci return 0; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci start = path; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci start = strstr(start, ":"); 59262306a36Sopenharmony_ci if (!start) 59362306a36Sopenharmony_ci return 0; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci /* skip ":" */ 59662306a36Sopenharmony_ci start++; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci start = strstr(start, ":"); 59962306a36Sopenharmony_ci if (!start) 60062306a36Sopenharmony_ci return 0; 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci /* skip ":" */ 60362306a36Sopenharmony_ci start++; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci if (strlen(start) >= sizeof_self_cg) 60662306a36Sopenharmony_ci return 0; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci snprintf(self_cg, sizeof_self_cg, "%s", start); 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci /* Swap '\n' with '\0' */ 61162306a36Sopenharmony_ci start = strstr(self_cg, "\n"); 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci /* there must be '\n' */ 61462306a36Sopenharmony_ci if (!start) 61562306a36Sopenharmony_ci return 0; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci /* ok, it found a string after the second : and before the \n */ 61862306a36Sopenharmony_ci *start = '\0'; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci return 1; 62162306a36Sopenharmony_ci} 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci/* 62462306a36Sopenharmony_ci * set_comm_cgroup - Set cgroup to pid_t pid 62562306a36Sopenharmony_ci * 62662306a36Sopenharmony_ci * If cgroup argument is not NULL, the threads will move to the given cgroup. 62762306a36Sopenharmony_ci * Otherwise, the cgroup of the calling, i.e., rtla, thread will be used. 62862306a36Sopenharmony_ci * 62962306a36Sopenharmony_ci * Supports cgroup v2. 63062306a36Sopenharmony_ci * 63162306a36Sopenharmony_ci * Returns 1 on success, 0 otherwise. 63262306a36Sopenharmony_ci */ 63362306a36Sopenharmony_ciint set_pid_cgroup(pid_t pid, const char *cgroup) 63462306a36Sopenharmony_ci{ 63562306a36Sopenharmony_ci char cgroup_path[MAX_PATH - strlen("/cgroup.procs")]; 63662306a36Sopenharmony_ci char cgroup_procs[MAX_PATH]; 63762306a36Sopenharmony_ci char pid_str[24]; 63862306a36Sopenharmony_ci int retval; 63962306a36Sopenharmony_ci int cg_fd; 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci retval = find_mount("cgroup2", cgroup_path, sizeof(cgroup_path)); 64262306a36Sopenharmony_ci if (!retval) { 64362306a36Sopenharmony_ci err_msg("Did not find cgroupv2 mount point\n"); 64462306a36Sopenharmony_ci return 0; 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci if (!cgroup) { 64862306a36Sopenharmony_ci retval = get_self_cgroup(&cgroup_path[strlen(cgroup_path)], 64962306a36Sopenharmony_ci sizeof(cgroup_path) - strlen(cgroup_path)); 65062306a36Sopenharmony_ci if (!retval) { 65162306a36Sopenharmony_ci err_msg("Did not find self cgroup\n"); 65262306a36Sopenharmony_ci return 0; 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci } else { 65562306a36Sopenharmony_ci snprintf(&cgroup_path[strlen(cgroup_path)], 65662306a36Sopenharmony_ci sizeof(cgroup_path) - strlen(cgroup_path), "%s/", cgroup); 65762306a36Sopenharmony_ci } 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci snprintf(cgroup_procs, MAX_PATH, "%s/cgroup.procs", cgroup_path); 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci debug_msg("Using cgroup path at: %s\n", cgroup_procs); 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci cg_fd = open(cgroup_procs, O_RDWR); 66462306a36Sopenharmony_ci if (cg_fd < 0) 66562306a36Sopenharmony_ci return 0; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci snprintf(pid_str, sizeof(pid_str), "%d\n", pid); 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci retval = write(cg_fd, pid_str, strlen(pid_str)); 67062306a36Sopenharmony_ci if (retval < 0) 67162306a36Sopenharmony_ci err_msg("Error setting cgroup attributes for pid:%s - %s\n", 67262306a36Sopenharmony_ci pid_str, strerror(errno)); 67362306a36Sopenharmony_ci else 67462306a36Sopenharmony_ci debug_msg("Set cgroup attributes for pid:%s\n", pid_str); 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci close(cg_fd); 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci return (retval >= 0); 67962306a36Sopenharmony_ci} 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci/** 68262306a36Sopenharmony_ci * set_comm_cgroup - Set cgroup to threads starting with char *comm_prefix 68362306a36Sopenharmony_ci * 68462306a36Sopenharmony_ci * If cgroup argument is not NULL, the threads will move to the given cgroup. 68562306a36Sopenharmony_ci * Otherwise, the cgroup of the calling, i.e., rtla, thread will be used. 68662306a36Sopenharmony_ci * 68762306a36Sopenharmony_ci * Supports cgroup v2. 68862306a36Sopenharmony_ci * 68962306a36Sopenharmony_ci * Returns 1 on success, 0 otherwise. 69062306a36Sopenharmony_ci */ 69162306a36Sopenharmony_ciint set_comm_cgroup(const char *comm_prefix, const char *cgroup) 69262306a36Sopenharmony_ci{ 69362306a36Sopenharmony_ci char cgroup_path[MAX_PATH - strlen("/cgroup.procs")]; 69462306a36Sopenharmony_ci char cgroup_procs[MAX_PATH]; 69562306a36Sopenharmony_ci struct dirent *proc_entry; 69662306a36Sopenharmony_ci DIR *procfs; 69762306a36Sopenharmony_ci int retval; 69862306a36Sopenharmony_ci int cg_fd; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci if (strlen(comm_prefix) >= MAX_PATH) { 70162306a36Sopenharmony_ci err_msg("Command prefix is too long: %d < strlen(%s)\n", 70262306a36Sopenharmony_ci MAX_PATH, comm_prefix); 70362306a36Sopenharmony_ci return 0; 70462306a36Sopenharmony_ci } 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci retval = find_mount("cgroup2", cgroup_path, sizeof(cgroup_path)); 70762306a36Sopenharmony_ci if (!retval) { 70862306a36Sopenharmony_ci err_msg("Did not find cgroupv2 mount point\n"); 70962306a36Sopenharmony_ci return 0; 71062306a36Sopenharmony_ci } 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci if (!cgroup) { 71362306a36Sopenharmony_ci retval = get_self_cgroup(&cgroup_path[strlen(cgroup_path)], 71462306a36Sopenharmony_ci sizeof(cgroup_path) - strlen(cgroup_path)); 71562306a36Sopenharmony_ci if (!retval) { 71662306a36Sopenharmony_ci err_msg("Did not find self cgroup\n"); 71762306a36Sopenharmony_ci return 0; 71862306a36Sopenharmony_ci } 71962306a36Sopenharmony_ci } else { 72062306a36Sopenharmony_ci snprintf(&cgroup_path[strlen(cgroup_path)], 72162306a36Sopenharmony_ci sizeof(cgroup_path) - strlen(cgroup_path), "%s/", cgroup); 72262306a36Sopenharmony_ci } 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci snprintf(cgroup_procs, MAX_PATH, "%s/cgroup.procs", cgroup_path); 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci debug_msg("Using cgroup path at: %s\n", cgroup_procs); 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci cg_fd = open(cgroup_procs, O_RDWR); 72962306a36Sopenharmony_ci if (cg_fd < 0) 73062306a36Sopenharmony_ci return 0; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci procfs = opendir("/proc"); 73362306a36Sopenharmony_ci if (!procfs) { 73462306a36Sopenharmony_ci err_msg("Could not open procfs\n"); 73562306a36Sopenharmony_ci goto out_cg; 73662306a36Sopenharmony_ci } 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci while ((proc_entry = readdir(procfs))) { 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci retval = procfs_is_workload_pid(comm_prefix, proc_entry); 74162306a36Sopenharmony_ci if (!retval) 74262306a36Sopenharmony_ci continue; 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci retval = write(cg_fd, proc_entry->d_name, strlen(proc_entry->d_name)); 74562306a36Sopenharmony_ci if (retval < 0) { 74662306a36Sopenharmony_ci err_msg("Error setting cgroup attributes for pid:%s - %s\n", 74762306a36Sopenharmony_ci proc_entry->d_name, strerror(errno)); 74862306a36Sopenharmony_ci goto out_procfs; 74962306a36Sopenharmony_ci } 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci debug_msg("Set cgroup attributes for pid:%s\n", proc_entry->d_name); 75262306a36Sopenharmony_ci } 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci closedir(procfs); 75562306a36Sopenharmony_ci close(cg_fd); 75662306a36Sopenharmony_ci return 1; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ciout_procfs: 75962306a36Sopenharmony_ci closedir(procfs); 76062306a36Sopenharmony_ciout_cg: 76162306a36Sopenharmony_ci close(cg_fd); 76262306a36Sopenharmony_ci return 0; 76362306a36Sopenharmony_ci} 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci/** 76662306a36Sopenharmony_ci * auto_house_keeping - Automatically move rtla out of measurement threads 76762306a36Sopenharmony_ci * 76862306a36Sopenharmony_ci * Try to move rtla away from the tracer, if possible. 76962306a36Sopenharmony_ci * 77062306a36Sopenharmony_ci * Returns 1 on success, 0 otherwise. 77162306a36Sopenharmony_ci */ 77262306a36Sopenharmony_ciint auto_house_keeping(cpu_set_t *monitored_cpus) 77362306a36Sopenharmony_ci{ 77462306a36Sopenharmony_ci cpu_set_t rtla_cpus, house_keeping_cpus; 77562306a36Sopenharmony_ci int retval; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci /* first get the CPUs in which rtla can actually run. */ 77862306a36Sopenharmony_ci retval = sched_getaffinity(getpid(), sizeof(rtla_cpus), &rtla_cpus); 77962306a36Sopenharmony_ci if (retval == -1) { 78062306a36Sopenharmony_ci debug_msg("Could not get rtla affinity, rtla might run with the threads!\n"); 78162306a36Sopenharmony_ci return 0; 78262306a36Sopenharmony_ci } 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci /* then check if the existing setup is already good. */ 78562306a36Sopenharmony_ci CPU_AND(&house_keeping_cpus, &rtla_cpus, monitored_cpus); 78662306a36Sopenharmony_ci if (!CPU_COUNT(&house_keeping_cpus)) { 78762306a36Sopenharmony_ci debug_msg("rtla and the monitored CPUs do not share CPUs."); 78862306a36Sopenharmony_ci debug_msg("Skipping auto house-keeping\n"); 78962306a36Sopenharmony_ci return 1; 79062306a36Sopenharmony_ci } 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci /* remove the intersection */ 79362306a36Sopenharmony_ci CPU_XOR(&house_keeping_cpus, &rtla_cpus, monitored_cpus); 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci /* get only those that rtla can run */ 79662306a36Sopenharmony_ci CPU_AND(&house_keeping_cpus, &house_keeping_cpus, &rtla_cpus); 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci /* is there any cpu left? */ 79962306a36Sopenharmony_ci if (!CPU_COUNT(&house_keeping_cpus)) { 80062306a36Sopenharmony_ci debug_msg("Could not find any CPU for auto house-keeping\n"); 80162306a36Sopenharmony_ci return 0; 80262306a36Sopenharmony_ci } 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci retval = sched_setaffinity(getpid(), sizeof(house_keeping_cpus), &house_keeping_cpus); 80562306a36Sopenharmony_ci if (retval == -1) { 80662306a36Sopenharmony_ci debug_msg("Could not set affinity for auto house-keeping\n"); 80762306a36Sopenharmony_ci return 0; 80862306a36Sopenharmony_ci } 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci debug_msg("rtla automatically moved to an auto house-keeping cpu set\n"); 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci return 1; 81362306a36Sopenharmony_ci} 814