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 "); + 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]); } else { idx = intel_x86_attr2mod(this, pidx, attr_idx); info->name = atdesc[idx].name; -- 1.9.3 ------------------------------------------------------------------------------ _______________________________________________ perfmon2-devel mailing list perfmon2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/perfmon2-devel