~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  *  (C) 2010,2011       Thomas Renninger <trenn@suse.de>, Novell Inc
  4  */
  5 
  6 #include <stdio.h>
  7 #include <stdlib.h>
  8 #include <stdint.h>
  9 #include <string.h>
 10 #include <limits.h>
 11 #include <cpuidle.h>
 12 
 13 #include "helpers/helpers.h"
 14 #include "idle_monitor/cpupower-monitor.h"
 15 
 16 #define CPUIDLE_STATES_MAX 10
 17 static cstate_t cpuidle_cstates[CPUIDLE_STATES_MAX];
 18 struct cpuidle_monitor cpuidle_sysfs_monitor;
 19 
 20 static unsigned long long **previous_count;
 21 static unsigned long long **current_count;
 22 static struct timespec start_time;
 23 static unsigned long long timediff;
 24 
 25 static int cpuidle_get_count_percent(unsigned int id, double *percent,
 26                                      unsigned int cpu)
 27 {
 28         unsigned long long statediff = current_count[cpu][id]
 29                 - previous_count[cpu][id];
 30         dprint("%s: - diff: %llu - percent: %f (%u)\n",
 31                cpuidle_cstates[id].name, timediff, *percent, cpu);
 32 
 33         if (timediff == 0)
 34                 *percent = 0.0;
 35         else
 36                 *percent = ((100.0 * statediff) / timediff);
 37 
 38         dprint("%s: - timediff: %llu - statediff: %llu - percent: %f (%u)\n",
 39                cpuidle_cstates[id].name, timediff, statediff, *percent, cpu);
 40 
 41         return 0;
 42 }
 43 
 44 static int cpuidle_start(void)
 45 {
 46         int cpu, state;
 47         clock_gettime(CLOCK_REALTIME, &start_time);
 48         for (cpu = 0; cpu < cpu_count; cpu++) {
 49                 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
 50                      state++) {
 51                         previous_count[cpu][state] =
 52                                 cpuidle_state_time(cpu, state);
 53                         dprint("CPU %d - State: %d - Val: %llu\n",
 54                                cpu, state, previous_count[cpu][state]);
 55                 }
 56         }
 57         return 0;
 58 }
 59 
 60 static int cpuidle_stop(void)
 61 {
 62         int cpu, state;
 63         struct timespec end_time;
 64         clock_gettime(CLOCK_REALTIME, &end_time);
 65         timediff = timespec_diff_us(start_time, end_time);
 66 
 67         for (cpu = 0; cpu < cpu_count; cpu++) {
 68                 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
 69                      state++) {
 70                         current_count[cpu][state] =
 71                                 cpuidle_state_time(cpu, state);
 72                         dprint("CPU %d - State: %d - Val: %llu\n",
 73                                cpu, state, previous_count[cpu][state]);
 74                 }
 75         }
 76         return 0;
 77 }
 78 
 79 void fix_up_intel_idle_driver_name(char *tmp, int num)
 80 {
 81         /* fix up cpuidle name for intel idle driver */
 82         if (!strncmp(tmp, "NHM-", 4)) {
 83                 switch (num) {
 84                 case 1:
 85                         strcpy(tmp, "C1");
 86                         break;
 87                 case 2:
 88                         strcpy(tmp, "C3");
 89                         break;
 90                 case 3:
 91                         strcpy(tmp, "C6");
 92                         break;
 93                 }
 94         } else if (!strncmp(tmp, "SNB-", 4)) {
 95                 switch (num) {
 96                 case 1:
 97                         strcpy(tmp, "C1");
 98                         break;
 99                 case 2:
100                         strcpy(tmp, "C3");
101                         break;
102                 case 3:
103                         strcpy(tmp, "C6");
104                         break;
105                 case 4:
106                         strcpy(tmp, "C7");
107                         break;
108                 }
109         } else if (!strncmp(tmp, "ATM-", 4)) {
110                 switch (num) {
111                 case 1:
112                         strcpy(tmp, "C1");
113                         break;
114                 case 2:
115                         strcpy(tmp, "C2");
116                         break;
117                 case 3:
118                         strcpy(tmp, "C4");
119                         break;
120                 case 4:
121                         strcpy(tmp, "C6");
122                         break;
123                 }
124         }
125 }
126 
127 #ifdef __powerpc__
128 void map_power_idle_state_name(char *tmp)
129 {
130         if (!strncmp(tmp, "stop0_lite", CSTATE_NAME_LEN))
131                 strcpy(tmp, "stop0L");
132         else if (!strncmp(tmp, "stop1_lite", CSTATE_NAME_LEN))
133                 strcpy(tmp, "stop1L");
134         else if (!strncmp(tmp, "stop2_lite", CSTATE_NAME_LEN))
135                 strcpy(tmp, "stop2L");
136 }
137 #else
138 void map_power_idle_state_name(char *tmp) { }
139 #endif
140 
141 static struct cpuidle_monitor *cpuidle_register(void)
142 {
143         int num;
144         char *tmp;
145         int this_cpu;
146 
147         this_cpu = sched_getcpu();
148 
149         /* Assume idle state count is the same for all CPUs */
150         cpuidle_sysfs_monitor.hw_states_num = cpuidle_state_count(this_cpu);
151 
152         if (cpuidle_sysfs_monitor.hw_states_num <= 0)
153                 return NULL;
154 
155         for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) {
156                 tmp = cpuidle_state_name(this_cpu, num);
157                 if (tmp == NULL)
158                         continue;
159 
160                 map_power_idle_state_name(tmp);
161                 fix_up_intel_idle_driver_name(tmp, num);
162                 strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1);
163                 free(tmp);
164 
165                 tmp = cpuidle_state_desc(this_cpu, num);
166                 if (tmp == NULL)
167                         continue;
168                 strncpy(cpuidle_cstates[num].desc, tmp, CSTATE_DESC_LEN - 1);
169                 free(tmp);
170 
171                 cpuidle_cstates[num].range = RANGE_THREAD;
172                 cpuidle_cstates[num].id = num;
173                 cpuidle_cstates[num].get_count_percent =
174                         cpuidle_get_count_percent;
175         }
176 
177         /* Free this at program termination */
178         previous_count = malloc(sizeof(long long *) * cpu_count);
179         current_count = malloc(sizeof(long long *) * cpu_count);
180         for (num = 0; num < cpu_count; num++) {
181                 previous_count[num] = malloc(sizeof(long long) *
182                                         cpuidle_sysfs_monitor.hw_states_num);
183                 current_count[num] = malloc(sizeof(long long) *
184                                         cpuidle_sysfs_monitor.hw_states_num);
185         }
186 
187         cpuidle_sysfs_monitor.name_len = strlen(cpuidle_sysfs_monitor.name);
188         return &cpuidle_sysfs_monitor;
189 }
190 
191 void cpuidle_unregister(void)
192 {
193         int num;
194 
195         for (num = 0; num < cpu_count; num++) {
196                 free(previous_count[num]);
197                 free(current_count[num]);
198         }
199         free(previous_count);
200         free(current_count);
201 }
202 
203 struct cpuidle_monitor cpuidle_sysfs_monitor = {
204         .name                   = "Idle_Stats",
205         .hw_states              = cpuidle_cstates,
206         .start                  = cpuidle_start,
207         .stop                   = cpuidle_stop,
208         .do_register            = cpuidle_register,
209         .unregister             = cpuidle_unregister,
210         .flags.needs_root       = 0,
211         .overflow_s             = UINT_MAX,
212 };
213 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php