typedef struct event_info event_info_t;
struct intel_pmu_ctx_s {
- _Bool hw_cache_events;
- _Bool kernel_pmu_events;
- _Bool sw_events;
- char event_list_fn[PATH_MAX];
+ bool hw_cache_events;
+ bool kernel_pmu_events;
+ bool sw_events;
+ char event_list_fn[PATH_MAX];
char **hw_events;
size_t hw_events_count;
struct eventlist *event_list;
DEBUG(PMU_PLUGIN ": software_events : %d", g_ctx.sw_events);
for (size_t i = 0; i < g_ctx.hw_events_count; i++) {
- DEBUG(PMU_PLUGIN ": hardware_events[%zu]: %s", i, g_ctx.hw_events[i]);
+ DEBUG(PMU_PLUGIN ": hardware_events[%" PRIsz "]: %s", i,
+ g_ctx.hw_events[i]);
}
}
return -EINVAL;
}
+ if (g_ctx.hw_events) {
+ ERROR(PMU_PLUGIN ": Duplicate config for HardwareEvents.");
+ return -EINVAL;
+ }
+
g_ctx.hw_events = calloc(ci->values_num, sizeof(char *));
if (g_ctx.hw_events == NULL) {
ERROR(PMU_PLUGIN ": Failed to allocate hw events.");
return 0;
}
-static void pmu_submit_counter(int cpu, char *event, counter_t value) {
+static void pmu_submit_counter(int cpu, char *event, counter_t value,
+ meta_data_t *meta) {
value_list_t vl = VALUE_LIST_INIT;
vl.values = &(value_t){.counter = value};
if (cpu == -1) {
snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "all");
} else {
+ vl.meta = meta;
snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%d", cpu);
}
sstrncpy(vl.type, "counter", sizeof(vl.type));
plugin_dispatch_values(&vl);
}
+meta_data_t *pmu_meta_data_create(const struct efd *efd) {
+ meta_data_t *meta = NULL;
+
+ /* create meta data only if value was scaled */
+ if (efd->val[1] == efd->val[2] || !efd->val[2]) {
+ return NULL;
+ }
+
+ meta = meta_data_create();
+ if (meta == NULL) {
+ ERROR(PMU_PLUGIN ": meta_data_create failed.");
+ return NULL;
+ }
+
+ meta_data_add_unsigned_int(meta, "intel_pmu:raw_count", efd->val[0]);
+ meta_data_add_unsigned_int(meta, "intel_pmu:time_enabled", efd->val[1]);
+ meta_data_add_unsigned_int(meta, "intel_pmu:time_running", efd->val[2]);
+
+ return meta;
+}
+
static void pmu_dispatch_data(void) {
struct event *e;
event_enabled++;
+ /* If there are more events than counters, the kernel uses time
+ * multiplexing. With multiplexing, at the end of the run,
+ * the counter is scaled basing on total time enabled vs time running.
+ * final_count = raw_count * time_enabled/time_running
+ */
uint64_t value = event_scaled_value(e, i);
all_value += value;
+ /* get meta data with information about scaling */
+ meta_data_t *meta = pmu_meta_data_create(&e->efd[i]);
+
/* dispatch per CPU value */
- pmu_submit_counter(i, e->event, value);
+ pmu_submit_counter(i, e->event, value, meta);
+
+ meta_data_destroy(meta);
}
if (event_enabled > 0) {
DEBUG(PMU_PLUGIN ": %-20s %'10lu", e->event, all_value);
/* dispatch all CPU value */
- pmu_submit_counter(-1, e->event, all_value);
+ pmu_submit_counter(-1, e->event, all_value, NULL);
}
}
}
char *s, *tmp;
for (s = strtok_r(events, ",", &tmp); s; s = strtok_r(NULL, ",", &tmp)) {
- /* Multiple events parsed in one entry */
- if (group_events_count == 1) {
- /* Mark previously added event as group leader */
- el->eventlist_last->group_leader = 1;
- }
-
/* Allocate memory for event struct that contains array of efd structs
for all cores */
struct event *e =
return -ENOMEM;
}
- if (resolve_event(s, &e->attr) == 0) {
- e->next = NULL;
- if (!el->eventlist)
- el->eventlist = e;
- if (el->eventlist_last)
- el->eventlist_last->next = e;
- el->eventlist_last = e;
- e->event = strdup(s);
- } else {
- DEBUG(PMU_PLUGIN ": Cannot resolve %s", s);
+ if (resolve_event(s, &e->attr) != 0) {
+ WARNING(PMU_PLUGIN ": Cannot resolve %s", s);
sfree(e);
+ continue;
+ }
+
+ /* Multiple events parsed in one entry */
+ if (group_events_count == 1) {
+ /* Mark previously added event as group leader */
+ el->eventlist_last->group_leader = 1;
}
+ e->next = NULL;
+ if (!el->eventlist)
+ el->eventlist = e;
+ if (el->eventlist_last)
+ el->eventlist_last->next = e;
+ el->eventlist_last = e;
+ e->event = strdup(s);
+
group_events_count++;
}
sfree(g_ctx.hw_events);
g_ctx.hw_events_count = 0;
-
return ret;
}