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 <[email protected]>
---
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/perfmon2-devel