Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cpuidle_sysfs.c
Go to the documentation of this file.
1 /*
2  * (C) 2010,2011 Thomas Renninger <[email protected]>, Novell Inc
3  *
4  * Licensed under the terms of the GNU GPL License version 2.
5  *
6  */
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdint.h>
11 #include <string.h>
12 #include <limits.h>
13 
14 #include "helpers/sysfs.h"
15 #include "helpers/helpers.h"
17 
18 #define CPUIDLE_STATES_MAX 10
19 static cstate_t cpuidle_cstates[CPUIDLE_STATES_MAX];
21 
22 static unsigned long long **previous_count;
23 static unsigned long long **current_count;
25 static unsigned long long timediff;
26 
27 static int cpuidle_get_count_percent(unsigned int id, double *percent,
28  unsigned int cpu)
29 {
30  unsigned long long statediff = current_count[cpu][id]
31  - previous_count[cpu][id];
32  dprint("%s: - diff: %llu - percent: %f (%u)\n",
33  cpuidle_cstates[id].name, timediff, *percent, cpu);
34 
35  if (timediff == 0)
36  *percent = 0.0;
37  else
38  *percent = ((100.0 * statediff) / timediff);
39 
40  dprint("%s: - timediff: %llu - statediff: %llu - percent: %f (%u)\n",
41  cpuidle_cstates[id].name, timediff, statediff, *percent, cpu);
42 
43  return 0;
44 }
45 
46 static int cpuidle_start(void)
47 {
48  int cpu, state;
50  for (cpu = 0; cpu < cpu_count; cpu++) {
51  for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
52  state++) {
53  previous_count[cpu][state] =
54  sysfs_get_idlestate_time(cpu, state);
55  dprint("CPU %d - State: %d - Val: %llu\n",
56  cpu, state, previous_count[cpu][state]);
57  }
58  };
59  return 0;
60 }
61 
62 static int cpuidle_stop(void)
63 {
64  int cpu, state;
65  struct timespec end_time;
66  clock_gettime(CLOCK_REALTIME, &end_time);
67  timediff = timespec_diff_us(start_time, end_time);
68 
69  for (cpu = 0; cpu < cpu_count; cpu++) {
70  for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
71  state++) {
72  current_count[cpu][state] =
73  sysfs_get_idlestate_time(cpu, state);
74  dprint("CPU %d - State: %d - Val: %llu\n",
75  cpu, state, previous_count[cpu][state]);
76  }
77  };
78  return 0;
79 }
80 
81 void fix_up_intel_idle_driver_name(char *tmp, int num)
82 {
83  /* fix up cpuidle name for intel idle driver */
84  if (!strncmp(tmp, "NHM-", 4)) {
85  switch (num) {
86  case 1:
87  strcpy(tmp, "C1");
88  break;
89  case 2:
90  strcpy(tmp, "C3");
91  break;
92  case 3:
93  strcpy(tmp, "C6");
94  break;
95  }
96  } else if (!strncmp(tmp, "SNB-", 4)) {
97  switch (num) {
98  case 1:
99  strcpy(tmp, "C1");
100  break;
101  case 2:
102  strcpy(tmp, "C3");
103  break;
104  case 3:
105  strcpy(tmp, "C6");
106  break;
107  case 4:
108  strcpy(tmp, "C7");
109  break;
110  }
111  } else if (!strncmp(tmp, "ATM-", 4)) {
112  switch (num) {
113  case 1:
114  strcpy(tmp, "C1");
115  break;
116  case 2:
117  strcpy(tmp, "C2");
118  break;
119  case 3:
120  strcpy(tmp, "C4");
121  break;
122  case 4:
123  strcpy(tmp, "C6");
124  break;
125  }
126  }
127 }
128 
129 static struct cpuidle_monitor *cpuidle_register(void)
130 {
131  int num;
132  char *tmp;
133 
134  /* Assume idle state count is the same for all CPUs */
136 
137  if (cpuidle_sysfs_monitor.hw_states_num <= 0)
138  return NULL;
139 
140  for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) {
141  tmp = sysfs_get_idlestate_name(0, num);
142  if (tmp == NULL)
143  continue;
144 
146  strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1);
147  free(tmp);
148 
149  tmp = sysfs_get_idlestate_desc(0, num);
150  if (tmp == NULL)
151  continue;
152  strncpy(cpuidle_cstates[num].desc, tmp, CSTATE_DESC_LEN - 1);
153  free(tmp);
154 
155  cpuidle_cstates[num].range = RANGE_THREAD;
156  cpuidle_cstates[num].id = num;
157  cpuidle_cstates[num].get_count_percent =
158  cpuidle_get_count_percent;
159  };
160 
161  /* Free this at program termination */
162  previous_count = malloc(sizeof(long long *) * cpu_count);
163  current_count = malloc(sizeof(long long *) * cpu_count);
164  for (num = 0; num < cpu_count; num++) {
165  previous_count[num] = malloc(sizeof(long long) *
166  cpuidle_sysfs_monitor.hw_states_num);
167  current_count[num] = malloc(sizeof(long long) *
168  cpuidle_sysfs_monitor.hw_states_num);
169  }
170 
172  return &cpuidle_sysfs_monitor;
173 }
174 
176 {
177  int num;
178 
179  for (num = 0; num < cpu_count; num++) {
180  free(previous_count[num]);
181  free(current_count[num]);
182  }
183  free(previous_count);
184  free(current_count);
185 }
186 
188  .name = "Idle_Stats",
189  .hw_states = cpuidle_cstates,
190  .start = cpuidle_start,
191  .stop = cpuidle_stop,
192  .do_register = cpuidle_register,
193  .unregister = cpuidle_unregister,
194  .needs_root = 0,
195  .overflow_s = UINT_MAX,
196 };