root/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cpuidle_get_count_percent
  2. cpuidle_start
  3. cpuidle_stop
  4. fix_up_intel_idle_driver_name
  5. map_power_idle_state_name
  6. map_power_idle_state_name
  7. cpuidle_register
  8. cpuidle_unregister

   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         .needs_root             = 0,
 211         .overflow_s             = UINT_MAX,
 212 };

/* [<][>][^][v][top][bottom][index][help] */