summaryrefslogtreecommitdiff
path: root/tools/power/cpupower/utils/cpupower.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/power/cpupower/utils/cpupower.c')
-rw-r--r--tools/power/cpupower/utils/cpupower.c201
1 files changed, 201 insertions, 0 deletions
diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c
new file mode 100644
index 000000000000..b048e5595359
--- /dev/null
+++ b/tools/power/cpupower/utils/cpupower.c
@@ -0,0 +1,201 @@
+/*
+ * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
+ *
+ * Licensed under the terms of the GNU GPL License version 2.
+ *
+ * Ideas taken over from the perf userspace tool (included in the Linus
+ * kernel git repo): subcommand builtins and param parsing.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "builtin.h"
+#include "helpers/helpers.h"
+#include "helpers/bitmask.h"
+
+struct cmd_struct {
+ const char *cmd;
+ int (*main)(int, const char **);
+ void (*usage)(void);
+ int needs_root;
+};
+
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+
+int cmd_help(int argc, const char **argv);
+
+/* Global cpu_info object available for all binaries
+ * Info only retrieved from CPU 0
+ *
+ * Values will be zero/unknown on non X86 archs
+ */
+struct cpupower_cpu_info cpupower_cpu_info;
+int run_as_root;
+/* Affected cpus chosen by -c/--cpu param */
+struct bitmask *cpus_chosen;
+
+#ifdef DEBUG
+int be_verbose;
+#endif
+
+static void print_help(void);
+
+static struct cmd_struct commands[] = {
+ { "frequency-info", cmd_freq_info, freq_info_help, 0 },
+ { "frequency-set", cmd_freq_set, freq_set_help, 1 },
+ { "idle-info", cmd_idle_info, idle_info_help, 0 },
+ { "set", cmd_set, set_help, 1 },
+ { "info", cmd_info, info_help, 0 },
+ { "monitor", cmd_monitor, monitor_help, 0 },
+ { "help", cmd_help, print_help, 0 },
+ // { "bench", cmd_bench, NULL, 1 },
+};
+
+int cmd_help(int argc, const char **argv)
+{
+ unsigned int i;
+
+ if (argc > 1) {
+ for (i = 0; i < ARRAY_SIZE(commands); i++) {
+ struct cmd_struct *p = commands + i;
+ if (strcmp(p->cmd, argv[1]))
+ continue;
+ if (p->usage) {
+ p->usage();
+ return EXIT_SUCCESS;
+ }
+ }
+ }
+ print_help();
+ if (argc == 1)
+ return EXIT_SUCCESS; /* cpupower help */
+ return EXIT_FAILURE;
+}
+
+static void print_help(void)
+{
+ unsigned int i;
+
+#ifdef DEBUG
+ printf(_("cpupower [ -d ][ -c cpulist ] subcommand [ARGS]\n"));
+ printf(_(" -d, --debug May increase output (stderr) on some subcommands\n"));
+#else
+ printf(_("cpupower [ -c cpulist ] subcommand [ARGS]\n"));
+#endif
+ printf(_("cpupower --version\n"));
+ printf(_("Supported subcommands are:\n"));
+ for (i = 0; i < ARRAY_SIZE(commands); i++)
+ printf("\t%s\n", commands[i].cmd);
+ printf(_("\nSome subcommands can make use of the -c cpulist option.\n"));
+ printf(_("Look at the general cpupower manpage how to use it\n"));
+ printf(_("and read up the subcommand's manpage whether it is supported.\n"));
+ printf(_("\nUse cpupower help subcommand for getting help for above subcommands.\n"));
+}
+
+static void print_version(void) {
+ printf(PACKAGE " " VERSION "\n");
+ printf(_("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT);
+}
+
+static void handle_options(int *argc, const char ***argv)
+{
+ int ret, x, new_argc = 0;
+
+ if (*argc < 1)
+ return;
+
+ for (x = 0; x < *argc && ((*argv)[x])[0] == '-'; x++) {
+ const char *param = (*argv)[x];
+ if (!strcmp(param, "-h") || !strcmp(param, "--help")){
+ print_help();
+ exit(EXIT_SUCCESS);
+ } else if (!strcmp(param, "-c") || !strcmp(param, "--cpu")){
+ if (*argc < 2) {
+ print_help();
+ exit(EXIT_FAILURE);
+ }
+ if (!strcmp((*argv)[x+1], "all"))
+ bitmask_setall(cpus_chosen);
+ else {
+ ret = bitmask_parselist(
+ (*argv)[x+1], cpus_chosen);
+ if (ret < 0) {
+ fprintf(stderr, _("Error parsing cpu "
+ "list\n"));
+ exit(EXIT_FAILURE);
+ }
+ }
+ x += 1;
+ /* Cut out param: cpupower -c 1 info -> cpupower info */
+ new_argc += 2;
+ continue;
+ } else if (!strcmp(param, "-v") || !strcmp(param, "--version")){
+ print_version();
+ exit(EXIT_SUCCESS);
+#ifdef DEBUG
+ } else if (!strcmp(param, "-d") || !strcmp(param, "--debug")){
+ be_verbose = 1;
+ new_argc ++;
+ continue;
+#endif
+ } else {
+ fprintf(stderr, "Unknown option: %s\n", param);
+ print_help();
+ exit(EXIT_FAILURE);
+ }
+ }
+ *argc -= new_argc;
+ *argv += new_argc;
+}
+
+int main(int argc, const char *argv[])
+{
+ const char *cmd;
+ unsigned int i, ret;
+
+ cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF));
+
+ argc--;
+ argv += 1;
+
+ handle_options(&argc, &argv);
+
+ cmd = argv[0];
+
+ if (argc < 1) {
+ print_help();
+ return EXIT_FAILURE;
+ }
+
+ setlocale(LC_ALL, "");
+ textdomain (PACKAGE);
+
+ /* Turn "perf cmd --help" into "perf help cmd" */
+ if (argc > 1 && !strcmp(argv[1], "--help")) {
+ argv[1] = argv[0];
+ argv[0] = cmd = "help";
+ }
+
+ get_cpu_info(0, &cpupower_cpu_info);
+ run_as_root = !getuid();
+
+ for (i = 0; i < ARRAY_SIZE(commands); i++) {
+ struct cmd_struct *p = commands + i;
+ if (strcmp(p->cmd, cmd))
+ continue;
+ if (!run_as_root && p->needs_root) {
+ fprintf(stderr, _("Subcommand %s needs root "
+ "privileges\n"), cmd);
+ return EXIT_FAILURE;
+ }
+ ret = p->main(argc, argv);
+ if (cpus_chosen)
+ bitmask_free(cpus_chosen);
+ return ret;
+ }
+ print_help();
+ return EXIT_FAILURE;
+}