Hi,

Sorry for the delay.

Several remarks on this patch:
- showevtinfo is a generic program that is meant to run even on non
Linux systems, it cannot contain Linux specific knowledge

The rest is inlined below.


On Mon, Sep 21, 2015 at 9:14 PM, Hemant Kumar <hem...@linux.vnet.ibm.com> wrote:
> Read the scale and unit values from the
> sysfs 
> (/sys/bus/event_source/devices/uncore_imc_*/events/cas_count_{read,write}.{scale,
> unit}) for intel sandy-bridge uncore memory controllers' read and write
> counters. These values are needed to scale the accumulated values to their
> respective units.
>
> Signed-off-by: Hemant Kumar <hem...@linux.vnet.ibm.com>
> ---
>  examples/showevtinfo.c   |   5 ++-
>  include/perfmon/pfmlib.h |   8 ++++
>  lib/pfmlib_intel_x86.c   | 103 
> +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 115 insertions(+), 1 deletion(-)
>
> diff --git a/examples/showevtinfo.c b/examples/showevtinfo.c
> index 45763ec..d182150 100644
> --- a/examples/showevtinfo.c
> +++ b/examples/showevtinfo.c
> @@ -460,13 +460,16 @@ show_event_info(pfm_event_info_t *info)
>
>                         print_attr_flags(&ainfo);
>
> +                       printf(": %lf ", ainfo.scale);
> +                       if (ainfo.unit == PFM_UNIT_MIB)
> +                               printf(": MiB ");
> +
Why do you need to know it is MiB. The kernel exports everything you
need. The perf tool has
 no knowledge of MiB. The unit is just a string which you can print.

