File 0008-pmdas-perf-Add-support-for-hv_24x7-nest-events-on-mu.patch of Package pcp.18196
From 2251fbdda3b270fa1b1c5f59c83d1e156ff8ea36 Mon Sep 17 00:00:00 2001
From: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
Date: Wed, 16 Oct 2019 16:09:04 +0530
Subject: [PATCH] pmdas/perf: Add support for hv_24x7 nest events on mutlinode
system
Patch-mainline: 5.0.1
Git-commit: 2251fbdda3b270fa1b1c5f59c83d1e156ff8ea36
For dynamic perf events like hv_24x7 nest event, `chip_id` is also an
event parameter. So for multinode systems, same event can be defined for
different nodes(/chips) in the system.
Add support for hv_24x7 nest events in mutinode systems.
Eg:
---> perfevent.conf
[dynamic]
hv_24x7.PM_PB_CYC 4 chip:0
hv_24x7.PM_PB_CYC 13 chip:1
hv_24x7.PM_MBA0_CLK_CYC 4 chip:0
hv_24x7.PM_MBA0_CLK_CYC 14 chip:1
# pminfo | grep PM_PB_CYC
perfevent.hwcounters.hv_24x7.PM_PB_CYC_chip_1.dutycycle
perfevent.hwcounters.hv_24x7.PM_PB_CYC_chip_1.value
perfevent.hwcounters.hv_24x7.PM_PB_CYC_chip_0.dutycycle
perfevent.hwcounters.hv_24x7.PM_PB_CYC_chip_0.value
# pmval perfevent.hwcounters.hv_24x7.PM_PB_CYC_chip_0.value
metric: perfevent.hwcounters.hv_24x7.PM_PB_CYC_chip_0.value
host: ####
semantics: cumulative counter (converting to rate)
units: count (converting to count / sec)
samples: all
cpu4
7.805E+06
# pmval perfevent.hwcounters.hv_24x7.PM_PB_CYC_chip_1.value
metric: perfevent.hwcounters.hv_24x7.PM_PB_CYC_chip_1.value
host: ####
semantics: cumulative counter (converting to rate)
units: count (converting to count / sec)
samples: all
cpu13
7.805E+06
7.805E+06
Signed-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
Signed-off-by: Anju T Sudhakar <anju@linux.vnet.ibm.com>
---
src/pmdas/perfevent/parse_events.c | 221 ++++++++++++++++++-----------
1 file changed, 138 insertions(+), 83 deletions(-)
diff --git a/src/pmdas/perfevent/parse_events.c b/src/pmdas/perfevent/parse_events.c
index 1632f09b1f32..27fb37df3fb7 100644
--- a/src/pmdas/perfevent/parse_events.c
+++ b/src/pmdas/perfevent/parse_events.c
@@ -412,89 +412,138 @@ static void cleanup_property_info(struct property_info *pi)
*/
static int parse_event_string(char *buf, struct pmu_event *event,
struct pmu *pmu, struct pmcsetting *dynamicpmc,
- char *pmu_name)
+ char *pmu_name, int *new_events)
{
struct property_info *pi, *head = NULL, *tmp;
- char *start, *ptr, *nptr, **endptr, *str, eventname[BUF_SIZE];
+ char *start, *ptr, *nptr, **endptr, *str, eventname[BUF_SIZE], ev_str[BUF_SIZE], pmc_str[BUF_SIZE], *tmp_buf_str;
struct pmcsetting *pmctmp;
+ int i, ret, sub_ev_cnt = 0;
+ struct pmu_event *sub_event = NULL, *ev_tmp= NULL, *ev_head = NULL;
+
+ pmsprintf(ev_str, sizeof(ev_str), "%s.%s", pmu_name, event->name);
+ for (pmctmp = dynamicpmc; pmctmp; pmctmp = pmctmp->next)
+ if (!strncmp(ev_str, pmctmp->name, strlen(ev_str)))
+ sub_ev_cnt++;
+
+ if (sub_ev_cnt > 1)
+ *new_events = sub_ev_cnt;
+
+ for (i = 0; i < (sub_ev_cnt - 1); i++) {
+ ev_tmp = calloc(1, sizeof(*ev_tmp));
+ if (!ev_tmp) {
+ sub_ev_cnt = 0;
+ break;
+ }
+
+ if (!sub_event) {
+ sub_event = ev_tmp;
+ ev_head = sub_event;
+ event->next = ev_head;
+ sub_event->name = strdup(event->name);
+ } else {
+ sub_event->next = ev_tmp;
+ sub_event = sub_event->next;
+ sub_event->name = strdup(event->name);
+ }
+ }
- start = buf;
-
- while (1) {
- ptr = strchr(start, '=');
- if (!ptr)
- break;
-
- /* Found a property */
- *ptr = '\0';
- ptr++; /* ptr now points to the value */
- pi = calloc(1, sizeof(*pi));
- if (!pi) {
- cleanup_property_info(head);
- return -E_PERFEVENT_REALLOC;
- }
- pi->next = NULL;
-
- pi->name = strdup(start);
- if (!pi->name) {
- free(pi);
- cleanup_property_info(head);
- return -E_PERFEVENT_REALLOC;
- }
-
- pmsprintf(eventname, sizeof(eventname), "%s.%s", pmu_name, event->name);
-
- /* Find next property */
- start = strchr(ptr, ',');
- if (!start) {
- str = buf + strlen(buf) - 1;
- endptr = &str;
- nptr = ptr;
- if ((!strcmp(nptr, "?")) && (!strcmp(pi->name, "chip"))) {
- for (pmctmp = dynamicpmc; pmctmp; pmctmp = pmctmp->next) {
- if (!strncmp(eventname, pmctmp->name, strlen(eventname)))
+ ev_head = event;
+
+ for (i=0; i < sub_ev_cnt; i++) {
+ head = NULL;
+ tmp_buf_str = strdup(buf);
+ start = tmp_buf_str;
+
+ while (1) {
+ ptr = strchr(start, '=');
+ if (!ptr)
+ break;
+
+ /* Found a property */
+ *ptr = '\0';
+ ptr++; /* ptr now points to the value */
+ pi = calloc(1, sizeof(*pi));
+ if (!pi) {
+ cleanup_property_info(head);
+ return -E_PERFEVENT_REALLOC;
+ }
+
+ pi->next = NULL;
+ pi->name = strdup(start);
+ if (!pi->name) {
+ free(pi);
+ cleanup_property_info(head);
+ return -E_PERFEVENT_REALLOC;
+ }
+
+ pmsprintf(eventname, sizeof(eventname), "%s.%s", pmu_name, event->name);
+
+ /* Find next property */
+ start = strchr(ptr, ',');
+ if (!start) {
+ str = buf + strlen(buf) - 1;
+ endptr = &str;
+ nptr = ptr;
+ if ((!strcmp(nptr, "?")) && (!strcmp(pi->name, "chip"))) {
+ for (pmctmp = dynamicpmc; pmctmp; pmctmp = pmctmp->next) {
+ if (!strncmp(eventname, pmctmp->name, strlen(pmctmp->name)))
{
- pi->value = pmctmp->chip;
+ pmsprintf(ev_str, sizeof(ev_str), "%s_chip_%d", event->name,pmctmp->chip);
+ event->name = strdup(ev_str);
+ pmsprintf(pmc_str, sizeof(pmc_str), "%s_chip_%d", pmctmp->name,pmctmp->chip);
+ pmctmp->name = strdup(pmc_str);
+ pi->value = pmctmp->chip;
+ break;
}
+ }
+ } else
+ pi->value = strtoull(nptr, endptr, 16);
+ if (!head) {
+ head = pi;
+ pi = pi->next;
+ } else {
+ tmp->next = pi;
+ tmp = tmp->next;
}
- } else
- pi->value = strtoull(nptr, endptr, 16);
- if (!head) {
- head = pi;
- pi = pi->next;
- } else {
- tmp->next = pi;
- tmp = tmp->next;
- }
- break;
- } else {
- /* We found the next property */
- *start = '\0';
- str = buf + strlen(buf) - 1;
- endptr = &str;
- start++;
- nptr = ptr;
- if ((!strcmp(nptr, "?")) && (!strcmp(pi->name, "chip"))) {
- for (pmctmp = dynamicpmc; pmctmp; pmctmp = pmctmp->next) {
- if (!strncmp(eventname, pmctmp->name, strlen(eventname)))
+ break;
+ } else {
+ /* We found the next property */
+ *start = '\0';
+ str = buf + strlen(buf) - 1;
+ endptr = &str;
+ start++;
+ nptr = ptr;
+ if ((!strcmp(nptr, "?")) && (!strcmp(pi->name, "chip"))) {
+ for (pmctmp = dynamicpmc; pmctmp; pmctmp = pmctmp->next) {
+ if (!strncmp(eventname, pmctmp->name, strlen(pmctmp->name)))
{
- pi->value = pmctmp->chip;
+ pmsprintf(ev_str, sizeof(ev_str), "%s_chip_%d", event->name,pmctmp->chip);
+ event->name = strdup(ev_str);
+ pmsprintf(pmc_str, sizeof(pmc_str), "%s_chip_%d", pmctmp->name,pmctmp->chip);
+ pmctmp->name = strdup(pmc_str);
+ pi->value = pmctmp->chip;
+ break;
}
- }
- } else
- pi->value = strtoul(nptr, endptr, 16);
- }
-
- if (!head) {
- head = pi;
- tmp = head;
- } else {
- tmp->next = pi;
- tmp = tmp->next;
- }
+ }
+ } else
+ pi->value = strtoul(nptr, endptr, 16);
+ }
+ if (!head) {
+ head = pi;
+ tmp = head;
+ } else {
+ tmp->next = pi;
+ tmp = tmp->next;
+ }
+ }
+ ret = fetch_event_config(head, event, pmu);
+ if (ret)
+ return ret;
+
+ event->pmu = pmu;
+ event = event->next;
}
-
- return fetch_event_config(head, event, pmu);
+ return 0;
}
/*
@@ -509,7 +558,7 @@ static int fetch_events(DIR *events_dir, struct pmu_event **events,
struct dirent *dir;
struct pmu_event *ev = NULL, *tmp, *head = NULL;
char event_path[PATH_MAX], *buf;
- int ret = 0;
+ int ret = 0, sub_events, i;
if (!events_dir)
return -1;
@@ -551,21 +600,27 @@ static int fetch_events(DIR *events_dir, struct pmu_event **events,
goto free_buf;
}
- ret = parse_event_string(buf, tmp, pmu, dynamicpmc, pmu_name);
+ ret = parse_event_string(buf, tmp, pmu, dynamicpmc, pmu_name, &sub_events);
if (ret) {
ret = -E_PERFEVENT_RUNTIME;
goto free_buf;
}
- tmp->pmu = pmu;
+ i = 0;
+ do {
+ tmp->pmu = pmu;
+ if (!ev) {
+ ev = tmp;
+ head = ev;
+ } else {
+ ev->next = tmp;
+ ev = ev->next;
+ }
+ tmp = tmp->next;
+ i++;
+ } while(i < sub_events);
- if (!ev) {
- ev = tmp;
- head = ev;
- } else {
- ev->next = tmp;
- ev = ev->next;
- }
+ sub_events = 0;
}
*events = head;
--
2.23.0