A series of patches towards limiting memory corruption and foot print
by Kalowsky, Daniel
Hi Powertop,
I've been working with the interactive mode and have run into cases where powertop will crash due to a series of memory corruptions. The following series of patches have helped to reduce the frequency of the issue, although not completely solved it. The issues arise much faster on platforms where there are constrained amounts of RAM to work within.
Patch 1 - When shutting down the interactive display, the display bits of memory is not correctly released. This patch provides a method for correctly doing so.
Patch 2 - Solving a documented memory leak with a non-elegant solution. The path either adds the bundle to the stack, or it forgets about it. If it is forgotten about, make sure to clear that memory before moving on. This is done with a simple flag variable being set.
Patch 3 - When the tuning window is updated, the current pointer is just set adrift and not properly free'd. This patch catches that issue and removes the dangling pointer by holding a reference to the pointer until it is reset or specifically free'd.
Patch 4 - Someone actually added in the code to create a onetime pretty-print array, this patch just puts it to use by setting the variable.
Patch 5 - Limiting the buffer copy to the size of the allocated buffer with snprintf.
Patch 6 - There exist some processes and entries that can and do extend beyond the length of these buffers. This limits those entries so as not to corrupt other memory on the system when in interactive mode.
Patch 7 - This is an untested patch, but follows along the same lines of Patch 6. It applies the same principals only for the report method.
Patch 8 - Creates a clean_shutdown function that can be used to cleanup the memory space at shutdown time. Calls upon parts of Patch 1 to make this happen.
There will more than likely be some more patches in the future as time permits.
7 years, 6 months
[PATCH] devfreq: add devfreq devices stats support
by Sanjay Singh Rawat
add window to show frequency stats for devfreq devices
Signed-off-by: Rajagopal Venkat <rajagopal.venkat(a)gmail.com>
Signed-off-by: Sanjay Singh Rawat <sanjay.rawat(a)linaro.org>
---
src/Makefile.am | 2 +-
src/devices/devfreq.cpp | 351 ++++++++++++++++++++++++++++++++++++++++++++++
src/devices/devfreq.h | 75 ++++++++++
src/main.cpp | 9 ++
src/report/report-maker.h | 1 +
5 files changed, 437 insertions(+), 1 deletion(-)
create mode 100644 src/devices/devfreq.cpp
create mode 100644 src/devices/devfreq.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 6886388..fee1ffa 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,7 +32,7 @@ powertop_SOURCES = parameters/persistent.cpp parameters/learn.cpp parameters/par
report/report-formatter-csv.cpp report/report-formatter-csv.h \
report/report-formatter-html.cpp report/report-formatter-html.h \
report/report-data-html.cpp report/report-data-html.h \
- main.cpp css.h powertop.css cpu/intel_gpu.cpp \
+ main.cpp css.h powertop.css cpu/intel_gpu.cpp devices/devfreq.cpp \
cpu/rapl/rapl_interface.cpp cpu/cpu_rapl_device.cpp cpu/rapl/rapl_interface.h\
cpu/dram_rapl_device.cpp devices/gpu_rapl_device.cpp cpu/cpu_rapl_device.h \
cpu/dram_rapl_device.h devices/gpu_rapl_device.h
diff --git a/src/devices/devfreq.cpp b/src/devices/devfreq.cpp
new file mode 100644
index 0000000..29d7790
--- /dev/null
+++ b/src/devices/devfreq.cpp
@@ -0,0 +1,351 @@
+/*
+ * Copyright 2012, Linaro
+ *
+ * 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:
+ * Rajagopal Venkat <rajagopal.venkat(a)linaro.org>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#include <dirent.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "device.h"
+#include "devfreq.h"
+#include "../display.h"
+#include "../cpu/cpu.h"
+#include "../report/report.h"
+#include "../report/report-maker.h"
+
+static bool is_enabled = true;
+
+static vector<class devfreq *> all_devfreq;
+
+devfreq::devfreq(const char* dpath): device()
+{
+ strncpy(dir_name, dpath, sizeof(dir_name));
+}
+
+uint64_t devfreq::parse_freq_time(char* pchr)
+{
+ char *cptr, *pptr = pchr;
+ uint64_t ctime;
+
+ cptr = strtok(pchr, " :");
+ while (cptr != NULL) {
+ cptr = strtok(NULL, " :");
+ if (cptr )
+ pptr = cptr;
+ }
+
+ ctime = strtoull(pptr, NULL, 10);
+ return ctime;
+}
+
+void devfreq::process_time_stamps()
+{
+ unsigned int i;
+ uint64_t active_time = 0;
+
+ sample_time = (1000000.0 * (stamp_after.tv_sec - stamp_before.tv_sec))
+ + ((stamp_after.tv_usec - stamp_before.tv_usec) );
+
+ for (i=0; i < dstates.size()-1; i++) {
+ struct frequency *state = dstates[i];
+ state->time_after = 1000 * (state->time_after - state->time_before);
+ active_time += state->time_after;
+ }
+ /* Compute idle time for the device */
+ dstates[i]->time_after = sample_time - active_time;
+}
+
+void devfreq::add_devfreq_freq_state(uint64_t freq, uint64_t time)
+{
+ struct frequency *state;
+
+ state = new(std::nothrow) struct frequency;
+ if (!state)
+ return;
+
+ memset(state, 0, sizeof(*state));
+ dstates.push_back(state);
+
+ state->freq = freq;
+ if (freq == 0)
+ strcpy(state->human_name, "Idle");
+ else
+ hz_to_human(freq, state->human_name);
+ state->time_before = time;
+}
+
+void devfreq::update_devfreq_freq_state(uint64_t freq, uint64_t time)
+{
+ unsigned int i;
+ struct frequency *state = NULL;
+
+ for(i=0; i < dstates.size(); i++) {
+ if (freq == dstates[i]->freq)
+ state = dstates[i];
+ }
+
+ if (state == NULL) {
+ add_devfreq_freq_state(freq, time);
+ return;
+ }
+
+ state->time_after = time;
+}
+
+void devfreq::parse_devfreq_trans_stat(char *dname)
+{
+ ifstream file;
+ char filename[256];
+
+ sprintf(filename, "/sys/class/devfreq/%s/trans_stat", dir_name);
+ file.open(filename);
+
+ if (!file)
+ return;
+
+ char line[1024];
+ char *c;
+
+ while (file) {
+ uint64_t freq;
+ uint64_t time;
+ char *pchr;
+
+ memset(line, 0, sizeof(line));
+ file.getline(line, sizeof(line));
+
+ pchr = strchr(line, '*');
+ pchr = (pchr != NULL) ? pchr+1 : line;
+
+ freq = strtoull(pchr, &c, 10);
+ if (!freq)
+ continue;
+
+ time = parse_freq_time(pchr);
+ update_devfreq_freq_state(freq, time);
+ }
+ file.close();
+}
+
+void devfreq::start_measurement(void)
+{
+ unsigned int i;
+ ifstream file;
+
+ for (i=0; i < dstates.size(); i++)
+ delete dstates[i];
+ dstates.resize(0);
+ sample_time = 0;
+
+ gettimeofday(&stamp_before, NULL);
+ parse_devfreq_trans_stat(dir_name);
+ /* add device idle state */
+ update_devfreq_freq_state(0, 0);
+}
+
+void devfreq::end_measurement(void)
+{
+ parse_devfreq_trans_stat(dir_name);
+ gettimeofday(&stamp_after, NULL);
+ process_time_stamps();
+}
+
+double devfreq::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ return 0;
+}
+
+double devfreq::utilization(void)
+{
+ return 0;
+}
+
+void devfreq::fill_freq_utilization(unsigned int idx, char *buf)
+{
+ buf[0] = 0;
+
+ if (idx < dstates.size() && dstates[idx]) {
+ struct frequency *state = dstates[idx];
+ sprintf(buf, " %5.1f%% ", percentage(1.0 * state->time_after / sample_time));
+ }
+}
+
+void devfreq::fill_freq_name(unsigned int idx, char *buf)
+{
+ buf[0] = 0;
+
+ if (idx < dstates.size() && dstates[idx]) {
+ sprintf(buf, "%-15s", dstates[idx]->human_name);
+ }
+}
+
+void start_devfreq_measurement(void)
+{
+ unsigned int i;
+
+ for (i=0; i<all_devfreq.size(); i++)
+ all_devfreq[i]->start_measurement();
+}
+
+void end_devfreq_measurement(void)
+{
+ unsigned int i;
+
+ for (i=0; i<all_devfreq.size(); i++)
+ all_devfreq[i]->end_measurement();
+}
+
+static void devfreq_dev_callback(const char *d_name)
+{
+ devfreq *df = new(std::nothrow) class devfreq(d_name);
+ if (df)
+ all_devfreq.push_back(df);
+}
+
+void create_all_devfreq_devices(void)
+{
+ DIR *dir;
+ std::string p = "/sys/class/devfreq/";
+ dir = opendir(p.c_str());
+ if (dir == NULL) {
+ fprintf(stderr, "Devfreq not enabled\n");
+ is_enabled = false;
+ return;
+ }
+
+ callback fn = &devfreq_dev_callback;
+ process_directory(p.c_str(), fn);
+}
+
+void initialize_devfreq(void)
+{
+ if (is_enabled)
+ create_tab("Device Freq stats", _("Device Freq stats"));
+}
+
+void display_devfreq_devices(void)
+{
+ unsigned int i, j;
+ WINDOW *win;
+ char fline[1024];
+ char buf[128];
+
+ win = get_ncurses_win("Device Freq stats");
+ if (!win)
+ return;
+
+ wclear(win);
+ wmove(win, 2,0);
+
+ if (!is_enabled) {
+ wprintw(win, _(" Devfreq is not enabled"));
+ return;
+ }
+
+ if (!all_devfreq.size()) {
+ wprintw(win, _(" No devfreq devices available"));
+ return;
+ }
+
+ for (i=0; i<all_devfreq.size(); i++) {
+
+ class devfreq *df = all_devfreq[i];
+ wprintw(win, "\n%s\n", df->device_name());
+
+ for(j=0; j < df->dstates.size(); j++) {
+ memset(fline, 0, sizeof(fline));
+ strcpy(fline, "\t");
+ df->fill_freq_name(j, buf);
+ strcat(fline, buf);
+ df->fill_freq_utilization(j, buf);
+ strcat(fline, buf);
+ strcat(fline, "\n");
+ wprintw(win, fline);
+ }
+ wprintw(win, "\n");
+ }
+}
+
+void report_devfreq_devices(void)
+{
+ if (!is_enabled) {
+ return;
+ }
+
+/* todo: adapt to new report format */
+#if 0
+ char buffer[512];
+ unsigned int i, j;
+
+ report.begin_section(SECTION_DEVFREQ);
+ report.add_header("Device Frequency Report");
+
+ report.begin_table(TABLE_WIDE);
+ if (!all_devfreq.size()) {
+ report.begin_row();
+ report.add(" No devfreq devices available");
+ return;
+ }
+
+ for (i = 0; i < all_devfreq.size(); i++) {
+ buffer[0] = 0;
+ class devfreq *df = all_devfreq[i];
+
+ report.begin_row();
+ report.begin_cell(CELL_CPU_PSTATE_HEADER);
+ report.addf("%s", df->device_name());
+
+ for (j = 0; j < df->dstates.size(); j++) {
+ report.begin_row();
+ report.begin_cell(CELL_CPU_STATE_VALUE);
+ df->fill_freq_name(j, buffer);
+ report.add(buffer);
+ report.begin_cell(CELL_CPU_STATE_VALUE);
+ df->fill_freq_utilization(j, buffer);
+ report.add(buffer);
+ }
+ }
+#endif
+
+}
+
+void clear_all_devfreq()
+{
+ unsigned int i, j;
+
+ for (i=0; i < all_devfreq.size(); i++) {
+ class devfreq *df = all_devfreq[i];
+
+ for(j=0; j < df->dstates.size(); j++)
+ delete df->dstates[j];
+
+ df->dstates.resize(0);
+ delete df;
+ }
+ all_devfreq.clear();
+}
diff --git a/src/devices/devfreq.h b/src/devices/devfreq.h
new file mode 100644
index 0000000..8ab5705
--- /dev/null
+++ b/src/devices/devfreq.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012, Linaro
+ *
+ * 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:
+ * Rajagopal Venkat <rajagopal.venkat(a)linaro.org>
+ */
+#ifndef _INCLUDE_GUARD_DEVFREQ_H
+#define _INCLUDE_GUARD_DEVFREQ_H
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+struct frequency;
+
+class devfreq: public device {
+ char dir_name[4096];
+ struct timeval stamp_before, stamp_after;
+ double sample_time;
+
+ uint64_t parse_freq_time(char *ptr);
+ void add_devfreq_freq_state(uint64_t freq, uint64_t time);
+ void update_devfreq_freq_state(uint64_t freq, uint64_t time);
+ void parse_devfreq_trans_stat(char *dname);
+ void process_time_stamps();
+
+public:
+
+ vector<struct frequency *> dstates;
+
+ devfreq(const char *c);
+ void fill_freq_utilization(unsigned int idx, char *buf);
+ void fill_freq_name(unsigned int idx, char *buf);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "devfreq";};
+
+ virtual const char * device_name(void) { return dir_name;};
+ virtual const char * human_name(void) { return "devfreq";};
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual const char * util_units(void) { return " rpm"; };
+ virtual int power_valid(void) { return 0; /*utilization_power_valid(r_index);*/};
+ virtual int grouping_prio(void) { return 1; };
+};
+
+extern void create_all_devfreq_devices(void);
+extern void clear_all_devfreq(void);
+extern void display_devfreq_devices(void);
+extern void report_devfreq_devices(void);
+extern void initialize_devfreq(void);
+extern void start_devfreq_measurement(void);
+extern void end_devfreq_measurement(void);
+
+#endif
diff --git a/src/main.cpp b/src/main.cpp
index cf4e547..d33eaed 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -48,6 +48,7 @@
#include "devices/device.h"
+#include "devices/devfreq.h"
#include "devices/usb.h"
#include "devices/ahci.h"
#include "measurement/measurement.h"
@@ -194,6 +195,7 @@ void one_measurement(int seconds, char *workload)
create_all_usb_devices();
start_power_measurement();
devices_start_measurement();
+ start_devfreq_measurement();
start_process_measurement();
start_cpu_measurement();
@@ -206,6 +208,7 @@ void one_measurement(int seconds, char *workload)
end_cpu_measurement();
end_process_measurement();
collect_open_devices();
+ end_devfreq_measurement();
devices_end_measurement();
end_power_measurement();
@@ -233,6 +236,9 @@ void one_measurement(int seconds, char *workload)
report_show_open_devices();
report_devices();
+ display_devfreq_devices();
+ report_devfreq_devices();
+
ahci_create_device_stats_table();
store_results(measurement_time);
end_cpu_data();
@@ -344,6 +350,7 @@ static void powertop_init(void)
enumerate_cpus();
create_all_devices();
+ create_all_devfreq_devices();
detect_power_meters();
register_parameter("base power", 100, 0.5);
@@ -457,6 +464,7 @@ int main(int argc, char **argv)
exit(0);
}
init_display();
+ initialize_devfreq();
initialize_tuning();
/* first one is short to not let the user wait too long */
one_measurement(1, NULL);
@@ -491,6 +499,7 @@ int main(int argc, char **argv)
clean_open_devices();
clear_all_devices();
+ clear_all_devfreq();
clear_all_cpus();
return 0;
diff --git a/src/report/report-maker.h b/src/report/report-maker.h
index 423568a..bda4cef 100644
--- a/src/report/report-maker.h
+++ b/src/report/report-maker.h
@@ -89,6 +89,7 @@ enum section_type {
SECTION_SYSINFO,
SECTION_CPUIDLE,
SECTION_CPUFREQ,
+ SECTION_DEVFREQ,
SECTION_DEVPOWER,
SECTION_SOFTWARE,
SECTION_SUMMARY,
--
1.8.3.2
7 years, 7 months
[PATCH 0/1] Update target value of Power Aware CPU scheduler tunable
by Nanley Chery
Hello,
This patch fixes a problem made evident by the debian bug 655843,
'powertop report[s] incorrect "bad" value.'
The issue is that the tunable for the "Power Aware CPU scheduler" has an
outdated target value of "1". That value was correct in linux kernels
before the 2.6.29 release. However, starting with the 2.6.29 release,
the level setting for the scheduler that offered the greatest power
savings was increased to "2" (linux kernel commit:
afb8a9b70b86866a60e08b2956ae4e1406390336). Eventually, due to seemingly
poor code maintenance, the power aware scheduler feature was removed
altogther in the 3.5 linux kernel (linux kernel commit:
8e7fbcbc22c12414bcc9dfdd683637f58fb32759).
According to the README file, we currently support kernels that have the
updated power savings level (>= 2.6.38). Therefore, this patch updates
the target value to "2" and conditionally omits adding the tunable for
kernel versions that do not support the feature (>= 3.5).
Nanley Chery (1):
tunable: update sched_mc_power_savings target value
src/tuning/tuning.cpp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--
2.0.4
7 years, 7 months
[PATCH v2 1/1] tunables: check usb autosuspend support before add
by Nanley Chery
Some usb devices do not have drivers that support autosuspend.
These drivers should not be added to the list of tunables, because
toggling their good/bad value does nothing.
Signed-off-by: Nanley Chery <nanleychery(a)gmail.com>
---
Fixed the issue in the previous patch that allowed returning between
opendir and closedir (thanks Sergey). Also improve detection of interface
folders.
src/tuning/tuningusb.cpp | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/src/tuning/tuningusb.cpp b/src/tuning/tuningusb.cpp
index 27a6dca..d2a0c11 100644
--- a/src/tuning/tuningusb.cpp
+++ b/src/tuning/tuningusb.cpp
@@ -28,6 +28,7 @@
#include "unistd.h"
#include "tuningusb.h"
#include <string.h>
+#include <dirent.h>
#include <utility>
#include <iostream>
#include <fstream>
@@ -117,6 +118,7 @@ static void add_usb_callback(const char *d_name)
{
class usb_tunable *usb;
char filename[4096];
+ DIR *dir;
sprintf(filename, "/sys/bus/usb/devices/%s/power/control", d_name);
if (access(filename, R_OK) != 0)
@@ -126,6 +128,23 @@ static void add_usb_callback(const char *d_name)
if (access(filename, R_OK)!=0)
return;
+ /* every interface of this device should support autosuspend */
+ sprintf(filename, "/sys/bus/usb/devices/%s", d_name);
+ if ((dir = opendir(filename))) {
+ struct dirent *entry;
+ while ((entry = readdir(dir))) {
+ /* dirname: <busnum>-<devnum>...:<config num>-<interface num> */
+ if (!isdigit(entry->d_name[0]))
+ continue;
+ sprintf(filename, "/sys/bus/usb/devices/%s/%s/supports_autosuspend", d_name, entry->d_name);
+ if (access(filename, R_OK) == 0 && read_sysfs(filename) == 0)
+ break;
+ }
+ closedir(dir);
+ if (entry)
+ return;
+ }
+
sprintf(filename, "/sys/bus/usb/devices/%s", d_name);
usb = new class usb_tunable(filename, d_name);
all_tunables.push_back(usb);
--
2.0.4
7 years, 7 months
[PATCH RESEND] Powertop: remove unnecessary code
by Salman Ahmed
nr_open is already initialized by NR_OPEN_DEF. Removing unnecessary checking and
assignment.
Signed-off-by: Salman Ahmed <salman0yam(a)gmail.com>
---
src/main.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/main.cpp b/src/main.cpp
index cf4e547..990bc1f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -293,8 +293,6 @@ static int get_nr_open(void) {
file.open("/proc/sys/fs/nr_open", ios::in);
if (file) {
file >> nr_open;
- if (!file)
- nr_open = NR_OPEN_DEF;
file.close();
}
return nr_open;
--
1.8.1.2
7 years, 7 months
how to build powerTop 2.6 for android kitkat
by Wang, Li W
Hi all,
I want to use powerTop on android device, but I did not know how to compile it for android kitkat. I have downloaded powerTop-2.6.1 from 01.org, libnl, pciutils from github, and put them to android_src/external/. Where can I get source code of libtraceevnet? Is there any BKM for building powerTop for android kitkat? Really appreciated for your help!
Thanks
Wang Li
7 years, 8 months
[PATCH] devfreq: add devfreq devices stats support
by Sanjay Singh Rawat
add window to show frequency stats for devfreq devices
Signed-off-by: Rajagopal Venkat <rajagopal.venkat(a)linaro.org>
Signed-off-by: Sanjay Singh Rawat <sanjay.rawat(a)linaro.org>
---
src/Makefile.am | 2 +-
src/devices/devfreq.cpp | 351 ++++++++++++++++++++++++++++++++++++++++++++++
src/devices/devfreq.h | 75 ++++++++++
src/main.cpp | 9 ++
src/report/report-maker.h | 1 +
5 files changed, 437 insertions(+), 1 deletion(-)
create mode 100644 src/devices/devfreq.cpp
create mode 100644 src/devices/devfreq.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 6886388..fee1ffa 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,7 +32,7 @@ powertop_SOURCES = parameters/persistent.cpp parameters/learn.cpp parameters/par
report/report-formatter-csv.cpp report/report-formatter-csv.h \
report/report-formatter-html.cpp report/report-formatter-html.h \
report/report-data-html.cpp report/report-data-html.h \
- main.cpp css.h powertop.css cpu/intel_gpu.cpp \
+ main.cpp css.h powertop.css cpu/intel_gpu.cpp devices/devfreq.cpp \
cpu/rapl/rapl_interface.cpp cpu/cpu_rapl_device.cpp cpu/rapl/rapl_interface.h\
cpu/dram_rapl_device.cpp devices/gpu_rapl_device.cpp cpu/cpu_rapl_device.h \
cpu/dram_rapl_device.h devices/gpu_rapl_device.h
diff --git a/src/devices/devfreq.cpp b/src/devices/devfreq.cpp
new file mode 100644
index 0000000..29d7790
--- /dev/null
+++ b/src/devices/devfreq.cpp
@@ -0,0 +1,351 @@
+/*
+ * Copyright 2012, Linaro
+ *
+ * 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:
+ * Rajagopal Venkat <rajagopal.venkat(a)linaro.org>
+ */
+
+#include <iostream>
+#include <fstream>
+
+#include <dirent.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "device.h"
+#include "devfreq.h"
+#include "../display.h"
+#include "../cpu/cpu.h"
+#include "../report/report.h"
+#include "../report/report-maker.h"
+
+static bool is_enabled = true;
+
+static vector<class devfreq *> all_devfreq;
+
+devfreq::devfreq(const char* dpath): device()
+{
+ strncpy(dir_name, dpath, sizeof(dir_name));
+}
+
+uint64_t devfreq::parse_freq_time(char* pchr)
+{
+ char *cptr, *pptr = pchr;
+ uint64_t ctime;
+
+ cptr = strtok(pchr, " :");
+ while (cptr != NULL) {
+ cptr = strtok(NULL, " :");
+ if (cptr )
+ pptr = cptr;
+ }
+
+ ctime = strtoull(pptr, NULL, 10);
+ return ctime;
+}
+
+void devfreq::process_time_stamps()
+{
+ unsigned int i;
+ uint64_t active_time = 0;
+
+ sample_time = (1000000.0 * (stamp_after.tv_sec - stamp_before.tv_sec))
+ + ((stamp_after.tv_usec - stamp_before.tv_usec) );
+
+ for (i=0; i < dstates.size()-1; i++) {
+ struct frequency *state = dstates[i];
+ state->time_after = 1000 * (state->time_after - state->time_before);
+ active_time += state->time_after;
+ }
+ /* Compute idle time for the device */
+ dstates[i]->time_after = sample_time - active_time;
+}
+
+void devfreq::add_devfreq_freq_state(uint64_t freq, uint64_t time)
+{
+ struct frequency *state;
+
+ state = new(std::nothrow) struct frequency;
+ if (!state)
+ return;
+
+ memset(state, 0, sizeof(*state));
+ dstates.push_back(state);
+
+ state->freq = freq;
+ if (freq == 0)
+ strcpy(state->human_name, "Idle");
+ else
+ hz_to_human(freq, state->human_name);
+ state->time_before = time;
+}
+
+void devfreq::update_devfreq_freq_state(uint64_t freq, uint64_t time)
+{
+ unsigned int i;
+ struct frequency *state = NULL;
+
+ for(i=0; i < dstates.size(); i++) {
+ if (freq == dstates[i]->freq)
+ state = dstates[i];
+ }
+
+ if (state == NULL) {
+ add_devfreq_freq_state(freq, time);
+ return;
+ }
+
+ state->time_after = time;
+}
+
+void devfreq::parse_devfreq_trans_stat(char *dname)
+{
+ ifstream file;
+ char filename[256];
+
+ sprintf(filename, "/sys/class/devfreq/%s/trans_stat", dir_name);
+ file.open(filename);
+
+ if (!file)
+ return;
+
+ char line[1024];
+ char *c;
+
+ while (file) {
+ uint64_t freq;
+ uint64_t time;
+ char *pchr;
+
+ memset(line, 0, sizeof(line));
+ file.getline(line, sizeof(line));
+
+ pchr = strchr(line, '*');
+ pchr = (pchr != NULL) ? pchr+1 : line;
+
+ freq = strtoull(pchr, &c, 10);
+ if (!freq)
+ continue;
+
+ time = parse_freq_time(pchr);
+ update_devfreq_freq_state(freq, time);
+ }
+ file.close();
+}
+
+void devfreq::start_measurement(void)
+{
+ unsigned int i;
+ ifstream file;
+
+ for (i=0; i < dstates.size(); i++)
+ delete dstates[i];
+ dstates.resize(0);
+ sample_time = 0;
+
+ gettimeofday(&stamp_before, NULL);
+ parse_devfreq_trans_stat(dir_name);
+ /* add device idle state */
+ update_devfreq_freq_state(0, 0);
+}
+
+void devfreq::end_measurement(void)
+{
+ parse_devfreq_trans_stat(dir_name);
+ gettimeofday(&stamp_after, NULL);
+ process_time_stamps();
+}
+
+double devfreq::power_usage(struct result_bundle *result, struct parameter_bundle *bundle)
+{
+ return 0;
+}
+
+double devfreq::utilization(void)
+{
+ return 0;
+}
+
+void devfreq::fill_freq_utilization(unsigned int idx, char *buf)
+{
+ buf[0] = 0;
+
+ if (idx < dstates.size() && dstates[idx]) {
+ struct frequency *state = dstates[idx];
+ sprintf(buf, " %5.1f%% ", percentage(1.0 * state->time_after / sample_time));
+ }
+}
+
+void devfreq::fill_freq_name(unsigned int idx, char *buf)
+{
+ buf[0] = 0;
+
+ if (idx < dstates.size() && dstates[idx]) {
+ sprintf(buf, "%-15s", dstates[idx]->human_name);
+ }
+}
+
+void start_devfreq_measurement(void)
+{
+ unsigned int i;
+
+ for (i=0; i<all_devfreq.size(); i++)
+ all_devfreq[i]->start_measurement();
+}
+
+void end_devfreq_measurement(void)
+{
+ unsigned int i;
+
+ for (i=0; i<all_devfreq.size(); i++)
+ all_devfreq[i]->end_measurement();
+}
+
+static void devfreq_dev_callback(const char *d_name)
+{
+ devfreq *df = new(std::nothrow) class devfreq(d_name);
+ if (df)
+ all_devfreq.push_back(df);
+}
+
+void create_all_devfreq_devices(void)
+{
+ DIR *dir;
+ std::string p = "/sys/class/devfreq/";
+ dir = opendir(p.c_str());
+ if (dir == NULL) {
+ fprintf(stderr, "Devfreq not enabled\n");
+ is_enabled = false;
+ return;
+ }
+
+ callback fn = &devfreq_dev_callback;
+ process_directory(p.c_str(), fn);
+}
+
+void initialize_devfreq(void)
+{
+ if (is_enabled)
+ create_tab("Device Freq stats", _("Device Freq stats"));
+}
+
+void display_devfreq_devices(void)
+{
+ unsigned int i, j;
+ WINDOW *win;
+ char fline[1024];
+ char buf[128];
+
+ win = get_ncurses_win("Device Freq stats");
+ if (!win)
+ return;
+
+ wclear(win);
+ wmove(win, 2,0);
+
+ if (!is_enabled) {
+ wprintw(win, _(" Devfreq is not enabled"));
+ return;
+ }
+
+ if (!all_devfreq.size()) {
+ wprintw(win, _(" No devfreq devices available"));
+ return;
+ }
+
+ for (i=0; i<all_devfreq.size(); i++) {
+
+ class devfreq *df = all_devfreq[i];
+ wprintw(win, "\n%s\n", df->device_name());
+
+ for(j=0; j < df->dstates.size(); j++) {
+ memset(fline, 0, sizeof(fline));
+ strcpy(fline, "\t");
+ df->fill_freq_name(j, buf);
+ strcat(fline, buf);
+ df->fill_freq_utilization(j, buf);
+ strcat(fline, buf);
+ strcat(fline, "\n");
+ wprintw(win, fline);
+ }
+ wprintw(win, "\n");
+ }
+}
+
+void report_devfreq_devices(void)
+{
+ if (!is_enabled) {
+ return;
+ }
+
+/* todo: adapt to new report format */
+#if 0
+ char buffer[512];
+ unsigned int i, j;
+
+ report.begin_section(SECTION_DEVFREQ);
+ report.add_header("Device Frequency Report");
+
+ report.begin_table(TABLE_WIDE);
+ if (!all_devfreq.size()) {
+ report.begin_row();
+ report.add(" No devfreq devices available");
+ return;
+ }
+
+ for (i = 0; i < all_devfreq.size(); i++) {
+ buffer[0] = 0;
+ class devfreq *df = all_devfreq[i];
+
+ report.begin_row();
+ report.begin_cell(CELL_CPU_PSTATE_HEADER);
+ report.addf("%s", df->device_name());
+
+ for (j = 0; j < df->dstates.size(); j++) {
+ report.begin_row();
+ report.begin_cell(CELL_CPU_STATE_VALUE);
+ df->fill_freq_name(j, buffer);
+ report.add(buffer);
+ report.begin_cell(CELL_CPU_STATE_VALUE);
+ df->fill_freq_utilization(j, buffer);
+ report.add(buffer);
+ }
+ }
+#endif
+
+}
+
+void clear_all_devfreq()
+{
+ unsigned int i, j;
+
+ for (i=0; i < all_devfreq.size(); i++) {
+ class devfreq *df = all_devfreq[i];
+
+ for(j=0; j < df->dstates.size(); j++)
+ delete df->dstates[j];
+
+ df->dstates.resize(0);
+ delete df;
+ }
+ all_devfreq.clear();
+}
diff --git a/src/devices/devfreq.h b/src/devices/devfreq.h
new file mode 100644
index 0000000..8ab5705
--- /dev/null
+++ b/src/devices/devfreq.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012, Linaro
+ *
+ * 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:
+ * Rajagopal Venkat <rajagopal.venkat(a)linaro.org>
+ */
+#ifndef _INCLUDE_GUARD_DEVFREQ_H
+#define _INCLUDE_GUARD_DEVFREQ_H
+
+#include "device.h"
+#include "../parameters/parameters.h"
+
+struct frequency;
+
+class devfreq: public device {
+ char dir_name[4096];
+ struct timeval stamp_before, stamp_after;
+ double sample_time;
+
+ uint64_t parse_freq_time(char *ptr);
+ void add_devfreq_freq_state(uint64_t freq, uint64_t time);
+ void update_devfreq_freq_state(uint64_t freq, uint64_t time);
+ void parse_devfreq_trans_stat(char *dname);
+ void process_time_stamps();
+
+public:
+
+ vector<struct frequency *> dstates;
+
+ devfreq(const char *c);
+ void fill_freq_utilization(unsigned int idx, char *buf);
+ void fill_freq_name(unsigned int idx, char *buf);
+
+ virtual void start_measurement(void);
+ virtual void end_measurement(void);
+
+ virtual double utilization(void); /* percentage */
+
+ virtual const char * class_name(void) { return "devfreq";};
+
+ virtual const char * device_name(void) { return dir_name;};
+ virtual const char * human_name(void) { return "devfreq";};
+ virtual double power_usage(struct result_bundle *result, struct parameter_bundle *bundle);
+ virtual const char * util_units(void) { return " rpm"; };
+ virtual int power_valid(void) { return 0; /*utilization_power_valid(r_index);*/};
+ virtual int grouping_prio(void) { return 1; };
+};
+
+extern void create_all_devfreq_devices(void);
+extern void clear_all_devfreq(void);
+extern void display_devfreq_devices(void);
+extern void report_devfreq_devices(void);
+extern void initialize_devfreq(void);
+extern void start_devfreq_measurement(void);
+extern void end_devfreq_measurement(void);
+
+#endif
diff --git a/src/main.cpp b/src/main.cpp
index cf4e547..d33eaed 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -48,6 +48,7 @@
#include "devices/device.h"
+#include "devices/devfreq.h"
#include "devices/usb.h"
#include "devices/ahci.h"
#include "measurement/measurement.h"
@@ -194,6 +195,7 @@ void one_measurement(int seconds, char *workload)
create_all_usb_devices();
start_power_measurement();
devices_start_measurement();
+ start_devfreq_measurement();
start_process_measurement();
start_cpu_measurement();
@@ -206,6 +208,7 @@ void one_measurement(int seconds, char *workload)
end_cpu_measurement();
end_process_measurement();
collect_open_devices();
+ end_devfreq_measurement();
devices_end_measurement();
end_power_measurement();
@@ -233,6 +236,9 @@ void one_measurement(int seconds, char *workload)
report_show_open_devices();
report_devices();
+ display_devfreq_devices();
+ report_devfreq_devices();
+
ahci_create_device_stats_table();
store_results(measurement_time);
end_cpu_data();
@@ -344,6 +350,7 @@ static void powertop_init(void)
enumerate_cpus();
create_all_devices();
+ create_all_devfreq_devices();
detect_power_meters();
register_parameter("base power", 100, 0.5);
@@ -457,6 +464,7 @@ int main(int argc, char **argv)
exit(0);
}
init_display();
+ initialize_devfreq();
initialize_tuning();
/* first one is short to not let the user wait too long */
one_measurement(1, NULL);
@@ -491,6 +499,7 @@ int main(int argc, char **argv)
clean_open_devices();
clear_all_devices();
+ clear_all_devfreq();
clear_all_cpus();
return 0;
diff --git a/src/report/report-maker.h b/src/report/report-maker.h
index 423568a..bda4cef 100644
--- a/src/report/report-maker.h
+++ b/src/report/report-maker.h
@@ -89,6 +89,7 @@ enum section_type {
SECTION_SYSINFO,
SECTION_CPUIDLE,
SECTION_CPUFREQ,
+ SECTION_DEVFREQ,
SECTION_DEVPOWER,
SECTION_SOFTWARE,
SECTION_SUMMARY,
--
1.8.3.2
7 years, 8 months
[PATCH 0/1] confirm USB autosuspend support before adding as tunable
by Nanley Chery
Make sure that a USB device supports autosuspend before we add it to
the list of tunables. This problem was discovered downstream in the
Debian bug 664455. If the device does not support autosuspend, its
settings cannot be toggled.
The algorithm used to determine autosuspend susport is the same one
found in the usb-pm-tools program. A USB device is added if every one
of its interfaces supports autosuspend.
Nanley Chery (1):
tunables: check usb autosuspend support before add
src/tuning/tuningusb.cpp | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
--
2.0.4
7 years, 8 months
[PATCH 01/14] configure: use vertical lists
by Sami Kerola
Horizontal lists has downside of being managed as a single entry in
version control, which makes commits that add and remove items difficult
to follow. With vertical lists each entry is managed separately, which
is much nicer.
Additionally add project URL to autoconfig init, and pretty print macro
expressions to have indentation, and bracing that follows more or less in
K&R style.
Signed-off-by: Sami Kerola <kerolasa(a)iki.fi>
---
configure.ac | 82 +++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 67 insertions(+), 15 deletions(-)
diff --git a/configure.ac b/configure.ac
index 0b02ad2..b41cfb3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,15 +2,21 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.68])
-AC_INIT([powertop], [2.6.1], [powertop(a)lists.01.org])
-AM_INIT_AUTOMAKE([-Wall foreign ])
+AC_INIT([powertop], [2.6.1], [powertop(a)lists.01.org], [], [https://01.org/powertop])
+AM_INIT_AUTOMAKE([-Wall foreign])
AC_LANG([C++])
-AC_CONFIG_FILES([Makefile src/Makefile traceevent/Makefile po/Makefile.in doc/Makefile])
+AC_CONFIG_FILES([
+ Makefile
+ src/Makefile
+ traceevent/Makefile
+ po/Makefile.in
+ doc/Makefile
+])
AC_CONFIG_SRCDIR([src/main.cpp])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
GETTEXT_PACKAGE=powertop
-AC_SUBST(GETTEXT_PACKAGE)
+AC_SUBST([GETTEXT_PACKAGE])
AM_SILENT_RULES([yes])
AM_GNU_GETTEXT([external])
AM_GNU_GETTEXT_VERSION([0.18])
@@ -26,7 +32,23 @@ AM_PROG_CC_C_O
# Checks for libraries.
# Checks for header files.
-AC_CHECK_HEADERS([fcntl.h libintl.h limits.h locale.h malloc.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/statfs.h sys/time.h termios.h unistd.h ncurses.h])
+AC_CHECK_HEADERS([ \
+ fcntl.h \
+ libintl.h \
+ limits.h \
+ locale.h \
+ malloc.h \
+ ncurses.h \
+ stdint.h \
+ stdlib.h \
+ string.h \
+ sys/ioctl.h \
+ sys/socket.h \
+ sys/statfs.h \
+ sys/time.h \
+ termios.h \
+ unistd.h \
+])
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL
@@ -44,20 +66,46 @@ AC_FUNC_MALLOC
AC_FUNC_MMAP
AC_FUNC_REALLOC
AC_FUNC_STRTOD
-AC_CHECK_FUNCS([fdatasync getpagesize gettimeofday memmove memset mkdir munmap pow realpath regcomp select setlocale socket sqrt strcasecmp strchr strdup strerror strncasecmp strstr strtoul strtoull])
+AC_CHECK_FUNCS([ \
+ fdatasync \
+ getpagesize \
+ gettimeofday \
+ memmove \
+ memset \
+ mkdir \
+ munmap \
+ pow \
+ realpath \
+ regcomp \
+ select \
+ setlocale \
+ socket \
+ sqrt \
+ strcasecmp \
+ strchr \
+ strdup \
+ strerror \
+ strncasecmp \
+ strstr \
+ strtoul \
+ strtoull \
+])
-PKG_CHECK_MODULES([NCURSES], [ncursesw ncurses], [LIBS="$LIBS $ncurses_LIBS"],
- AC_SEARCH_LIBS([delwin], [ncursesw ncurses], [], AC_MSG_ERROR([ncurses is required but was not found]), []))
+PKG_CHECK_MODULES([NCURSES], [ncursesw ncurses], [LIBS="$LIBS $ncurses_LIBS"], [
+ AC_SEARCH_LIBS([delwin], [ncursesw ncurses], [], [
+ AC_MSG_ERROR([ncurses is required but was not found])
+ ], [])
+])
has_libpci=0
-PKG_CHECK_MODULES([PCIUTILS], [libpci],[has_libpci=1],[
- AC_SEARCH_LIBS([pci_get_dev], [pci],[has_libpci=1], [has_libpci=0] )])
+PKG_CHECK_MODULES([PCIUTILS], [libpci],[has_libpci=1], [
+ AC_SEARCH_LIBS([pci_get_dev], [pci],[has_libpci=1], [has_libpci=0])
+])
has_libnl_ver=0
-# libnl-2 provides only libnl-2.0.pc file, so we check for separate libnl-genl-3.0.pc
-# pkg-config file just for libnl-3.0 case.
-#
+dnl libnl-2 provides only libnl-2.0.pc file, so we check for separate
+dnl libnl-genl-3.0.pc pkg-config file just for libnl-3.0 case.
PKG_CHECK_MODULES([LIBNL], [libnl-3.0 >= 3.0 libnl-genl-3.0 >= 3.0], [has_libnl_ver=3], [
PKG_CHECK_MODULES([LIBNL], [libnl-2.0 >= 2.0], [has_libnl_ver=2], [
PKG_CHECK_MODULES([LIBNL], [libnl-1], [has_libnl_ver=1], [has_libnl_ver=0])])])
@@ -78,7 +126,11 @@ if (test "$has_libpci" -eq 0); then
])
fi
-AC_SEARCH_LIBS([pthread_create], [pthread], [], AC_MSG_ERROR([libpthread is required but was not found]), [])
-AC_SEARCH_LIBS([inet_aton], [resolv], [], AC_MSG_ERROR([libresolv is required but was not found]), [])
+AC_SEARCH_LIBS([pthread_create], [pthread], [], [
+ AC_MSG_ERROR([libpthread is required but was not found])
+], [])
+AC_SEARCH_LIBS([inet_aton], [resolv], [], [
+ AC_MSG_ERROR([libresolv is required but was not found])
+], [])
AC_OUTPUT
--
2.0.4
7 years, 8 months
[Announcement] PowerTOP doesn't do git pull requests
by Alexandra Yates
Dear Contributors,
Thank you very much for the work you do to improve PowerTOP.
In the last few days I've noticed an increasing demand to do git pull
requests from our contributors. However, PowerTOP doesn't do git pull
requests.
PowerTOP handles bug-fixes and development on patches via the mailing
list. We appreciate you submitting your code to the mailing list.
Thank you,
Alexandra.
7 years, 9 months