>                         putchar(':');
>
>                         if (ainfo.equiv)
>                                 printf(" Alias to %s", ainfo.equiv);
>                         else
>                                 printf(" %s", ainfo.desc);
> -
>                         putchar('\n');
>                         um++;
>                         break;
> diff --git a/include/perfmon/pfmlib.h b/include/perfmon/pfmlib.h
> index 2fb4744..ceea202 100644
> --- a/include/perfmon/pfmlib.h
> +++ b/include/perfmon/pfmlib.h
> @@ -428,6 +428,8 @@ typedef struct {
>                 int             dfl_bool;       /* default boolean value */
>                 int             dfl_int;        /* default integer value */
>         } SWIG_NAME(defaults);
> +       double scale;
> +       int unit;
>  } pfm_event_attr_info_t;
>
>  /*
> @@ -515,6 +517,12 @@ extern pfm_err_t pfm_get_event_encoding(const char *str, 
> int dfl_plm, char **fst
>  #define PFM_ERR_TOOMANY                -11     /* too many parameters */
>  #define PFM_ERR_TOOSMALL       -12     /* parameter is too small */
>
> +typedef enum {
> +       PFM_UNIT_UNKNOWN=0,     /* unknown units type */
> +       PFM_UNIT_MIB,           /* The unit is MiB */
> +       PFM_UNIT_MAX
> +} pfm_attr_unit_t;
> +
>  /*
>   * event, attribute iterators
>   * must be used because no guarante indexes are contiguous
> diff --git a/lib/pfmlib_intel_x86.c b/lib/pfmlib_intel_x86.c
> index 81a2258..d5b8d62 100644
> --- a/lib/pfmlib_intel_x86.c
> +++ b/lib/pfmlib_intel_x86.c
> @@ -894,6 +894,107 @@ skip_dfl:
>         return error ? PFM_ERR_INVAL : PFM_SUCCESS;
>  }
>
> +#define MAX_LEN 20
> +
> +static char *
> +get_attr_file_name(void *this, int pidx, int idx, intel_x86_umask_t umask)
> +{
> +       const intel_x86_entry_t *pe = this_pe(this);
> +       char *attr_file = NULL;
> +
> +       if (!strcmp(pe[pidx].name, "UNC_M_CAS_COUNT")) {
> +               attr_file = calloc(MAX_LEN, (sizeof (char)));
> +               if (!attr_file)
> +                       return NULL;
> +               strcpy(attr_file, "cas_count_");
> +       }
> +       if (attr_file) {
> +               if (!strcmp(pe[pidx].umasks[idx].uname, "RD"))
> +                       strcat(attr_file, "read");
> +               else if (!strcmp(pe[pidx].umasks[idx].uname, "WR"))
> +                       strcat(attr_file, "write");
> +       }
> +
> +       return attr_file;
> +}
> +
> +#define PATH_MAX 512
> +
> +static double
> +get_attr_scale(void *this, int pidx, int idx, intel_x86_umask_t umask)
> +{
> +       char scale_path[PATH_MAX];
> +       FILE *fp;
> +       size_t len = 0;
> +       char *line = NULL, *attr_name = NULL;
> +       ssize_t ret;
> +       double scale_value;
> +
> +       attr_name = get_attr_file_name(this, pidx, idx, umask);
> +       if (!attr_name)
> +               goto end;
> +
> +       sprintf(scale_path, 
> "/sys/bus/event_source/devices/%s/events/%s.scale",
> +               (((pfmlib_pmu_t *)this)->perf_name), attr_name);
> +       if (attr_name != NULL)
> +               free(attr_name);
> +
> +       fp = fopen(scale_path, "r");
> +       if (!fp)
> +               goto end;
> +
> +       ret = getline(&line, &len, fp);
> +       if (ret > 0) {
> +               /* Remove the new line from the end of the string here */
> +               if (line[strlen(line) - 1] == '\n')
> +                       line[strlen(line) - 1] = '\0';
> +               scale_value = atof(line);
> +               free(line);
> +               fclose(fp);
> +               return scale_value;
> +       }
> +end:
> +       return 0.0;
> +}
> +
> +static int
> +get_attr_unit(void *this, int pidx, int idx, intel_x86_umask_t umask)
> +{
> +       char unit_path[PATH_MAX];
> +       FILE *fp;
> +       size_t len = 0;
> +       char *line = NULL, *unit_file = NULL;
> +       ssize_t ret;
> +       int unit;
> +
> +       unit_file = get_attr_file_name(this, pidx, idx, umask);
> +       if (!unit_file)
> +               goto end;
> +
> +       sprintf(unit_path, "/sys/bus/event_source/devices/%s/events/%s.unit",
> +               (((pfmlib_pmu_t *)this)->perf_name), unit_file);
> +       if (unit_file != NULL)
> +               free(unit_file);
> +
> +       fp = fopen(unit_path, "r");
> +       if (!fp)
> +               goto end;
> +
> +       ret = getline(&line, &len, fp);
> +       if (ret > 0) {
> +               /* Remove the new line from the end of the string here */
> +               if (line[strlen(line) - 1] == '\n')
> +                       line[strlen(line) - 1] = '\0';
> +               if (!strcmp(line, "MiB"))
> +                       unit = PFM_UNIT_MIB;
> +               free(line);
> +               fclose(fp);
> +               return unit;
> +       }
> +end:
> +       return PFM_UNIT_UNKNOWN;
> +}
> +
>  int
>  pfm_intel_x86_get_event_attr_info(void *this, int pidx, int attr_idx, 
> pfm_event_attr_info_t *info)
>  {
> @@ -915,6 +1016,8 @@ pfm_intel_x86_get_event_attr_info(void *this, int pidx, 
> int attr_idx, pfm_event_
>                 info->type = PFM_ATTR_UMASK;
>                 info->is_dfl = intel_x86_uflag(this, pidx, idx, 
> INTEL_X86_DFL);
>                 info->is_precise = intel_x86_uflag(this, pidx, idx, 
> INTEL_X86_PEBS);
> +               info->scale = get_attr_scale(this, pidx, idx, 
> pe[pidx].umasks[idx]);
> +               info->unit = get_attr_unit(this, pidx, idx, 
> pe[pidx].umasks[idx]);

I think we could add those two fields to the info struct. However,
that would need to come from the perf_event layer
and not form the generic layer like you are doing now. In other words,
those two info fields need to be filled out in an
OS specific callback.

>         } else {
>                 idx = intel_x86_attr2mod(this, pidx, attr_idx);
>                 info->name = atdesc[idx].name;
> --
> 1.9.3
>

------------------------------------------------------------------------------
Monitor Your Dynamic Infrastructure at Any Scale With Datadog!
Get real-time metrics from all of your servers, apps and tools
in one place.
SourceForge users - Click here to start your Free Trial of Datadog now!
http://pubads.g.doubleclick.net/gampad/clk?id=241902991&iu=/4140
_______________________________________________
perfmon2-devel mailing list
perfmon2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/perfmon2-devel

Reply via email to