123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- /*
- * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc
- *
- * Licensed under the terms of the GNU GPL License version 2.
- *
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <string.h>
- #include <limits.h>
- #include "helpers/sysfs.h"
- #include "helpers/helpers.h"
- #include "idle_monitor/cpupower-monitor.h"
- #define CPUIDLE_STATES_MAX 10
- static cstate_t cpuidle_cstates[CPUIDLE_STATES_MAX];
- struct cpuidle_monitor cpuidle_sysfs_monitor;
- static unsigned long long **previous_count;
- static unsigned long long **current_count;
- struct timespec start_time;
- static unsigned long long timediff;
- static int cpuidle_get_count_percent(unsigned int id, double *percent,
- unsigned int cpu)
- {
- unsigned long long statediff = current_count[cpu][id]
- - previous_count[cpu][id];
- dprint("%s: - diff: %llu - percent: %f (%u)\n",
- cpuidle_cstates[id].name, timediff, *percent, cpu);
- if (timediff == 0)
- *percent = 0.0;
- else
- *percent = ((100.0 * statediff) / timediff);
- dprint("%s: - timediff: %llu - statediff: %llu - percent: %f (%u)\n",
- cpuidle_cstates[id].name, timediff, statediff, *percent, cpu);
- return 0;
- }
- static int cpuidle_start(void)
- {
- int cpu, state;
- clock_gettime(CLOCK_REALTIME, &start_time);
- for (cpu = 0; cpu < cpu_count; cpu++) {
- for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
- state++) {
- previous_count[cpu][state] =
- sysfs_get_idlestate_time(cpu, state);
- dprint("CPU %d - State: %d - Val: %llu\n",
- cpu, state, previous_count[cpu][state]);
- }
- };
- return 0;
- }
- static int cpuidle_stop(void)
- {
- int cpu, state;
- struct timespec end_time;
- clock_gettime(CLOCK_REALTIME, &end_time);
- timediff = timespec_diff_us(start_time, end_time);
- for (cpu = 0; cpu < cpu_count; cpu++) {
- for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
- state++) {
- current_count[cpu][state] =
- sysfs_get_idlestate_time(cpu, state);
- dprint("CPU %d - State: %d - Val: %llu\n",
- cpu, state, previous_count[cpu][state]);
- }
- };
- return 0;
- }
- void fix_up_intel_idle_driver_name(char *tmp, int num)
- {
- /* fix up cpuidle name for intel idle driver */
- if (!strncmp(tmp, "NHM-", 4)) {
- switch (num) {
- case 1:
- strcpy(tmp, "C1");
- break;
- case 2:
- strcpy(tmp, "C3");
- break;
- case 3:
- strcpy(tmp, "C6");
- break;
- }
- } else if (!strncmp(tmp, "SNB-", 4)) {
- switch (num) {
- case 1:
- strcpy(tmp, "C1");
- break;
- case 2:
- strcpy(tmp, "C3");
- break;
- case 3:
- strcpy(tmp, "C6");
- break;
- case 4:
- strcpy(tmp, "C7");
- break;
- }
- } else if (!strncmp(tmp, "ATM-", 4)) {
- switch (num) {
- case 1:
- strcpy(tmp, "C1");
- break;
- case 2:
- strcpy(tmp, "C2");
- break;
- case 3:
- strcpy(tmp, "C4");
- break;
- case 4:
- strcpy(tmp, "C6");
- break;
- }
- }
- }
- static struct cpuidle_monitor *cpuidle_register(void)
- {
- int num;
- char *tmp;
- /* Assume idle state count is the same for all CPUs */
- cpuidle_sysfs_monitor.hw_states_num = sysfs_get_idlestate_count(0);
- if (cpuidle_sysfs_monitor.hw_states_num <= 0)
- return NULL;
- for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) {
- tmp = sysfs_get_idlestate_name(0, num);
- if (tmp == NULL)
- continue;
- fix_up_intel_idle_driver_name(tmp, num);
- strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1);
- free(tmp);
- tmp = sysfs_get_idlestate_desc(0, num);
- if (tmp == NULL)
- continue;
- strncpy(cpuidle_cstates[num].desc, tmp, CSTATE_DESC_LEN - 1);
- free(tmp);
- cpuidle_cstates[num].range = RANGE_THREAD;
- cpuidle_cstates[num].id = num;
- cpuidle_cstates[num].get_count_percent =
- cpuidle_get_count_percent;
- };
- /* Free this at program termination */
- previous_count = malloc(sizeof(long long *) * cpu_count);
- current_count = malloc(sizeof(long long *) * cpu_count);
- for (num = 0; num < cpu_count; num++) {
- previous_count[num] = malloc(sizeof(long long) *
- cpuidle_sysfs_monitor.hw_states_num);
- current_count[num] = malloc(sizeof(long long) *
- cpuidle_sysfs_monitor.hw_states_num);
- }
- cpuidle_sysfs_monitor.name_len = strlen(cpuidle_sysfs_monitor.name);
- return &cpuidle_sysfs_monitor;
- }
- void cpuidle_unregister(void)
- {
- int num;
- for (num = 0; num < cpu_count; num++) {
- free(previous_count[num]);
- free(current_count[num]);
- }
- free(previous_count);
- free(current_count);
- }
- struct cpuidle_monitor cpuidle_sysfs_monitor = {
- .name = "Idle_Stats",
- .hw_states = cpuidle_cstates,
- .start = cpuidle_start,
- .stop = cpuidle_stop,
- .do_register = cpuidle_register,
- .unregister = cpuidle_unregister,
- .needs_root = 0,
- .overflow_s = UINT_MAX,
- };
|