/* * Copyright 2010, 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 * or just google for it. * * Authors: * Arjan van de Ven * Peter Anvin */ #include #include #include #include #include #include #include #include #include #include #include #include extern "C" { #include } #include "lib.h" #include #include #include #include #include #include #include #include #include #include #include #include static int kallsyms_read = 0; double percentage(double F) { F = F * 100.0; // if (F > 100.0) // F = 100.0; if (F < 0.0) F = 0.0; return F; } char *hz_to_human(unsigned long hz, char *buffer, int digits) { unsigned long long Hz; buffer[0] = 0; Hz = hz; /* default: just put the Number in */ sprintf(buffer,_("%9lli"), Hz); if (Hz>1000) { if (digits == 2) sprintf(buffer, _("%4lli Mhz"), (Hz+500)/1000); else sprintf(buffer, _("%6lli Mhz"), (Hz+500)/1000); } if (Hz>1500000) { if (digits == 2) sprintf(buffer, _("%4.2f Ghz"), (Hz+5000.0)/1000000); else sprintf(buffer, _("%3.1f Ghz"), (Hz+5000.0)/1000000); } return buffer; } using namespace std; map kallsyms; static void read_kallsyms(void) { ifstream file; char line[1024]; kallsyms_read = 1; file.open("/proc/kallsyms", ios::in); while (file) { char *c = NULL, *c2 = NULL; unsigned long address = 0; memset(line, 0, 1024); file.getline(line, 1024); c = strchr(line, ' '); if (!c) continue; *c = 0; c2 = c + 1; if (*c2) c2++; if (*c2) c2++; address = strtoull(line, NULL, 16); c = strchr(c2, '\t'); if (c) *c = 0; if (address != 0) kallsyms[address] = c2; } file.close(); } const char *kernel_function(uint64_t address) { const char *c; if (!kallsyms_read) read_kallsyms(); c = kallsyms[address].c_str(); if (!c) return ""; return c; } static int _max_cpu; int get_max_cpu(void) { return _max_cpu; } void set_max_cpu(int cpu) { if (cpu > _max_cpu) _max_cpu = cpu; } bool stringless::operator()(const char * const & lhs, const char * const & rhs) const { if (strcmp(lhs, rhs) < 0) return true; return false; } void write_sysfs(const string &filename, const string &value) { ofstream file; file.open(filename.c_str(), ios::out); if (!file) return; file << value; file.close(); } int read_sysfs(const string &filename) { ifstream file; int i; file.open(filename.c_str(), ios::in); if (!file) return 0; file >> i; file.close(); return i; } string read_sysfs_string(const string &filename) { ifstream file; char content[4096]; char *c; file.open(filename.c_str(), ios::in); if (!file) return ""; file.getline(content, 4096); file.close(); c = strchr(content, '\n'); if (c) *c = 0; return content; } string read_sysfs_string(const char *format, const char *param) { ifstream file; char content[4096]; char *c; char filename[8192]; snprintf(filename, 8191, format, param); file.open(filename, ios::in); if (!file) return ""; file.getline(content, 4096); file.close(); c = strchr(content, '\n'); if (c) *c = 0; return content; } void format_watts(double W, char *buffer, unsigned int len) { buffer[0] = 0; char buf[32]; sprintf(buffer, _("%7sW"), fmt_prefix(W, buf)); if (W < 0.0001) sprintf(buffer, _(" 0 mW")); while (mbstowcs(NULL,buffer,0) < len) strcat(buffer, " "); } static struct pci_access *pci_access; char *pci_id_to_name(uint16_t vendor, uint16_t device, char *buffer, int len) { char *ret; buffer[0] = 0; if (!pci_access) { pci_access = pci_alloc(); pci_init(pci_access); } ret = pci_lookup_name(pci_access, buffer, len, PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE, vendor, device); return ret; } void end_pci_access(void) { if (pci_access) pci_free_name_list(pci_access); } int utf_ok = -1; /* pretty print numbers while limiting the precision */ char *fmt_prefix(double n, char *buf) { static const char prefixes[] = "yzafpnum kMGTPEZY"; char tmpbuf[16]; int omag, npfx; char *p, *q, pfx, *c; int i; if (utf_ok == -1) { char *g; g = getenv("LANG"); if (g && strstr(g, "UTF-8")) utf_ok = 1; else utf_ok = 0; } p = buf; *p = ' '; if (n < 0.0) { *p = '-'; n = -n; p++; } snprintf(tmpbuf, sizeof tmpbuf, "%.2e", n); c = strchr(tmpbuf, 'e'); if (!c) { sprintf(buf, "NaN"); return buf; } omag = atoi(c + 1); npfx = ((omag + 27) / 3) - (27/3); omag = (omag + 27) % 3; q = tmpbuf; if (omag == 2) omag = -1; for (i = 0; i < 3; i++) { while (!isdigit(*q)) q++; *p++ = *q++; if (i == omag) *p++ = '.'; } *p++ = ' '; pfx = prefixes[npfx + 8]; if (pfx == ' ') { /* do nothing */ } else if (pfx == 'u' && utf_ok > 0) { strcpy(p, "ยต"); /* Mu is a multibyte sequence */ while (*p) p++; } else { *p++ = pfx; } *p = '\0'; return buf; } static map pretty_prints; static int pretty_print_init = 0; static void init_pretty_print(void) { pretty_prints["[12] i8042"] = _("PS/2 Touchpad / Keyboard / Mouse"); pretty_prints["ahci"] = _("SATA controller"); pretty_prints["usb-device-8087-0020"] = _("Intel built in USB hub"); } char *pretty_print(const char *str, char *buf, int len) { const char *p; if (!pretty_print_init) init_pretty_print(); p = pretty_prints[str].c_str(); if (strlen(p) == 0) p = str; snprintf(buf, len, "%s", p); if (len) buf[len - 1] = 0; return buf; } int equals(double a, double b) { return fabs(a - b) <= std::numeric_limits::epsilon(); } void process_directory(const char *d_name, callback fn) { struct dirent *entry; DIR *dir; dir = opendir(d_name); if (!dir) return; while (1) { entry = readdir(dir); if (!entry) break; if (entry->d_name[0] == '.') continue; if (strcmp(entry->d_name, "lo")==0) continue; fn(entry->d_name); } closedir(dir); }