>
>> add window to show frequency stats for devfreq devices
>>
>> Signed-off-by: Rajagopal Venkat <rajagopal.ven...@gmail.com>
>> Signed-off-by: Sanjay Singh Rawat <sanjay.ra...@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.ven...@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.ven...@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
>>
>> _______________________________________________
>> PowerTop mailing list
>> power...@lists.01.org
>> https://lists.01.org/mailman/listinfo/powertop
>>
>
> Hi Sanjay,
>
> It would be better that Device Frequency Stats appears only when
> /sys/class/devfewq is present on the system.  That will simplify code
> execution at runtime and remove the blank window with "No devfreq devices
> available".
>
> Thank you,
> Alexandra.
> _______________________________________________
> PowerTop mailing list
> power...@lists.01.org
> https://lists.01.org/mailman/listinfo/powertop
>

I'm testing the code doesn't break Intel support.  Please Sergey
Senozhatsky and any one else in the community can you help me test this
patch on ARM platforms.

Thank you,
Alexandra.

_______________________________________________
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev

Reply via email to