Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cpuidle-info.c
Go to the documentation of this file.
1 /*
2  * (C) 2004-2009 Dominik Brodowski <[email protected]>
3  * (C) 2010 Thomas Renninger <[email protected]>
4  *
5  * Licensed under the terms of the GNU GPL License version 2.
6  */
7 
8 
9 #include <unistd.h>
10 #include <stdio.h>
11 #include <errno.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <getopt.h>
15 #include <cpufreq.h>
16 
17 #include "helpers/helpers.h"
18 #include "helpers/sysfs.h"
19 #include "helpers/bitmask.h"
20 
21 #define LINE_LEN 10
22 
23 static void cpuidle_cpu_output(unsigned int cpu, int verbose)
24 {
25  int idlestates, idlestate;
26  char *tmp;
27 
28  printf(_ ("Analyzing CPU %d:\n"), cpu);
29 
30  idlestates = sysfs_get_idlestate_count(cpu);
31  if (idlestates == 0) {
32  printf(_("CPU %u: No idle states\n"), cpu);
33  return;
34  } else if (idlestates <= 0) {
35  printf(_("CPU %u: Can't read idle state info\n"), cpu);
36  return;
37  }
38  printf(_("Number of idle states: %d\n"), idlestates);
39  printf(_("Available idle states:"));
40  for (idlestate = 0; idlestate < idlestates; idlestate++) {
41  tmp = sysfs_get_idlestate_name(cpu, idlestate);
42  if (!tmp)
43  continue;
44  printf(" %s", tmp);
45  free(tmp);
46  }
47  printf("\n");
48 
49  if (!verbose)
50  return;
51 
52  for (idlestate = 0; idlestate < idlestates; idlestate++) {
53  tmp = sysfs_get_idlestate_name(cpu, idlestate);
54  if (!tmp)
55  continue;
56  printf("%s:\n", tmp);
57  free(tmp);
58 
59  tmp = sysfs_get_idlestate_desc(cpu, idlestate);
60  if (!tmp)
61  continue;
62  printf(_("Flags/Description: %s\n"), tmp);
63  free(tmp);
64 
65  printf(_("Latency: %lu\n"),
66  sysfs_get_idlestate_latency(cpu, idlestate));
67  printf(_("Usage: %lu\n"),
68  sysfs_get_idlestate_usage(cpu, idlestate));
69  printf(_("Duration: %llu\n"),
70  sysfs_get_idlestate_time(cpu, idlestate));
71  }
72  printf("\n");
73 }
74 
75 static void cpuidle_general_output(void)
76 {
77  char *tmp;
78 
80  if (!tmp) {
81  printf(_("Could not determine cpuidle driver\n"));
82  return;
83  }
84 
85  printf(_("CPUidle driver: %s\n"), tmp);
86  free(tmp);
87 
89  if (!tmp) {
90  printf(_("Could not determine cpuidle governor\n"));
91  return;
92  }
93 
94  printf(_("CPUidle governor: %s\n"), tmp);
95  free(tmp);
96 }
97 
98 static void proc_cpuidle_cpu_output(unsigned int cpu)
99 {
100  long max_allowed_cstate = 2000000000;
101  int cstates, cstate;
102 
103  cstates = sysfs_get_idlestate_count(cpu);
104  if (cstates == 0) {
105  /*
106  * Go on and print same useless info as you'd see with
107  * cat /proc/acpi/processor/../power
108  * printf(_("CPU %u: No C-states available\n"), cpu);
109  * return;
110  */
111  } else if (cstates <= 0) {
112  printf(_("CPU %u: Can't read C-state info\n"), cpu);
113  return;
114  }
115  /* printf("Cstates: %d\n", cstates); */
116 
117  printf(_("active state: C0\n"));
118  printf(_("max_cstate: C%u\n"), cstates-1);
119  printf(_("maximum allowed latency: %lu usec\n"), max_allowed_cstate);
120  printf(_("states:\t\n"));
121  for (cstate = 1; cstate < cstates; cstate++) {
122  printf(_(" C%d: "
123  "type[C%d] "), cstate, cstate);
124  printf(_("promotion[--] demotion[--] "));
125  printf(_("latency[%03lu] "),
126  sysfs_get_idlestate_latency(cpu, cstate));
127  printf(_("usage[%08lu] "),
128  sysfs_get_idlestate_usage(cpu, cstate));
129  printf(_("duration[%020Lu] \n"),
130  sysfs_get_idlestate_time(cpu, cstate));
131  }
132 }
133 
134 static struct option info_opts[] = {
135  { .name = "silent", .has_arg = no_argument, .flag = NULL, .val = 's'},
136  { .name = "proc", .has_arg = no_argument, .flag = NULL, .val = 'o'},
137  { },
138 };
139 
140 static inline void cpuidle_exit(int fail)
141 {
142  exit(EXIT_FAILURE);
143 }
144 
145 int cmd_idle_info(int argc, char **argv)
146 {
147  extern char *optarg;
148  extern int optind, opterr, optopt;
149  int ret = 0, cont = 1, output_param = 0, verbose = 1;
150  unsigned int cpu = 0;
151 
152  do {
153  ret = getopt_long(argc, argv, "os", info_opts, NULL);
154  if (ret == -1)
155  break;
156  switch (ret) {
157  case '?':
158  output_param = '?';
159  cont = 0;
160  break;
161  case 's':
162  verbose = 0;
163  break;
164  case -1:
165  cont = 0;
166  break;
167  case 'o':
168  if (output_param) {
169  output_param = -1;
170  cont = 0;
171  break;
172  }
173  output_param = ret;
174  break;
175  }
176  } while (cont);
177 
178  switch (output_param) {
179  case -1:
180  printf(_("You can't specify more than one "
181  "output-specific argument\n"));
182  cpuidle_exit(EXIT_FAILURE);
183  case '?':
184  printf(_("invalid or unknown argument\n"));
185  cpuidle_exit(EXIT_FAILURE);
186  }
187 
188  /* Default is: show output of CPU 0 only */
191 
192  if (output_param == 0)
193  cpuidle_general_output();
194 
195  for (cpu = bitmask_first(cpus_chosen);
196  cpu <= bitmask_last(cpus_chosen); cpu++) {
197 
198  if (!bitmask_isbitset(cpus_chosen, cpu) ||
199  cpufreq_cpu_exists(cpu))
200  continue;
201 
202  switch (output_param) {
203 
204  case 'o':
205  proc_cpuidle_cpu_output(cpu);
206  break;
207  case 0:
208  printf("\n");
209  cpuidle_cpu_output(cpu, verbose);
210  break;
211  }
212  }
213  return EXIT_SUCCESS;
214 }