forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
213 lines
4.5 KiB
213 lines
4.5 KiB
// SPDX-License-Identifier: GPL-2.0-only |
|
/* |
|
* (C) 2004-2009 Dominik Brodowski <[email protected]> |
|
* (C) 2010 Thomas Renninger <[email protected]> |
|
*/ |
|
|
|
|
|
#include <unistd.h> |
|
#include <stdio.h> |
|
#include <errno.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <getopt.h> |
|
|
|
#include <cpuidle.h> |
|
|
|
#include "helpers/sysfs.h" |
|
#include "helpers/helpers.h" |
|
#include "helpers/bitmask.h" |
|
|
|
#define LINE_LEN 10 |
|
|
|
static void cpuidle_cpu_output(unsigned int cpu, int verbose) |
|
{ |
|
unsigned int idlestates, idlestate; |
|
char *tmp; |
|
|
|
idlestates = cpuidle_state_count(cpu); |
|
if (idlestates == 0) { |
|
printf(_("CPU %u: No idle states\n"), cpu); |
|
return; |
|
} |
|
|
|
printf(_("Number of idle states: %d\n"), idlestates); |
|
printf(_("Available idle states:")); |
|
for (idlestate = 0; idlestate < idlestates; idlestate++) { |
|
tmp = cpuidle_state_name(cpu, idlestate); |
|
if (!tmp) |
|
continue; |
|
printf(" %s", tmp); |
|
free(tmp); |
|
} |
|
printf("\n"); |
|
|
|
if (!verbose) |
|
return; |
|
|
|
for (idlestate = 0; idlestate < idlestates; idlestate++) { |
|
int disabled = cpuidle_is_state_disabled(cpu, idlestate); |
|
/* Disabled interface not supported on older kernels */ |
|
if (disabled < 0) |
|
disabled = 0; |
|
tmp = cpuidle_state_name(cpu, idlestate); |
|
if (!tmp) |
|
continue; |
|
printf("%s%s:\n", tmp, (disabled) ? " (DISABLED) " : ""); |
|
free(tmp); |
|
|
|
tmp = cpuidle_state_desc(cpu, idlestate); |
|
if (!tmp) |
|
continue; |
|
printf(_("Flags/Description: %s\n"), tmp); |
|
free(tmp); |
|
|
|
printf(_("Latency: %lu\n"), |
|
cpuidle_state_latency(cpu, idlestate)); |
|
printf(_("Usage: %lu\n"), |
|
cpuidle_state_usage(cpu, idlestate)); |
|
printf(_("Duration: %llu\n"), |
|
cpuidle_state_time(cpu, idlestate)); |
|
} |
|
} |
|
|
|
static void cpuidle_general_output(void) |
|
{ |
|
char *tmp; |
|
|
|
tmp = cpuidle_get_driver(); |
|
if (!tmp) { |
|
printf(_("Could not determine cpuidle driver\n")); |
|
return; |
|
} |
|
|
|
printf(_("CPUidle driver: %s\n"), tmp); |
|
free(tmp); |
|
|
|
tmp = cpuidle_get_governor(); |
|
if (!tmp) { |
|
printf(_("Could not determine cpuidle governor\n")); |
|
return; |
|
} |
|
|
|
printf(_("CPUidle governor: %s\n"), tmp); |
|
free(tmp); |
|
} |
|
|
|
static void proc_cpuidle_cpu_output(unsigned int cpu) |
|
{ |
|
long max_allowed_cstate = 2000000000; |
|
unsigned int cstate, cstates; |
|
|
|
cstates = cpuidle_state_count(cpu); |
|
if (cstates == 0) { |
|
printf(_("CPU %u: No C-states info\n"), cpu); |
|
return; |
|
} |
|
|
|
printf(_("active state: C0\n")); |
|
printf(_("max_cstate: C%u\n"), cstates-1); |
|
printf(_("maximum allowed latency: %lu usec\n"), max_allowed_cstate); |
|
printf(_("states:\t\n")); |
|
for (cstate = 1; cstate < cstates; cstate++) { |
|
printf(_(" C%d: " |
|
"type[C%d] "), cstate, cstate); |
|
printf(_("promotion[--] demotion[--] ")); |
|
printf(_("latency[%03lu] "), |
|
cpuidle_state_latency(cpu, cstate)); |
|
printf(_("usage[%08lu] "), |
|
cpuidle_state_usage(cpu, cstate)); |
|
printf(_("duration[%020Lu] \n"), |
|
cpuidle_state_time(cpu, cstate)); |
|
} |
|
} |
|
|
|
static struct option info_opts[] = { |
|
{"silent", no_argument, NULL, 's'}, |
|
{"proc", no_argument, NULL, 'o'}, |
|
{ }, |
|
}; |
|
|
|
static inline void cpuidle_exit(int fail) |
|
{ |
|
exit(EXIT_FAILURE); |
|
} |
|
|
|
int cmd_idle_info(int argc, char **argv) |
|
{ |
|
extern char *optarg; |
|
extern int optind, opterr, optopt; |
|
int ret = 0, cont = 1, output_param = 0, verbose = 1; |
|
unsigned int cpu = 0; |
|
|
|
do { |
|
ret = getopt_long(argc, argv, "os", info_opts, NULL); |
|
if (ret == -1) |
|
break; |
|
switch (ret) { |
|
case '?': |
|
output_param = '?'; |
|
cont = 0; |
|
break; |
|
case 's': |
|
verbose = 0; |
|
break; |
|
case -1: |
|
cont = 0; |
|
break; |
|
case 'o': |
|
if (output_param) { |
|
output_param = -1; |
|
cont = 0; |
|
break; |
|
} |
|
output_param = ret; |
|
break; |
|
} |
|
} while (cont); |
|
|
|
switch (output_param) { |
|
case -1: |
|
printf(_("You can't specify more than one " |
|
"output-specific argument\n")); |
|
cpuidle_exit(EXIT_FAILURE); |
|
case '?': |
|
printf(_("invalid or unknown argument\n")); |
|
cpuidle_exit(EXIT_FAILURE); |
|
} |
|
|
|
/* Default is: show output of CPU 0 only */ |
|
if (bitmask_isallclear(cpus_chosen)) |
|
bitmask_setbit(cpus_chosen, 0); |
|
|
|
if (output_param == 0) |
|
cpuidle_general_output(); |
|
|
|
for (cpu = bitmask_first(cpus_chosen); |
|
cpu <= bitmask_last(cpus_chosen); cpu++) { |
|
|
|
if (!bitmask_isbitset(cpus_chosen, cpu)) |
|
continue; |
|
|
|
printf(_("analyzing CPU %d:\n"), cpu); |
|
|
|
if (sysfs_is_cpu_online(cpu) != 1) { |
|
printf(_(" *is offline\n")); |
|
printf("\n"); |
|
continue; |
|
} |
|
|
|
switch (output_param) { |
|
|
|
case 'o': |
|
proc_cpuidle_cpu_output(cpu); |
|
break; |
|
case 0: |
|
printf("\n"); |
|
cpuidle_cpu_output(cpu, verbose); |
|
break; |
|
} |
|
printf("\n"); |
|
} |
|
return EXIT_SUCCESS; |
|
}
|
|
|