/* * Copyright 2007, Intel Corporation * * This file is part of PowerTOP * * This program file is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License * along with this program in a file named COPYING; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * Authors: * Arjan van de Ven */ #include #include #include #include #include #include #include #include "powertop.h" #define MAX_PSTATES 32 #define MAX_CPUS 8 struct cpufreqdata { uint64_t frequency; uint64_t count; }; struct cpufreqdata freqs[MAX_CPUS][MAX_PSTATES]; struct cpufreqdata oldfreqs[MAX_CPUS][MAX_PSTATES]; struct cpufreqdata delta[MAX_CPUS][MAX_PSTATES]; char cpufreqstrings[25][256]; int topfreq = -1; static void zap(void) { memset(freqs, 0, sizeof(freqs)); } int sort_by_count (const void *av, const void *bv) { const struct cpufreqdata *a = av, *b = bv; return b->count - a->count; } int sort_by_freq (const void *av, const void *bv) { const struct cpufreqdata *a = av, *b = bv; return b->frequency - a->frequency; } static char *HzToHuman(unsigned long hz) { static char buffer[1024]; memset(buffer, 0, 1024); unsigned long long Hz; Hz = hz; /* default: just put the Number in */ sprintf(buffer,_("%9lli"), Hz); if (Hz>1000) sprintf(buffer, _("%6lli Mhz"), (Hz+500)/1000); if (Hz>1500000) sprintf(buffer, _("%6.2f Ghz"), (Hz+5000.0)/1000000); return buffer; } void do_cpufreq_stats(void) { DIR *dir; struct dirent *dirent; FILE *file; char filename[PATH_MAX]; char line[1024]; int cpu = -1; int ret, cpucount; int maxfreq = 0; uint64_t total_time[MAX_CPUS] = {0}; memcpy(&oldfreqs, &freqs, sizeof(freqs)); memset(&cpufreqstrings, 0, sizeof(cpufreqstrings)); sprintf(cpufreqstrings[0], _("P-states (frequencies)\n")); for (ret = 0; retd_name[0]=='.') continue; sprintf(filename, "/sys/devices/system/cpu/%s/cpufreq/stats/time_in_state", dirent->d_name); file = fopen(filename, "r"); if (!file) continue; memset(line, 0, 1024); cpu++; if ( cpu >= MAX_CPUS) cpu = MAX_CPUS -1; i = 0; while (!feof(file)) { uint64_t f,count; char *c; if (fgets(line, 1023,file)==NULL) break; f = strtoull(line, &c, 10); if (!c) break; count = strtoull(c, NULL, 10); if (freqs[cpu][i].frequency && freqs[cpu][i].frequency != f) { zap(); break; } freqs[cpu][i].frequency = f; freqs[cpu][i].count += count; if (f && maxfreq < i) maxfreq = i; i++; if (i>(MAX_PSTATES - 1)) break; } fclose(file); } closedir(dir); for (ret = 0; ret < MAX_PSTATES; ret++) { for (cpucount = 0; cpucount < MAX_CPUS; cpucount++) { delta[cpucount][ret].count = freqs[cpucount][ret].count - oldfreqs[cpucount][ret].count; total_time[cpucount] += delta[cpucount][ret].count; delta[cpucount][ret].frequency = freqs[cpucount][ret].frequency; if (freqs[cpucount][ret].frequency != oldfreqs[cpucount][ret].frequency) return; /* duff data */ } } for (cpucount = 0 ; cpucount < MAX_CPUS; cpucount++) { if (total_time[cpucount]) break; } if (cpucount == MAX_CPUS) return; topfreq = -1; for (ret = 0 ; ret<=maxfreq && ret<=254; ret++) { uint64_t last_freq = -1; strlcpy(cpufreqstrings[ret+1], " ",sizeof(cpufreqstrings[ret+1])); for ( cpucount = 0; cpucount <= cpu; cpucount++) { char temp_freq[32]; if (delta[cpucount][ret].frequency != last_freq && delta[cpucount][ret].frequency != 0) { snprintf(temp_freq, sizeof(temp_freq), "%6s", HzToHuman(delta[cpucount][ret].frequency)); strncat(cpufreqstrings[ret+1], temp_freq, 32); last_freq = delta[cpucount][ret].frequency; } snprintf(temp_freq, sizeof(temp_freq), "\t%5.1f%% ", delta[cpucount][ret].count * 100.0 / total_time[cpucount]); strncat(cpufreqstrings[ret+1], temp_freq, 32); if (delta[cpucount][ret].count > total_time[cpucount]/2) topfreq = ret; } strncat(cpufreqstrings[ret+1], "\n", 1); } }