lkml.org 
[lkml]   [2012]   [Apr]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: [PATCH 4/6] perf tool: Parse general events from sysfs
    On 04/24/2012 05:04 PM, Jiri Olsa wrote:
    > hi,
    > so the point is to have an alias support for pmu event definition.
    > Seems like good idea to improve usability/readability, I have some
    > general comments though..
    >
    Thank you very much for reviewing this.
    > - you suggest to have sysfs files having contents like:
    > event=0x2c,umask=0xf
    > when we were adding the formats stuff into sysfs, we had to cut off
    > the sysfs file contents to bare minimum to obey the sysfs rule:
    > single file = single value
    > so you might have some troubles pushing that through.. not sure ;)
    >
    > - I haven't read the whole patchset, but seems like the "events"
    > directory is now specific to a 'Intel uncore pmu'. If thats the
    > case I think there should be generic way for each pmu to define
    > this stuff.
    >
    > - as for the tools/pmu.c change I'd like to see more consistent
    > way of parsing this, than via 'newcfg' variable.. but none
    > is comming to me so far ;) I'll think about that..
    >
    For this point, how about making the parser re-entrantable like the patch
    attached below does.

    Regards
    Yan, Zheng

    ---
    diff --git a/tools/perf/Makefile b/tools/perf/Makefile
    index e98e14c..a8b47d2 100644
    --- a/tools/perf/Makefile
    +++ b/tools/perf/Makefile
    @@ -728,11 +728,13 @@ $(OUTPUT)perf.o perf.spec \
    # These two need to be here so that when O= is not used they take precedence
    # over the general rule for .o

    +ALL_CFLAGS_NO_WERROR = $(shell echo $(ALL_CFLAGS) | sed "s/-Werror //g")
    +
    $(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS
    - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Iutil/ -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $<
    + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS_NO_WERROR) -Iutil/ -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $<

    $(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS
    - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -Iutil/ -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $<
    + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS_NO_WERROR) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -Iutil/ -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $<

    $(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
    $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
    diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
    index 5b3a0ef..b776c2e 100644
    --- a/tools/perf/util/parse-events.c
    +++ b/tools/perf/util/parse-events.c
    @@ -11,6 +11,7 @@
    #include "cache.h"
    #include "header.h"
    #include "debugfs.h"
    +#include "parse-events-bison.h"
    #include "parse-events-flex.h"
    #include "pmu.h"

    @@ -24,7 +25,8 @@ struct event_symbol {
    };

    int parse_events_parse(struct list_head *list, struct list_head *list_tmp,
    - int *idx);
    + int *idx, void *scanner);
    +static int __parse_events(const char *str, int *idx, struct list_head *list);

    #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
    #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
    @@ -651,8 +653,11 @@ int parse_events_add_numeric(struct list_head *list, int *idx,
    int parse_events_add_pmu(struct list_head *list, int *idx,
    char *name, struct list_head *head_config)
    {
    + LIST_HEAD(event);
    struct perf_event_attr attr;
    struct perf_pmu *pmu;
    + char *config;
    + int ret;

    pmu = perf_pmu__find(name);
    if (!pmu)
    @@ -666,10 +671,21 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
    */
    config_attr(&attr, head_config, 0);

    - if (perf_pmu__config(pmu, &attr, head_config))
    - return -EINVAL;
    + ret = perf_pmu__config(pmu, &attr, head_config);
    + if (!ret)
    + return add_event(list, idx, &attr, (char *) "pmu");
    +
    + ret = perf_pmu__alias(pmu, &config, head_config);
    + if (ret)
    + return ret;
    +
    + ret = __parse_events(config, idx, &event);
    + free(config);
    + if (ret)
    + return ret;

    - return add_event(list, idx, &attr, (char *) "pmu");
    + list_splice_tail(&event, list);
    + return 0;
    }

    void parse_events_update_lists(struct list_head *list_event,
    @@ -747,20 +763,34 @@ int parse_events_modifier(struct list_head *list, char *str)
    return 0;
    }

    -int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
    +static int __parse_events(const char *str, int *idx, struct list_head *list)
    {
    - LIST_HEAD(list);
    LIST_HEAD(list_tmp);
    YY_BUFFER_STATE buffer;
    - int ret, idx = evlist->nr_entries;
    + void *scanner;
    + int ret;
    +
    + ret = parse_events_lex_init(&scanner);
    + if (ret)
    + return ret;
    +
    + buffer = parse_events__scan_string(str, scanner);
    +
    + ret = parse_events_parse(list, &list_tmp, idx, scanner);

    - buffer = parse_events__scan_string(str);
    + parse_events__flush_buffer(buffer, scanner);
    + parse_events__delete_buffer(buffer, scanner);
    + parse_events_lex_destroy(scanner);

    - ret = parse_events_parse(&list, &list_tmp, &idx);
    + return ret;
    +}

    - parse_events__flush_buffer(buffer);
    - parse_events__delete_buffer(buffer);
    +int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
    +{
    + LIST_HEAD(list);
    + int ret, idx = evlist->nr_entries;

    + ret = __parse_events(str, &idx, &list);
    if (!ret) {
    int entries = idx - evlist->nr_entries;
    perf_evlist__splice_list_tail(evlist, &list, entries);
    diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
    index ca069f8..e1ffeb7 100644
    --- a/tools/perf/util/parse-events.h
    +++ b/tools/perf/util/parse-events.h
    @@ -80,7 +80,7 @@ void parse_events_update_lists(struct list_head *list_event,
    struct list_head *list_all);
    void parse_events_error(struct list_head *list_all,
    struct list_head *list_event,
    - int *idx, char const *msg);
    + int *idx, void *scanner, char const *msg);

    void print_events(const char *event_glob);
    void print_events_type(u8 type);
    diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
    index 05d766e..72066d2 100644
    --- a/tools/perf/util/parse-events.l
    +++ b/tools/perf/util/parse-events.l
    @@ -1,4 +1,6 @@

    +%option reentrant
    +%option bison-bridge
    %option prefix="parse_events_"

    %{
    @@ -7,7 +9,7 @@
    #include "parse-events-bison.h"
    #include "parse-events.h"

    -static int __value(char *str, int base, int token)
    +static int __value(YYSTYPE *yylval, char *str, int base, int token)
    {
    long num;

    @@ -16,35 +18,35 @@ static int __value(char *str, int base, int token)
    if (errno)
    return PE_ERROR;

    - parse_events_lval.num = num;
    + yylval->num = num;
    return token;
    }

    -static int value(int base)
    +static int value(YYSTYPE *yylval, char *text, int base)
    {
    - return __value(parse_events_text, base, PE_VALUE);
    + return __value(yylval, text, base, PE_VALUE);
    }

    -static int raw(void)
    +static int raw(YYSTYPE *yylval, char *text)
    {
    - return __value(parse_events_text + 1, 16, PE_RAW);
    + return __value(yylval, text + 1, 16, PE_RAW);
    }

    -static int str(int token)
    +static int str(YYSTYPE *yylval, char *text, int token)
    {
    - parse_events_lval.str = strdup(parse_events_text);
    + yylval->str = strdup(text);
    return token;
    }

    -static int sym(int type, int config)
    +static int sym(YYSTYPE *yylval, int type, int config)
    {
    - parse_events_lval.num = (type << 16) + config;
    + yylval->num = (type << 16) + config;
    return PE_VALUE_SYM;
    }

    -static int term(int type)
    +static int term(YYSTYPE *yylval, int type)
    {
    - parse_events_lval.num = type;
    + yylval->num = type;
    return PE_TERM;
    }

    @@ -58,25 +60,25 @@ modifier_event [ukhp]{1,5}
    modifier_bp [rwx]

    %%
    -cpu-cycles|cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
    -stalled-cycles-frontend|idle-cycles-frontend { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
    -stalled-cycles-backend|idle-cycles-backend { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
    -instructions { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
    -cache-references { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
    -cache-misses { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
    -branch-instructions|branches { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
    -branch-misses { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
    -bus-cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
    -ref-cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
    -cpu-clock { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
    -task-clock { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
    -page-faults|faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
    -minor-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
    -major-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
    -context-switches|cs { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
    -cpu-migrations|migrations { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
    -alignment-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
    -emulation-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
    +cpu-cycles|cycles { return sym(yylval, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
    +stalled-cycles-frontend|idle-cycles-frontend { return sym(yylval, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
    +stalled-cycles-backend|idle-cycles-backend { return sym(yylval, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
    +instructions { return sym(yylval, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
    +cache-references { return sym(yylval, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
    +cache-misses { return sym(yylval, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
    +branch-instructions|branches { return sym(yylval, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
    +branch-misses { return sym(yylval, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
    +bus-cycles { return sym(yylval, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
    +ref-cycles { return sym(yylval, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
    +cpu-clock { return sym(yylval, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
    +task-clock { return sym(yylval, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
    +page-faults|faults { return sym(yylval, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
    +minor-faults { return sym(yylval, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
    +major-faults { return sym(yylval, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
    +context-switches|cs { return sym(yylval, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
    +cpu-migrations|migrations { return sym(yylval, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
    +alignment-faults { return sym(yylval, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
    +emulation-faults { return sym(yylval, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }

    L1-dcache|l1-d|l1d|L1-data |
    L1-icache|l1-i|l1i|L1-instruction |
    @@ -84,14 +86,14 @@ LLC|L2 |
    dTLB|d-tlb|Data-TLB |
    iTLB|i-tlb|Instruction-TLB |
    branch|branches|bpu|btb|bpc |
    -node { return str(PE_NAME_CACHE_TYPE); }
    +node { return str(yylval, yytext, PE_NAME_CACHE_TYPE); }

    load|loads|read |
    store|stores|write |
    prefetch|prefetches |
    speculative-read|speculative-load |
    refs|Reference|ops|access |
    -misses|miss { return str(PE_NAME_CACHE_OP_RESULT); }
    +misses|miss { return str(yylval, yytext, PE_NAME_CACHE_OP_RESULT); }

    /*
    * These are event config hardcoded term names to be specified
    @@ -99,20 +101,20 @@ misses|miss { return str(PE_NAME_CACHE_OP_RESULT); }
    * so we can put them here directly. In case the we have a conflict
    * in future, this needs to go into '//' condition block.
    */
    -config { return term(PARSE_EVENTS__TERM_TYPE_CONFIG); }
    -config1 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG1); }
    -config2 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG2); }
    -period { return term(PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
    -branch_type { return term(PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
    +config { return term(yylval, PARSE_EVENTS__TERM_TYPE_CONFIG); }
    +config1 { return term(yylval, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
    +config2 { return term(yylval, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
    +period { return term(yylval, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
    +branch_type { return term(yylval, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }

    mem: { return PE_PREFIX_MEM; }
    -r{num_raw_hex} { return raw(); }
    -{num_dec} { return value(10); }
    -{num_hex} { return value(16); }
    +r{num_raw_hex} { return raw(yylval, yytext); }
    +{num_dec} { return value(yylval, yytext, 10); }
    +{num_hex} { return value(yylval, yytext, 16); }

    -{modifier_event} { return str(PE_MODIFIER_EVENT); }
    -{modifier_bp} { return str(PE_MODIFIER_BP); }
    -{name} { return str(PE_NAME); }
    +{modifier_event} { return str(yylval, yytext, PE_MODIFIER_EVENT); }
    +{modifier_bp} { return str(yylval, yytext, PE_MODIFIER_BP); }
    +{name} { return str(yylval, yytext, PE_NAME); }
    "/" { return '/'; }
    - { return '-'; }
    , { return ','; }
    @@ -121,7 +123,7 @@ r{num_raw_hex} { return raw(); }

    %%

    -int parse_events_wrap(void)
    +int parse_events_wrap(void *scanner __used)
    {
    return 1;
    }
    diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
    index d9637da..8a26f3d 100644
    --- a/tools/perf/util/parse-events.y
    +++ b/tools/perf/util/parse-events.y
    @@ -1,8 +1,10 @@
    -
    +%pure-parser
    %name-prefix "parse_events_"
    %parse-param {struct list_head *list_all}
    %parse-param {struct list_head *list_event}
    %parse-param {int *idx}
    +%parse-param {void *scanner}
    +%lex-param {void* scanner}

    %{

    @@ -13,8 +15,9 @@
    #include "types.h"
    #include "util.h"
    #include "parse-events.h"
    +#include "parse-events-bison.h"

    -extern int parse_events_lex (void);
    +extern int parse_events_lex (YYSTYPE* lvalp, void* scanner);

    #define ABORT_ON(val) \
    do { \
    @@ -194,7 +197,7 @@ PE_NAME
    {
    struct parse_events__term *term;

    - ABORT_ON(parse_events__new_term(&term, PARSE_EVENTS__TERM_TYPE_NUM,
    + ABORT_ON(parse_events__new_term(&term, PARSE_EVENTS__TERM_TYPE_STR,
    $1, NULL, 1));
    $$ = term;
    }
    @@ -223,7 +226,7 @@ sep_slash_dc: '/' | ':' |

    void parse_events_error(struct list_head *list_all __used,
    struct list_head *list_event __used,
    - int *idx __used,
    + int *idx __used, void *scanner __used,
    char const *msg __used)
    {
    }
    diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
    index cb08a11..3daf828 100644
    --- a/tools/perf/util/pmu.c
    +++ b/tools/perf/util/pmu.c
    @@ -80,6 +80,89 @@ static int pmu_format(char *name, struct list_head *format)
    return 0;
    }

    +static int perf_pmu__new_event(struct list_head *list, char *name, FILE *file)
    +{
    + struct perf_pmu__event *event;
    + char buf[256];
    + int ret;
    +
    + ret = fread(buf, 1, sizeof(buf), file);
    + if (ret == 0)
    + return -EINVAL;
    +
    + event = zalloc(sizeof(*event));
    + if (!event)
    + return -ENOMEM;
    +
    + event->name = strdup(name);
    + event->config = strndup(buf, ret);
    +
    + list_add_tail(&event->list, list);
    + return 0;
    +}
    +
    +/*
    + * Process all the sysfs attributes located under the directory
    + * specified in 'dir' parameter.
    + */
    +static int pmu_events_parse(char *dir, struct list_head *head)
    +{
    + struct dirent *evt_ent;
    + DIR *event_dir;
    + int ret = 0;
    +
    + event_dir = opendir(dir);
    + if (!event_dir)
    + return -EINVAL;
    +
    + while (!ret && (evt_ent = readdir(event_dir))) {
    + char path[PATH_MAX];
    + char *name = evt_ent->d_name;
    + FILE *file;
    +
    + if (!strcmp(name, ".") || !strcmp(name, ".."))
    + continue;
    +
    + snprintf(path, PATH_MAX, "%s/%s", dir, name);
    +
    + ret = -EINVAL;
    + file = fopen(path, "r");
    + if (!file)
    + break;
    + ret = perf_pmu__new_event(head, name, file);
    + fclose(file);
    + }
    +
    + closedir(event_dir);
    + return ret;
    +}
    +
    +/*
    + * Reading the pmu event definition, which should be located at:
    + * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
    + */
    +static int pmu_events(char *name, struct list_head *events)
    +{
    + struct stat st;
    + char path[PATH_MAX];
    + const char *sysfs;
    +
    + sysfs = sysfs_find_mountpoint();
    + if (!sysfs)
    + return -1;
    +
    + snprintf(path, PATH_MAX,
    + "%s/bus/event_source/devices/%s/events", sysfs, name);
    +
    + if (stat(path, &st) < 0)
    + return -1;
    +
    + if (pmu_events_parse(path, events))
    + return -1;
    +
    + return 0;
    +}
    +
    /*
    * Reading/parsing the default pmu type value, which should be
    * located at:
    @@ -118,6 +201,7 @@ static struct perf_pmu *pmu_lookup(char *name)
    {
    struct perf_pmu *pmu;
    LIST_HEAD(format);
    + LIST_HEAD(events);
    __u32 type;

    /*
    @@ -135,8 +219,12 @@ static struct perf_pmu *pmu_lookup(char *name)
    if (!pmu)
    return NULL;

    + pmu_events(name, &events);
    +
    INIT_LIST_HEAD(&pmu->format);
    + INIT_LIST_HEAD(&pmu->events);
    list_splice(&format, &pmu->format);
    + list_splice(&events, &pmu->events);
    pmu->name = strdup(name);
    pmu->type = type;
    return pmu;
    @@ -262,6 +350,47 @@ static int pmu_config(struct list_head *formats, struct perf_event_attr *attr,
    return 0;
    }

    +
    +static struct perf_pmu__event*
    +pmu_find_event(struct list_head *events, char *name)
    +{
    + struct perf_pmu__event *event;
    +
    + list_for_each_entry(event, events, list)
    + if (!strcmp(event->name, name))
    + return event;
    +
    + return NULL;
    +}
    +
    +static int pmu_event(struct perf_pmu *pmu, struct list_head *head_terms,
    + char **config)
    +{
    + struct parse_events__term *term;
    + struct perf_pmu__event *event;
    + char *buf;
    +
    + if (!list_is_singular(head_terms))
    + return -EINVAL;
    +
    + term = list_entry(head_terms->next, struct parse_events__term, list);
    +
    + if (term->type != PARSE_EVENTS__TERM_TYPE_STR || term->val.str)
    + return -EINVAL;
    +
    + event = pmu_find_event(&pmu->events, term->config);
    + if (!event)
    + return -EINVAL;
    +
    + buf = malloc(strlen(pmu->name) + strlen(event->config) + 3);
    + if (!buf)
    + return -ENOMEM;
    +
    + sprintf(buf, "%s/%s/", pmu->name, event->config);
    + *config = buf;
    + return 0;
    +}
    +
    /*
    * Configures event's 'attr' parameter based on the:
    * 1) users input - specified in terms parameter
    @@ -274,6 +403,12 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
    return pmu_config(&pmu->format, attr, head_terms);
    }

    +int perf_pmu__alias(struct perf_pmu *pmu, char **config,
    + struct list_head *head_terms)
    +{
    + return pmu_event(pmu, head_terms, config);
    +}
    +
    int perf_pmu__new_format(struct list_head *list, char *name,
    int config, unsigned long *bits)
    {
    diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
    index 68c0db9..3656b42 100644
    --- a/tools/perf/util/pmu.h
    +++ b/tools/perf/util/pmu.h
    @@ -19,16 +19,25 @@ struct perf_pmu__format {
    struct list_head list;
    };

    +struct perf_pmu__event {
    + char *name;
    + char *config;
    + struct list_head list;
    +};
    +
    struct perf_pmu {
    char *name;
    __u32 type;
    struct list_head format;
    + struct list_head events;
    struct list_head list;
    };

    struct perf_pmu *perf_pmu__find(char *name);
    int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
    struct list_head *head_terms);
    +int perf_pmu__alias(struct perf_pmu *pmu, char **config,
    + struct list_head *head_terms);

    int perf_pmu_wrap(void);
    void perf_pmu_error(struct list_head *list, char *name, char const *msg);

    \
     
     \ /
      Last update: 2012-04-25 07:51    [W:0.053 / U:29.876 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site