lkml.org 
[lkml]   [2016]   [Feb]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 05/23] perf mem: Add -e record option
    Date
    Adding -e option for perf mem record command,
    to be able to specify memory event directly.

    Get list of available events:

    $ perf mem record -e list
    ldlat-loads
    ldlat-stores

    Monitor ldlat-loads:
    $ perf mem record -e ldlat-loads true

    Link: http://lkml.kernel.org/n/tip-x5famenpxjfmhojzo95sf26s@git.kernel.org
    Signed-off-by: Jiri Olsa <jolsa@kernel.org>
    ---
    tools/perf/builtin-mem.c | 63 +++++++++++++++++++++++++++++++++++++++++---
    tools/perf/util/mem-events.c | 47 ++++++++++++++++++++++++++++++---
    tools/perf/util/mem-events.h | 3 +++
    3 files changed, 106 insertions(+), 7 deletions(-)

    diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
    index 36c56a4b778b..b3f8a89ede40 100644
    --- a/tools/perf/builtin-mem.c
    +++ b/tools/perf/builtin-mem.c
    @@ -7,6 +7,7 @@
    #include "util/session.h"
    #include "util/data.h"
    #include "util/mem-events.h"
    +#include "util/debug.h"

    #define MEM_OPERATION_LOAD 0x1
    #define MEM_OPERATION_STORE 0x2
    @@ -22,11 +23,55 @@ struct perf_mem {
    DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
    };

    +static int parse_record_events(const struct option *opt,
    + const char *str, int unset __maybe_unused)
    +{
    + struct perf_mem *mem = *(struct perf_mem **)opt->value;
    + int j;
    +
    + if (strcmp(str, "list")) {
    + if (!perf_mem_events__parse(str)) {
    + mem->operation = 0;
    + return 0;
    + }
    + exit(-1);
    + }
    +
    + for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
    + struct perf_mem_event *e = &perf_mem_events[j];
    +
    + fprintf(stderr, "%-20s%s",
    + e->tag, verbose ? "" : "\n");
    + if (verbose)
    + fprintf(stderr, " [%s]\n", e->name);
    + }
    + exit(0);
    +}
    +
    +static const char * const __usage[] = {
    + "perf mem record [<options>] [<command>]",
    + "perf mem record [<options>] -- <command> [<options>]",
    + NULL
    +};
    +
    +static const char * const *record_mem_usage = __usage;
    +
    static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
    {
    int rec_argc, i = 0, j;
    const char **rec_argv;
    int ret;
    + struct option options[] = {
    + OPT_CALLBACK('e', "event", &mem, "event",
    + "event selector. use 'perf mem record -e list' to list available events",
    + parse_record_events),
    + OPT_INCR('v', "verbose", &verbose,
    + "be more verbose (show counter open errors, etc)"),
    + OPT_END()
    + };
    +
    + argc = parse_options(argc, argv, options, record_mem_usage,
    + PARSE_OPT_STOP_AT_NON_OPTION);

    rec_argc = argc + 7; /* max number of arguments */
    rec_argv = calloc(rec_argc + 1, sizeof(char *));
    @@ -35,10 +80,11 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)

    rec_argv[i++] = "record";

    - if (mem->operation & MEM_OPERATION_LOAD) {
    + if (mem->operation & MEM_OPERATION_LOAD)
    perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true;
    +
    + if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record)
    rec_argv[i++] = "-W";
    - }

    rec_argv[i++] = "-d";

    @@ -50,9 +96,19 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
    rec_argv[i++] = perf_mem_events[j].name;
    };

    - for (j = 1; j < argc; j++, i++)
    + for (j = 0; j < argc; j++, i++)
    rec_argv[i] = argv[j];

    + if (verbose > 0) {
    + pr_debug("calling: record ");
    +
    + while (rec_argv[j]) {
    + pr_debug("%s ", rec_argv[j]);
    + j++;
    + }
    + pr_debug("\n");
    + }
    +
    ret = cmd_record(i, rec_argv, NULL);
    free(rec_argv);
    return ret;
    @@ -299,7 +355,6 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
    NULL
    };

    -
    argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands,
    mem_usage, PARSE_OPT_STOP_AT_NON_OPTION);

    diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c
    index c6ba0a19ec9a..b1507c04b257 100644
    --- a/tools/perf/util/mem-events.c
    +++ b/tools/perf/util/mem-events.c
    @@ -1,10 +1,51 @@
    +#include <stddef.h>
    +#include <stdlib.h>
    +#include <string.h>
    +#include <errno.h>
    #include "mem-events.h"
    +#include "debug.h"

    -#define E(n) { .name = n }
    +#define E(t, n) { .tag = t, .name = n }

    struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
    - E("cpu/mem-loads,ldlat=30/P"),
    - E("cpu/mem-stores/P"),
    + E("ldlat-loads", "cpu/mem-loads,ldlat=30/P"),
    + E("ldlat-stores", "cpu/mem-stores/P"),
    };

    #undef E
    +
    +int perf_mem_events__parse(const char *str)
    +{
    + char *tok, *saveptr = NULL;
    + bool found = false;
    + char *buf;
    + int j;
    +
    + /* We need buffer that we know we can write to. */
    + buf = malloc(strlen(str) + 1);
    + if (!buf)
    + return -ENOMEM;
    +
    + strcpy(buf, str);
    +
    + tok = strtok_r((char *)buf, ",", &saveptr);
    +
    + while (tok) {
    + for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
    + struct perf_mem_event *e = &perf_mem_events[j];
    +
    + if (strstr(e->tag, tok))
    + e->record = found = true;
    + }
    +
    + tok = strtok_r(NULL, ",", &saveptr);
    + }
    +
    + free(buf);
    +
    + if (found)
    + return 0;
    +
    + pr_err("failed: event '%s' not found, use '-e list' to get list of available events\n", str);
    + return -1;
    +}
    diff --git a/tools/perf/util/mem-events.h b/tools/perf/util/mem-events.h
    index ee5fde222389..0b5247468462 100644
    --- a/tools/perf/util/mem-events.h
    +++ b/tools/perf/util/mem-events.h
    @@ -5,6 +5,7 @@

    struct perf_mem_event {
    bool record;
    + const char *tag;
    const char *name;
    };

    @@ -16,5 +17,7 @@ enum {

    extern struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX];

    +int perf_mem_events__parse(const char *str);
    +
    #endif /* __PERF_MEM_EVENTS_H */

    --
    2.4.3
    \
     
     \ /
      Last update: 2016-02-15 10:21    [W:3.212 / U:0.068 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site