^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Ideas taken over from the perf userspace tool (included in the Linus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * kernel git repo): subcommand builtins and param parsing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <sys/utsname.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "builtin.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "helpers/helpers.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "helpers/bitmask.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static int cmd_help(int argc, const char **argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /* Global cpu_info object available for all binaries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * Info only retrieved from CPU 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * Values will be zero/unknown on non X86 archs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct cpupower_cpu_info cpupower_cpu_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) int run_as_root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) int base_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* Affected cpus chosen by -c/--cpu param */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct bitmask *cpus_chosen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) int be_verbose;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static void print_help(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct cmd_struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) const char *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int (*main)(int, const char **);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) int needs_root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static struct cmd_struct commands[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) { "frequency-info", cmd_freq_info, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) { "frequency-set", cmd_freq_set, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) { "idle-info", cmd_idle_info, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) { "idle-set", cmd_idle_set, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) { "set", cmd_set, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { "info", cmd_info, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { "monitor", cmd_monitor, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) { "help", cmd_help, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* { "bench", cmd_bench, 1 }, */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static void print_help(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) printf(_("Usage:\tcpupower [-d|--debug] [-c|--cpu cpulist ] <command> [<args>]\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) printf(_("Usage:\tcpupower [-c|--cpu cpulist ] <command> [<args>]\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) printf(_("Supported commands are:\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) for (i = 0; i < ARRAY_SIZE(commands); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) printf("\t%s\n", commands[i].cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) printf(_("\nNot all commands can make use of the -c cpulist option.\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) printf(_("\nUse 'cpupower help <command>' for getting help for above commands.\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static int print_man_page(const char *subpage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) char *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) len = 10; /* enough for "cpupower-" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (subpage != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) len += strlen(subpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) page = malloc(len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) sprintf(page, "cpupower");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if ((subpage != NULL) && strcmp(subpage, "help")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) strcat(page, "-");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) strcat(page, subpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) execlp("man", "man", page, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* should not be reached */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static int cmd_help(int argc, const char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (argc > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) print_man_page(argv[1]); /* exits within execlp() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return EXIT_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) print_help();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return EXIT_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static void print_version(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) printf(PACKAGE " " VERSION "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) printf(_("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static void handle_options(int *argc, const char ***argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int ret, x, new_argc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (*argc < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) for (x = 0; x < *argc && ((*argv)[x])[0] == '-'; x++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) const char *param = (*argv)[x];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (!strcmp(param, "-h") || !strcmp(param, "--help")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) print_help();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) exit(EXIT_SUCCESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) } else if (!strcmp(param, "-c") || !strcmp(param, "--cpu")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (*argc < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) print_help();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (!strcmp((*argv)[x+1], "all"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) bitmask_setall(cpus_chosen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ret = bitmask_parselist(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) (*argv)[x+1], cpus_chosen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) fprintf(stderr, _("Error parsing cpu "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) "list\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) x += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /* Cut out param: cpupower -c 1 info -> cpupower info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) new_argc += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) } else if (!strcmp(param, "-v") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) !strcmp(param, "--version")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) print_version();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) exit(EXIT_SUCCESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) } else if (!strcmp(param, "-d") || !strcmp(param, "--debug")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) be_verbose = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) new_argc++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) fprintf(stderr, "Unknown option: %s\n", param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) print_help();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) *argc -= new_argc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) *argv += new_argc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int main(int argc, const char *argv[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) const char *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) unsigned int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct stat statbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct utsname uts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) char pathname[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) argc--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) argv += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) handle_options(&argc, &argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) cmd = argv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (argc < 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) print_help();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return EXIT_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) setlocale(LC_ALL, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) textdomain(PACKAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /* Turn "perf cmd --help" into "perf help cmd" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (argc > 1 && !strcmp(argv[1], "--help")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) argv[1] = argv[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) argv[0] = cmd = "help";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) base_cpu = sched_getcpu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (base_cpu < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) fprintf(stderr, _("No valid cpus found.\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return EXIT_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) get_cpu_info(&cpupower_cpu_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) run_as_root = !geteuid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (run_as_root) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ret = uname(&uts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (!ret && !strcmp(uts.machine, "x86_64") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) stat(pathname, &statbuf) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (system("modprobe msr") == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) fprintf(stderr, _("MSR access not available.\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) for (i = 0; i < ARRAY_SIZE(commands); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct cmd_struct *p = commands + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (strcmp(p->cmd, cmd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (!run_as_root && p->needs_root) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) fprintf(stderr, _("Subcommand %s needs root "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) "privileges\n"), cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return EXIT_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ret = p->main(argc, argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (cpus_chosen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) bitmask_free(cpus_chosen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) print_help();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return EXIT_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }