Replace zu with PRIu64 and llu with new macro, PRIsz, which will make it easier to...
[collectd.git] / src / intel_pmu.c
index 87a713b..957004d 100644 (file)
@@ -67,7 +67,7 @@ struct intel_pmu_ctx_s {
   _Bool hw_cache_events;
   _Bool kernel_pmu_events;
   _Bool sw_events;
-  char  event_list_fn[PATH_MAX];
+  char event_list_fn[PATH_MAX];
   char **hw_events;
   size_t hw_events_count;
   struct eventlist *event_list;
@@ -182,8 +182,6 @@ static void pmu_dump_events() {
     DEBUG(PMU_PLUGIN ":     config    : %#x", (unsigned)e->attr.config);
     DEBUG(PMU_PLUGIN ":     size      : %d", e->attr.size);
   }
-
-  return;
 }
 
 static void pmu_dump_config(void) {
@@ -194,10 +192,9 @@ static void pmu_dump_config(void) {
   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;
 }
 
 #endif /* COLLECT_DEBUG */
@@ -233,11 +230,11 @@ static int pmu_config_hw_events(oconfig_item_t *ci) {
 }
 
 static int pmu_config(oconfig_item_t *ci) {
-  int ret = 0;
 
   DEBUG(PMU_PLUGIN ": %s:%d", __FUNCTION__, __LINE__);
 
   for (int i = 0; i < ci->children_num; i++) {
+    int ret = 0;
     oconfig_item_t *child = ci->children + i;
 
     if (strcasecmp("ReportHardwareCacheEvents", child->key) == 0) {
@@ -253,7 +250,7 @@ static int pmu_config(oconfig_item_t *ci) {
       ret = cf_util_get_boolean(child, &g_ctx.sw_events);
     } else {
       ERROR(PMU_PLUGIN ": Unknown configuration parameter \"%s\".", child->key);
-      ret = (-1);
+      ret = -1;
     }
 
     if (ret != 0) {
@@ -269,7 +266,8 @@ static int pmu_config(oconfig_item_t *ci) {
   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};
@@ -277,9 +275,10 @@ static void pmu_submit_counter(int cpu, char *event, counter_t value) {
 
   sstrncpy(vl.plugin, PMU_PLUGIN, sizeof(vl.plugin));
   if (cpu == -1) {
-    ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "all");
+    snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "all");
   } else {
-    ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%d", cpu);
+    vl.meta = meta;
+    snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%d", cpu);
   }
   sstrncpy(vl.type, "counter", sizeof(vl.type));
   sstrncpy(vl.type_instance, event, sizeof(vl.type_instance));
@@ -287,7 +286,28 @@ static void pmu_submit_counter(int cpu, char *event, counter_t value) {
   plugin_dispatch_values(&vl);
 }
 
-static int pmu_dispatch_data(void) {
+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;
 
@@ -301,21 +321,29 @@ static int pmu_dispatch_data(void) {
 
       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);
     }
   }
-
-  return 0;
 }
 
 static int pmu_read(__attribute__((unused)) user_data_t *ud) {
@@ -326,22 +354,18 @@ static int pmu_read(__attribute__((unused)) user_data_t *ud) {
   ret = read_all_events(g_ctx.event_list);
   if (ret != 0) {
     ERROR(PMU_PLUGIN ": Failed to read values of all events.");
-    return 0;
+    return ret;
   }
 
-  ret = pmu_dispatch_data();
-  if (ret != 0) {
-    ERROR(PMU_PLUGIN ": Failed to dispatch event values.");
-    return 0;
-  }
+  pmu_dispatch_data();
 
   return 0;
 }
 
 static int pmu_add_events(struct eventlist *el, uint32_t type,
-                          event_info_t *events, int count) {
+                          event_info_t *events, size_t count) {
 
-  for (int i = 0; i < count; i++) {
+  for (size_t i = 0; i < count; i++) {
     /* Allocate memory for event struct that contains array of efd structs
        for all cores */
     struct event *e =
@@ -354,7 +378,6 @@ static int pmu_add_events(struct eventlist *el, uint32_t type,
     e->attr.type = type;
     e->attr.config = events[i].config;
     e->attr.size = PERF_ATTR_SIZE_VER0;
-    e->next = NULL;
     if (!el->eventlist)
       el->eventlist = e;
     if (el->eventlist_last)
@@ -550,7 +573,6 @@ init_error:
   sfree(g_ctx.hw_events);
   g_ctx.hw_events_count = 0;
 
-
   return ret;
 }