linux/tools/power/cpupower/utils/cpuidle-info.c
Thomas Renninger ac5a181d06 cpupower: Add cpuidle parts into library
This more or less is a renaming and moving of functions and should not
introduce any functional change.

cpupower was built from cpufrequtils (which had a C library providing easy
access to cpu frequency platform info). In the meantime it got enhanced
by quite some neat cpuidle userspace tools.

Now the cpu idle functions have been separated and added to the cpupower.so
library.
So beside an already existing public header file:
cpufreq.h
cpupower now also exports these cpu idle functions in:
cpuidle.h

Here again pasted for better review of the interfaces:

======================================
int cpuidle_is_state_disabled(unsigned int cpu,
                                       unsigned int idlestate);
int cpuidle_state_disable(unsigned int cpu, unsigned int idlestate,
                                   unsigned int disable);
unsigned long cpuidle_state_latency(unsigned int cpu,
                                                unsigned int idlestate);
unsigned long cpuidle_state_usage(unsigned int cpu,
                                        unsigned int idlestate);
unsigned long long cpuidle_state_time(unsigned int cpu,
                                                unsigned int idlestate);
char *cpuidle_state_name(unsigned int cpu,
                                unsigned int idlestate);
char *cpuidle_state_desc(unsigned int cpu,
                                unsigned int idlestate);
unsigned int cpuidle_state_count(unsigned int cpu);

char *cpuidle_get_governor(void);
char *cpuidle_get_driver(void);

======================================

Signed-off-by: Thomas Renninger <trenn@suse.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2016-04-28 16:02:29 +02:00

215 lines
4.5 KiB
C

/*
* (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
* (C) 2010 Thomas Renninger <trenn@suse.de>
*
* Licensed under the terms of the GNU GPL License version 2.
*/
#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;
}