Read the scale and unit values from the
sysfs
(/sys/bus/event_source/devices/uncore_imc_*/events/cas_count_{read,write}.scale)
for intel sandy-bridge uncore memory controllers' read and write
counters. These values are needed to scale the counter values.
This patch also adds a function pfm_get_os_event_scale() to the libpfm
API so that tools using perfmon/libpfm4 library can get the value of the
scale similar to how pfm_get_os_event_encoding() gets the event
encoding.
Signed-off-by: Hemant Kumar <[email protected]>
---
include/perfmon/pfmlib.h | 6 ++++
lib/pfmlib_common.c | 31 ++++++++++++++++++++
lib/pfmlib_intel_x86.c | 25 ++++++++++++++++
lib/pfmlib_perf_event.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/pfmlib_priv.h | 1 +
5 files changed, 138 insertions(+)
diff --git a/include/perfmon/pfmlib.h b/include/perfmon/pfmlib.h
index 2fb4744..543a8b2 100644
--- a/include/perfmon/pfmlib.h
+++ b/include/perfmon/pfmlib.h
@@ -412,6 +412,7 @@ typedef struct {
const char *name; /* attribute symbolic name */
const char *desc; /* attribute description */
const char *equiv; /* attribute is equivalent to */
+ const char *uname;
size_t size; /* struct sizeof */
uint64_t code; /* attribute code */
pfm_attr_t type; /* attribute type */
@@ -484,6 +485,11 @@ extern pfm_err_t pfm_get_event_info(int idx, pfm_os_t os,
pfm_event_info_t *outp
extern pfm_err_t pfm_get_os_event_encoding(const char *str, int dfl_plm,
pfm_os_t os, void *args);
/*
+ * event scale API
+ */
+extern pfm_err_t pfm_get_os_event_scale(const char *str, int dfl_plm, pfm_os_t
os, void *args);
+
+/*
* attribute API
*/
extern pfm_err_t pfm_get_event_attr_info(int eidx, int aidx, pfm_os_t os,
pfm_event_attr_info_t *output);
diff --git a/lib/pfmlib_common.c b/lib/pfmlib_common.c
index a6a364e..a108ada 100644
--- a/lib/pfmlib_common.c
+++ b/lib/pfmlib_common.c
@@ -1350,10 +1350,34 @@ pfm_get_event_next(int idx)
}
int
+pfm_get_os_event_scale(const char *str, int dfl_plm, pfm_os_t uos, void *args)
+{
+ pfmlib_os_t *os;
+
+ if (PFMLIB_INITIALIZED() == 0)
+ return PFM_ERR_NOINIT;
+
+ if (dfl_plm & ~(PFM_PLM_ALL))
+ return PFM_ERR_INVAL;
+
+ os = pfmlib_find_os(uos);
+ if (!os)
+ return PFM_ERR_NOTSUPP;
+
+ return os->get_scale(os, str, dfl_plm, args);
+}
+
+int
pfm_get_os_event_encoding(const char *str, int dfl_plm, pfm_os_t uos, void
*args)
{
pfmlib_os_t *os;
+ FILE *fp;
+
+ fp = fopen("/home/hemant/tmp.txt", "w");
+ if (!fp)
+ return PFM_ERR_NOINIT;
+ fprintf(fp, "os->name : %s\n", os->name);
if (PFMLIB_INITIALIZED() == 0)
return PFM_ERR_NOINIT;
@@ -1981,10 +2005,17 @@ pfmlib_raw_pmu_detect(void *this)
return PFM_SUCCESS;
}
+static int
+pfmlib_raw_pmu_get_scale(void *this, const char *str, int dfl_plm, void *data)
+{
+ return PFM_ERR_NOTSUPP;
+}
+
static pfmlib_os_t pfmlib_os_none= {
.name = "No OS (raw PMU)",
.id = PFM_OS_NONE,
.flags = PFMLIB_OS_FL_ACTIVATED,
.encode = pfmlib_raw_pmu_encode,
.detect = pfmlib_raw_pmu_detect,
+ .get_scale = pfmlib_raw_pmu_get_scale,
};
diff --git a/lib/pfmlib_intel_x86.c b/lib/pfmlib_intel_x86.c
index 81a2258..cb76cd1 100644
--- a/lib/pfmlib_intel_x86.c
+++ b/lib/pfmlib_intel_x86.c
@@ -894,6 +894,30 @@ skip_dfl:
return error ? PFM_ERR_INVAL : PFM_SUCCESS;
}
+#define MAX_LEN 100
+
+static char *
+get_attr_uname(void *this, int pidx, int idx)
+{
+ const intel_x86_entry_t *pe = this_pe(this);
+ char *text = NULL;
+
+ if (!strcmp(pe[pidx].name, "UNC_M_CAS_COUNT")) {
+ text = calloc(MAX_LEN, sizeof(char));
+ if (!text)
+ return NULL;
+ strcpy(text, "cas_count_");
+ }
+ if (text) {
+ if (!strcmp(pe[pidx].umasks[idx].uname, "RD"))
+ strcat(text, "read");
+ else if(!strcmp(pe[pidx].umasks[idx].uname, "WR"))
+ strcat(text, "write");
+ }
+
+ return text;
+}
+
int
pfm_intel_x86_get_event_attr_info(void *this, int pidx, int attr_idx,
pfm_event_attr_info_t *info)
{
@@ -906,6 +930,7 @@ pfm_intel_x86_get_event_attr_info(void *this, int pidx, int
attr_idx, pfm_event_
idx = intel_x86_attr2umask(this, pidx, attr_idx);
info->name = pe[pidx].umasks[idx].uname;
info->desc = pe[pidx].umasks[idx].udesc;
+ info->uname = get_attr_uname(this, pidx, idx);
info->equiv= pe[pidx].umasks[idx].uequiv;
info->code = pe[pidx].umasks[idx].ucode;
diff --git a/lib/pfmlib_perf_event.c b/lib/pfmlib_perf_event.c
index 8618d60..7f191f0 100644
--- a/lib/pfmlib_perf_event.c
+++ b/lib/pfmlib_perf_event.c
@@ -73,6 +73,79 @@ static const pfmlib_attr_desc_t perf_event_ext_mods[]={
PFM_ATTR_NULL /* end-marker to avoid exporting number of entries */
};
+static double
+get_perf_scale(const char *pmu, const char *event)
+{
+ char scale_path[PATH_MAX];
+
+ FILE *fp;
+ size_t len = 0;
+ char *line = NULL;
+ ssize_t ret;
+ double scale;
+
+ sprintf(scale_path, "/sys/bus/event_source/devices/%s/events/%s.scale",
+ pmu, event);
+
+ 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 = atof(line);
+ free(line);
+ fclose(fp);
+ return scale;
+ }
+ if (fp)
+ fclose(fp);
+end:
+ return 1.0;
+}
+
+static int
+pfmlib_perf_event_scale(void *this, const char *str, int dfl_plm, void *data)
+{
+ pfmlib_os_t *os = this;
+ pfmlib_pmu_t *pmu;
+ pfmlib_event_desc_t e;
+ pfm_event_attr_info_t ainfo;
+ int ret;
+ double *scale = data;
+
+ memset(&e, 0, sizeof(e));
+
+ e.osid = os->id;
+ e.dfl_plm = dfl_plm;
+
+ /* after this call, need to call pfmlib_release_event() */
+ ret = pfmlib_parse_event(str, &e);
+ if (ret != PFM_SUCCESS)
+ return ret;
+
+ pmu = e.pmu;
+
+ fprintf(stderr, "event name : %s\n", str);
+ fprintf(stderr, "PMU name : %s\n", (e.pmu)->perf_name);
+ fprintf(stderr, "attribute name : %d\n", (e.attrs)->id);
+
+ /* need to free up ainfo.uname */
+ ret = pmu->get_event_attr_info(pmu, e.event, (e.attrs)->id, &ainfo);
+ if (ainfo.uname) {
+ fprintf(stderr, "UNAME : %s\n", ainfo.uname);
+ *scale = get_perf_scale((e.pmu)->perf_name, ainfo.uname);
+ fprintf(stderr, "scale : %f\n", *scale);
+ }
+
+ pfmlib_release_event(&e);
+ return ret;
+}
+
static int
pfmlib_perf_event_encode(void *this, const char *str, int dfl_plm, void *data)
{
@@ -432,6 +505,7 @@ pfmlib_os_t pfmlib_os_perf={
.get_os_attr_info = perf_get_os_attr_info,
.get_os_nattrs = perf_get_os_nattrs,
.encode = pfmlib_perf_event_encode,
+ .get_scale = pfmlib_perf_event_scale,
};
pfmlib_os_t pfmlib_os_perf_ext={
@@ -442,6 +516,7 @@ pfmlib_os_t pfmlib_os_perf_ext={
.get_os_attr_info = perf_get_os_attr_info,
.get_os_nattrs = perf_get_os_nattrs,
.encode = pfmlib_perf_event_encode,
+ .get_scale = pfmlib_perf_event_scale,
};
diff --git a/lib/pfmlib_priv.h b/lib/pfmlib_priv.h
index b5e2d0c..cc6307a 100644
--- a/lib/pfmlib_priv.h
+++ b/lib/pfmlib_priv.h
@@ -152,6 +152,7 @@ typedef struct {
int (*get_os_attr_info)(void *this,
pfmlib_event_desc_t *e);
int (*get_os_nattrs)(void *this,
pfmlib_event_desc_t *e);
int (*encode)(void *this, const char *str,
int dfl_plm, void *args);
+ int (*get_scale)(void *this, const char
*str, int dfl_plm, void *args);
} pfmlib_os_t;
#define PFMLIB_OS_FL_ACTIVATED 0x1 /* OS layer detected */
--
1.9.3
------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
perfmon2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/perfmon2-devel