perf tools: Add support to parse event group syntax

Adding scanner/parser bits to parse event groups.

The grammar for group is:
  groups:      groups ',' group | group
  group:       group_name '{' events '}' group_mod
  group_name:  name | empty
  group_mod:   ':' group_mods | empty
  group_mods:  event_mod

It's possible to use standard event modifier as a modifier
for group. It'll be used as an update to existing event
modifiers.

It's necessary to use quoting ("'\) when specifying group on
command line, since {} characters are interpreted by most of
the shells.

It is now possible to specify groups in event syntax like:

  '{cycles,faults}'
   - anonymous group

  'group1{cycles,faults}
   - group with name 'group1'

  '{cycles,faults}:k
   - anonymous group with event modifier 'k'

  '{cpu-clock,task-clock},{minor-faults,major-faults}'
   - two anonymous groups

The grouping functionality itself is coming shortly.

Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Acked-by: Peter Zijlstra <peterz@infradead.org>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ulrich Drepper <drepper@gmail.com>
Link: http://lkml.kernel.org/n/tip-p4j8bnvo879uokum4k4zk5q6@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Jiri Olsa 2012-08-08 12:14:14 +02:00 committed by Arnaldo Carvalho de Melo
parent a619183672
commit 89efb02950
4 changed files with 97 additions and 16 deletions

View File

@ -611,19 +611,29 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
pmu_event_name(head_config));
}
int parse_events__modifier_group(struct list_head *list __used,
char *event_mod __used)
{
return 0;
}
void parse_events__group(char *name __used, struct list_head *list __used)
{
}
void parse_events_update_lists(struct list_head *list_event,
struct list_head *list_all)
{
/*
* Called for single event definition. Update the
* 'all event' list, and reinit the 'signle event'
* 'all event' list, and reinit the 'single event'
* list, for next event definition.
*/
list_splice_tail(list_event, list_all);
free(list_event);
}
int parse_events_modifier(struct list_head *list, char *str)
int parse_events__modifier_event(struct list_head *list, char *str)
{
struct perf_evsel *evsel;
int exclude = 0, exclude_GH = 0;

View File

@ -79,7 +79,8 @@ int parse_events__term_str(struct parse_events__term **_term,
int parse_events__term_clone(struct parse_events__term **new,
struct parse_events__term *term);
void parse_events__free_terms(struct list_head *terms);
int parse_events_modifier(struct list_head *list, char *str);
int parse_events__modifier_event(struct list_head *list, char *str);
int parse_events__modifier_group(struct list_head *list, char *event_mod);
int parse_events_add_tracepoint(struct list_head **list, int *idx,
char *sys, char *event);
int parse_events_add_numeric(struct list_head **list, int *idx,
@ -91,6 +92,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
void *ptr, char *type);
int parse_events_add_pmu(struct list_head **list, int *idx,
char *pmu , struct list_head *head_config);
void parse_events__group(char *name, struct list_head *list);
void parse_events_update_lists(struct list_head *list_event,
struct list_head *list_all);
void parse_events_error(void *data, void *scanner, char const *msg);

View File

@ -151,6 +151,8 @@ r{num_raw_hex} { return raw(yyscanner); }
- { return '-'; }
, { return ','; }
: { return ':'; }
"{" { return '{'; }
"}" { return '}'; }
= { return '='; }
\n { }

View File

@ -30,7 +30,7 @@ do { \
%token PE_NAME
%token PE_MODIFIER_EVENT PE_MODIFIER_BP
%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
%token PE_PREFIX_MEM PE_PREFIX_RAW
%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
%token PE_ERROR
%type <num> PE_VALUE
%type <num> PE_VALUE_SYM_HW
@ -53,6 +53,11 @@ do { \
%type <head> event_legacy_numeric
%type <head> event_legacy_raw
%type <head> event_def
%type <head> event
%type <head> events
%type <head> group_def
%type <head> group
%type <head> groups
%union
{
@ -64,33 +69,95 @@ do { \
%%
start:
PE_START_EVENTS events
PE_START_EVENTS start_events
|
PE_START_TERMS terms
PE_START_TERMS start_terms
start_events: groups
{
struct parse_events_data__events *data = _data;
parse_events_update_lists($1, &data->list);
}
groups:
groups ',' group
{
struct list_head *list = $1;
struct list_head *group = $3;
parse_events_update_lists(group, list);
$$ = list;
}
|
groups ',' event
{
struct list_head *list = $1;
struct list_head *event = $3;
parse_events_update_lists(event, list);
$$ = list;
}
|
group
|
event
group:
group_def ':' PE_MODIFIER_EVENT
{
struct list_head *list = $1;
ABORT_ON(parse_events__modifier_group(list, $3));
$$ = list;
}
|
group_def
group_def:
PE_NAME '{' events '}'
{
struct list_head *list = $3;
parse_events__group($1, list);
$$ = list;
}
|
'{' events '}'
{
struct list_head *list = $2;
parse_events__group(NULL, list);
$$ = list;
}
events:
events ',' event | event
events ',' event
{
struct list_head *event = $3;
struct list_head *list = $1;
parse_events_update_lists(event, list);
$$ = list;
}
|
event
event:
event_def PE_MODIFIER_EVENT
{
struct parse_events_data__events *data = _data;
struct list_head *list = $1;
/*
* Apply modifier on all events added by single event definition
* (there could be more events added for multiple tracepoint
* definitions via '*?'.
*/
ABORT_ON(parse_events_modifier($1, $2));
parse_events_update_lists($1, &data->list);
ABORT_ON(parse_events__modifier_event(list, $2));
$$ = list;
}
|
event_def
{
struct parse_events_data__events *data = _data;
parse_events_update_lists($1, &data->list);
}
event_def: event_pmu |
event_legacy_symbol |
@ -222,7 +289,7 @@ PE_RAW
$$ = list;
}
terms: event_config
start_terms: event_config
{
struct parse_events_data__terms *data = _data;
data->terms = $1;