Hello,

Alexandra, sorry, no ARM devices around at this moment.

        -ss

On (09/29/14 16:04), Alexandra Yates wrote:
> >
> >> 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