perf: Use PERF_SAMPLE_IDENTIFIER
[akaros.git] / tools / profile / perf / perf_core.c
index 88e8e1c..181d2f1 100644 (file)
@@ -467,8 +467,7 @@ static uint64_t *perf_get_event_values(int perf_fd, int ped, size_t *pnvalues)
        uint32_t i, n;
        uint64_t *values;
        uint64_t temp;
-       size_t bufsize = 3 * sizeof(uint64_t) + sizeof(uint32_t) +
-               MAX_NUM_CORES * sizeof(uint64_t);
+       size_t bufsize = sizeof(uint32_t) + MAX_NUM_CORES * sizeof(uint64_t);
        uint8_t *cmdbuf = xmalloc(bufsize);
        uint8_t *wptr = cmdbuf;
        const uint8_t *rptr = cmdbuf;
@@ -479,17 +478,11 @@ static uint64_t *perf_get_event_values(int perf_fd, int ped, size_t *pnvalues)
        xpwrite(perf_fd, cmdbuf, wptr - cmdbuf, 0);
        rsize = pread(perf_fd, cmdbuf, bufsize, 0);
 
-       if (rsize < (3 * sizeof(uint64_t) + sizeof(uint32_t))) {
+       if (rsize < (sizeof(uint32_t))) {
                fprintf(stderr, "Invalid read size while fetching event status: %ld\n",
                                rsize);
                exit(1);
        }
-
-       /* TODO: The kernel lies to us about this, it's all 0. */
-       rptr = get_le_u64(rptr, &temp);         /* discard ev.event */
-       rptr = get_le_u64(rptr, &temp);         /* discard ev.flags */
-       rptr = get_le_u64(rptr, &temp);         /* discard ev.trigger_count */
-
        rptr = get_le_u32(rptr, &n);
        if (((rptr - cmdbuf) + n * sizeof(uint64_t)) > rsize) {
                fprintf(stderr, "Invalid read size while fetching event status: %ld\n",
@@ -506,6 +499,21 @@ static uint64_t *perf_get_event_values(int perf_fd, int ped, size_t *pnvalues)
        return values;
 }
 
+/* Helper, returns the total count (across all cores) of the event @idx */
+uint64_t perf_get_event_count(struct perf_context *pctx, unsigned int idx)
+{
+       uint64_t total = 0;
+       size_t nvalues;
+       uint64_t *values;
+
+       values = perf_get_event_values(pctx->perf_fd, pctx->events[idx].ped,
+                                      &nvalues);
+       for (int i = 0; i < nvalues; i++)
+               total += values[i];
+       free(values);
+       return total;
+}
+
 static void perf_close_event(int perf_fd, int ped)
 {
        uint8_t cmdbuf[1 + sizeof(uint32_t)];
@@ -517,51 +525,29 @@ static void perf_close_event(int perf_fd, int ped)
        xpwrite(perf_fd, cmdbuf, wptr - cmdbuf, 0);
 }
 
-static void perf_enable_sampling(int kpctl_fd)
-{
-       static const char * const enable_str = "start";
-
-       xwrite(kpctl_fd, enable_str, strlen(enable_str));
-}
-
-static void perf_disable_sampling(int kpctl_fd)
-{
-       static const char * const disable_str = "stop";
-
-       xwrite(kpctl_fd, disable_str, strlen(disable_str));
-}
-
-static void perf_flush_sampling(int kpctl_fd)
-{
-       static const char * const flush_str = "flush";
-
-       xwrite(kpctl_fd, flush_str, strlen(flush_str));
-}
-
-struct perf_context *perf_create_context(const struct perf_context_config *cfg)
+struct perf_context *perf_create_context(struct perf_context_config *cfg)
 {
        struct perf_context *pctx = xzmalloc(sizeof(struct perf_context));
 
+       pctx->cfg = cfg;
        pctx->perf_fd = xopen(cfg->perf_file, O_RDWR, 0);
-       pctx->kpctl_fd = xopen(cfg->kpctl_file, O_RDWR, 0);
+       /* perf record needs kpctl_fd, but other perf subcommands might not.  We'll
+        * delay the opening of kpctl until we need it, since kprof is picky about
+        * multiple users of kpctl. */
+       pctx->kpctl_fd = -1;
        perf_get_arch_info(pctx->perf_fd, &pctx->pai);
-       perf_enable_sampling(pctx->kpctl_fd);
 
        return pctx;
 }
 
 void perf_free_context(struct perf_context *pctx)
 {
-       close(pctx->kpctl_fd);  /* disabled sampling */
+       if (pctx->kpctl_fd != -1)
+               close(pctx->kpctl_fd);  /* disabled sampling */
        close(pctx->perf_fd);   /* closes all events */
        free(pctx);
 }
 
-void perf_flush_context_traces(struct perf_context *pctx)
-{
-       perf_flush_sampling(pctx->kpctl_fd);
-}
-
 void perf_context_event_submit(struct perf_context *pctx,
                                                           const struct core_set *cores,
                                                           const struct perf_eventsel *sel)
@@ -583,24 +569,44 @@ void perf_context_event_submit(struct perf_context *pctx,
        }
 }
 
-void perf_context_show_values(struct perf_context *pctx, FILE *file)
+void perf_stop_events(struct perf_context *pctx)
 {
-       for (int i = 0; i < pctx->event_count; i++) {
-               size_t nvalues;
-               struct perf_eventsel *sel = &pctx->events[i].sel;
-               uint64_t *values = perf_get_event_values(pctx->perf_fd,
-                                                                                                pctx->events[i].ped,
-                                                                                                &nvalues);
+       for (int i = 0; i < pctx->event_count; i++)
+               perf_close_event(pctx->perf_fd, pctx->events[i].ped);
+}
 
-               fprintf(file, "Event: %s, final code %p%s, trigger count %d\n\t",
+static void ensure_kpctl_is_open(struct perf_context *pctx)
+{
+       if (pctx->kpctl_fd == -1)
+               pctx->kpctl_fd = xopen(pctx->cfg->kpctl_file, O_RDWR, 0);
+}
+
+void perf_start_sampling(struct perf_context *pctx)
+{
+       static const char * const enable_str = "start";
+
+       ensure_kpctl_is_open(pctx);
+       xwrite(pctx->kpctl_fd, enable_str, strlen(enable_str));
+}
+
+void perf_stop_sampling(struct perf_context *pctx)
+{
+       static const char * const disable_str = "stop";
+
+       ensure_kpctl_is_open(pctx);
+       xwrite(pctx->kpctl_fd, disable_str, strlen(disable_str));
+}
+
+void perf_context_show_events(struct perf_context *pctx, FILE *file)
+{
+       struct perf_eventsel *sel;
+
+       for (int i = 0; i < pctx->event_count; i++) {
+               sel = &pctx->events[i].sel;
+               fprintf(file, "Event: %s, final code %p%s, trigger count %d\n",
                        sel->fq_str, sel->ev.event,
                        perfmon_is_fixed_event(&sel->ev) ? " (fixed)" : "",
                        sel->ev.trigger_count);
-               for (size_t j = 0; j < nvalues; j++)
-                       fprintf(file, "%lu ", values[j]);
-               fprintf(file, "\n");
-
-               free(values);
        }
 }
 
@@ -758,7 +764,6 @@ void perf_convert_trace_data(struct perfconv_context *cctx, const char *input,
 {
        FILE *infile;
        size_t ksize;
-       char kpath[1024];
 
        infile = xfopen(input, "rb");
        if (xfsize(infile) > 0) {