Skip to contentSkip to conversation

perf tool: Fix enable/disable events logic for record command

PATCH In review Jiri Olsa 2 participants 14 messages Nov 12, 2012 – Dec 8, 2012 perf events

lore
Share & tools
lore

Jiri Olsa

author
#0 lore raw

cover perf tool: Fix enable/disable events logic for record command

hi,
this patchset fixes the event enable/disable logic for record command (patches 1 - 4) plus small fix for event parsing (patch 5).

Attached patches:
1/5 perf tool: Fix attributes for '{}' defined event groups 2/5 perf tool: Fix 'disabled' attribute config for record command 3/5 perf tool: Ensure single disable call per event in record comand 4/5 perf tool: Omit group members from perf_evlist__disable/enable 5/5 perf tool: Add basic event modifier sanity check

Also available in:
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/linux.git
perf/enable5

thanks,
jirka

Cc Corey Ashford <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
---
 tools/perf/builtin-record.c               | 26 ++++++++++++++++++++++----
 tools/perf/builtin-stat.c                 | 11 ++++-------
 tools/perf/tests/attr/test-record-group   |  1 +
 tools/perf/tests/attr/test-record-group1  |  5 ++---
 tools/perf/tests/attr/test-stat-group1    |  6 ++----
 tools/perf/tests/open-syscall-tp-fields.c |  2 +-
 tools/perf/util/evlist.c                  | 10 ++++++----
 tools/perf/util/evsel.c                   | 50 ++++++++++++++++++++++++++++++++++++++++++++------
 tools/perf/util/evsel.h                   |  3 +--
 tools/perf/util/parse-events.c            | 20 ++++++++++++++++++++
 tools/perf/util/parse-events.l            |  2 +-
 11 files changed, 104 insertions(+), 32 deletions(-)
author
#1 lore raw

PATCH 1/5 perf tool: Fix attributes for '{}' defined event groups

Fixing events attributes for groups defined via '{}'.

Currently 'enable_on_exec' attribute in record command and both 'disabled ' and 'enable_on_exec' attributes in stat command are set based on the 'group' option. This eliminates proper setup for '{}' defined groups as they don't set 'group' option.

Making above attributes values based on the 'evsel->leader' as this is common to both group definition.

Moving perf_evlist__set_leader call within builtin-record ahead perf_evlist__config_attrs call, because the latter needs possible group leader links in place.

Cc Corey Ashford <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
---
 tools/perf/builtin-record.c               |  8 ++++++--
 tools/perf/builtin-stat.c                 | 11 ++++-------
 tools/perf/tests/attr/test-record-group1  |  4 +---
 tools/perf/tests/attr/test-stat-group1    |  6 ++----
 tools/perf/tests/open-syscall-tp-fields.c |  2 +-
 tools/perf/util/evlist.c                  |  6 ++----
 tools/perf/util/evsel.c                   |  8 +++-----
 tools/perf/util/evsel.h                   |  3 +--
 8 files changed, 20 insertions(+), 28 deletions(-)
tools/perf/builtin-record.c +6 -2
index 5783c32..3717027 100644
@@ -230,11 +230,15 @@ static int perf_record__open(struct perf_record *rec)
 	struct perf_record_opts *opts = &rec->opts;
 	int rc = 0;
 
-	perf_evlist__config_attrs(evlist, opts);
-
+	/*
+	 * Set the evsel leader links before we configure attributes,
+	 * since some might depend on this info.
+	 */
 	if (opts->group)
 		perf_evlist__set_leader(evlist);
 
+	perf_evlist__config_attrs(evlist, opts);
+
 	list_for_each_entry(pos, &evlist->entries, node) {
 		struct perf_event_attr *attr = &pos->attr;
 		/*
tools/perf/builtin-stat.c +4 -7
index 6888960..557081e 100644
@@ -129,8 +129,7 @@ static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];
 static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS];
 static struct stats walltime_nsecs_stats;
 
-static int create_perf_stat_counter(struct perf_evsel *evsel,
-				    struct perf_evsel *first)
+static int create_perf_stat_counter(struct perf_evsel *evsel)
 {
 	struct perf_event_attr *attr = &evsel->attr;
 	bool exclude_guest_missing = false;
@@ -153,7 +152,7 @@ retry:
 		return 0;
 	}
 
-	if (!perf_target__has_task(&target) && (!group || evsel == first)) {
+	if (!perf_target__has_task(&target) && (!evsel->leader)) {
 		attr->disabled = 1;
 		attr->enable_on_exec = 1;
 	}
@@ -272,7 +271,7 @@ static int read_counter(struct perf_evsel *counter)
 static int __run_perf_stat(int argc __maybe_unused, const char **argv)
 {
 	unsigned long long t0, t1;
-	struct perf_evsel *counter, *first;
+	struct perf_evsel *counter;
 	int status = 0;
 	int child_ready_pipe[2], go_pipe[2];
 	const bool forks = (argc > 0);
@@ -332,10 +331,8 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv)
 	if (group)
 		perf_evlist__set_leader(evsel_list);
 
-	first = perf_evlist__first(evsel_list);
-
 	list_for_each_entry(counter, &evsel_list->entries, node) {
-		if (create_perf_stat_counter(counter, first) < 0) {
+		if (create_perf_stat_counter(counter) < 0) {
 			/*
 			 * PPC returns ENXIO for HW counters until 2.6.37
 			 * (behavior changed with commit b0a873e).
tools/perf/tests/attr/test-record-group1 +1 -3
index 39bf860..013572f 100644
@@ -15,6 +15,4 @@ config=1
 sample_type=327
 mmap=0
 comm=0
-# TODO this is disabled for --group option, enabled otherwise
-#      check why..
-enable_on_exec=1
+enable_on_exec=0
tools/perf/tests/attr/test-stat-group1 +2 -4
index 5ae2718..2a1f86e 100644
@@ -11,7 +11,5 @@ group_fd=-1
 fd=2
 group_fd=1
 config=1
-# TODO both disabled and enable_on_exec are disabled for --group option,
-#      enabled otherwise, check why..
-disabled=1
-enable_on_exec=1
+disabled=0
+enable_on_exec=0
tools/perf/tests/open-syscall-tp-fields.c +1 -1
index b05b6a6..1c52fdc 100644
@@ -41,7 +41,7 @@ int test__syscall_open_tp_fields(void)
 		goto out_delete_evlist;
 	}
 
-	perf_evsel__config(evsel, &opts, evsel);
+	perf_evsel__config(evsel, &opts);
 
 	evlist->threads->map[0] = getpid();
 
tools/perf/util/evlist.c +2 -4
index a41dc4a..04acae0 100644
@@ -52,15 +52,13 @@ struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
 void perf_evlist__config_attrs(struct perf_evlist *evlist,
 			       struct perf_record_opts *opts)
 {
-	struct perf_evsel *evsel, *first;
+	struct perf_evsel *evsel;
 
 	if (evlist->cpus->map[0] < 0)
 		opts->no_inherit = true;
 
-	first = perf_evlist__first(evlist);
-
 	list_for_each_entry(evsel, &evlist->entries, node) {
-		perf_evsel__config(evsel, opts, first);
+		perf_evsel__config(evsel, opts);
 
 		if (evlist->nr_entries > 1)
 			evsel->attr.sample_type |= PERF_SAMPLE_ID;
tools/perf/util/evsel.c +3 -5
index 618d411..6d4a5f6 100644
@@ -404,8 +404,8 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
 	return evsel->name ?: "unknown";
 }
 
-void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
-			struct perf_evsel *first)
+void perf_evsel__config(struct perf_evsel *evsel,
+			struct perf_record_opts *opts)
 {
 	struct perf_event_attr *attr = &evsel->attr;
 	int track = !evsel->idx; /* only the first counter needs these */
@@ -486,10 +486,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
 	attr->mmap = track;
 	attr->comm = track;
 
-	if (perf_target__none(&opts->target) &&
-	    (!opts->group || evsel == first)) {
+	if (perf_target__none(&opts->target) && (!evsel->leader))
 		attr->enable_on_exec = 1;
-	}
 }
 
 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
tools/perf/util/evsel.h +1 -2
index 6f94d6d..32d7ec7 100644
@@ -92,8 +92,7 @@ void perf_evsel__exit(struct perf_evsel *evsel);
 void perf_evsel__delete(struct perf_evsel *evsel);
 
 void perf_evsel__config(struct perf_evsel *evsel,
-			struct perf_record_opts *opts,
-			struct perf_evsel *first);
+			struct perf_record_opts *opts);
 
 bool perf_evsel__is_cache_op_valid(u8 type, u8 op);
 
Signature · 1 line
1.7.11.7
#2 lore raw

[tip:perf/core] perf tools: Fix attributes for '{}' defined event groups

Commit-ID:  cac21425578abddc4e9f529845832a57ba27ce0f
Gitweb:     http://git.kernel.org/tip/cac21425578abddc4e9f529845832a57ba27ce0f
Author:     Jiri Olsa <[email protected]>
AuthorDate: Mon, 12 Nov 2012 18:34:00 +0100
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 14 Nov 2012 16:51:50 -0300

perf tools: Fix attributes for '{}' defined event groups

Fixing events attributes for groups defined via '{}'.

Currently 'enable_on_exec' attribute in record command and both 'disabled ' and 'enable_on_exec' attributes in stat command are set based on the 'group' option. This eliminates proper setup for '{}' defined groups as they don't set 'group' option.

Making above attributes values based on the 'evsel->leader' as this is common to both group definition.

Moving perf_evlist__set_leader call within builtin-record ahead perf_evlist__config_attrs call, because the latter needs possible group leader links in place.

---
 tools/perf/builtin-record.c               |  8 ++++++--
 tools/perf/builtin-stat.c                 | 11 ++++-------
 tools/perf/tests/attr/test-record-group1  |  4 +---
 tools/perf/tests/attr/test-stat-group1    |  6 ++----
 tools/perf/tests/open-syscall-tp-fields.c |  2 +-
 tools/perf/util/evlist.c                  |  6 ++----
 tools/perf/util/evsel.c                   |  8 +++-----
 tools/perf/util/evsel.h                   |  3 +--
 8 files changed, 20 insertions(+), 28 deletions(-)
tools/perf/builtin-record.c +6 -2
index 5783c32..3717027 100644
@@ -230,11 +230,15 @@ static int perf_record__open(struct perf_record *rec)
 	struct perf_record_opts *opts = &rec->opts;
 	int rc = 0;
 
-	perf_evlist__config_attrs(evlist, opts);
-
+	/*
+	 * Set the evsel leader links before we configure attributes,
+	 * since some might depend on this info.
+	 */
 	if (opts->group)
 		perf_evlist__set_leader(evlist);
 
+	perf_evlist__config_attrs(evlist, opts);
+
 	list_for_each_entry(pos, &evlist->entries, node) {
 		struct perf_event_attr *attr = &pos->attr;
 		/*
tools/perf/builtin-stat.c +4 -7
index 6888960..557081e 100644
@@ -129,8 +129,7 @@ static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];
 static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS];
 static struct stats walltime_nsecs_stats;
 
-static int create_perf_stat_counter(struct perf_evsel *evsel,
-				    struct perf_evsel *first)
+static int create_perf_stat_counter(struct perf_evsel *evsel)
 {
 	struct perf_event_attr *attr = &evsel->attr;
 	bool exclude_guest_missing = false;
@@ -153,7 +152,7 @@ retry:
 		return 0;
 	}
 
-	if (!perf_target__has_task(&target) && (!group || evsel == first)) {
+	if (!perf_target__has_task(&target) && (!evsel->leader)) {
 		attr->disabled = 1;
 		attr->enable_on_exec = 1;
 	}
@@ -272,7 +271,7 @@ static int read_counter(struct perf_evsel *counter)
 static int __run_perf_stat(int argc __maybe_unused, const char **argv)
 {
 	unsigned long long t0, t1;
-	struct perf_evsel *counter, *first;
+	struct perf_evsel *counter;
 	int status = 0;
 	int child_ready_pipe[2], go_pipe[2];
 	const bool forks = (argc > 0);
@@ -332,10 +331,8 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv)
 	if (group)
 		perf_evlist__set_leader(evsel_list);
 
-	first = perf_evlist__first(evsel_list);
-
 	list_for_each_entry(counter, &evsel_list->entries, node) {
-		if (create_perf_stat_counter(counter, first) < 0) {
+		if (create_perf_stat_counter(counter) < 0) {
 			/*
 			 * PPC returns ENXIO for HW counters until 2.6.37
 			 * (behavior changed with commit b0a873e).
tools/perf/tests/attr/test-record-group1 +1 -3
index 39bf860..013572f 100644
@@ -15,6 +15,4 @@ config=1
 sample_type=327
 mmap=0
 comm=0
-# TODO this is disabled for --group option, enabled otherwise
-#      check why..
-enable_on_exec=1
+enable_on_exec=0
tools/perf/tests/attr/test-stat-group1 +2 -4
index 5ae2718..2a1f86e 100644
@@ -11,7 +11,5 @@ group_fd=-1
 fd=2
 group_fd=1
 config=1
-# TODO both disabled and enable_on_exec are disabled for --group option,
-#      enabled otherwise, check why..
-disabled=1
-enable_on_exec=1
+disabled=0
+enable_on_exec=0
tools/perf/tests/open-syscall-tp-fields.c +1 -1
index b05b6a6..1c52fdc 100644
@@ -41,7 +41,7 @@ int test__syscall_open_tp_fields(void)
 		goto out_delete_evlist;
 	}
 
-	perf_evsel__config(evsel, &opts, evsel);
+	perf_evsel__config(evsel, &opts);
 
 	evlist->threads->map[0] = getpid();
 
tools/perf/util/evlist.c +2 -4
index a41dc4a..04acae0 100644
@@ -52,15 +52,13 @@ struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
 void perf_evlist__config_attrs(struct perf_evlist *evlist,
 			       struct perf_record_opts *opts)
 {
-	struct perf_evsel *evsel, *first;
+	struct perf_evsel *evsel;
 
 	if (evlist->cpus->map[0] < 0)
 		opts->no_inherit = true;
 
-	first = perf_evlist__first(evlist);
-
 	list_for_each_entry(evsel, &evlist->entries, node) {
-		perf_evsel__config(evsel, opts, first);
+		perf_evsel__config(evsel, opts);
 
 		if (evlist->nr_entries > 1)
 			evsel->attr.sample_type |= PERF_SAMPLE_ID;
tools/perf/util/evsel.c +3 -5
index 618d411..6d4a5f6 100644
@@ -404,8 +404,8 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
 	return evsel->name ?: "unknown";
 }
 
-void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
-			struct perf_evsel *first)
+void perf_evsel__config(struct perf_evsel *evsel,
+			struct perf_record_opts *opts)
 {
 	struct perf_event_attr *attr = &evsel->attr;
 	int track = !evsel->idx; /* only the first counter needs these */
@@ -486,10 +486,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
 	attr->mmap = track;
 	attr->comm = track;
 
-	if (perf_target__none(&opts->target) &&
-	    (!opts->group || evsel == first)) {
+	if (perf_target__none(&opts->target) && (!evsel->leader))
 		attr->enable_on_exec = 1;
-	}
 }
 
 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
tools/perf/util/evsel.h +1 -2
index 6f94d6d..32d7ec7 100644
@@ -92,8 +92,7 @@ void perf_evsel__exit(struct perf_evsel *evsel);
 void perf_evsel__delete(struct perf_evsel *evsel);
 
 void perf_evsel__config(struct perf_evsel *evsel,
-			struct perf_record_opts *opts,
-			struct perf_evsel *first);
+			struct perf_record_opts *opts);
 
 bool perf_evsel__is_cache_op_valid(u8 type, u8 op);
 
author
#3 lore raw

PATCH 2/5 perf tool: Fix 'disabled' attribute config for record command

In reply to Jiri Olsa

Currently the record command sets all events initially as disabled.

There's non conditional perf_evlist__enable call, that enables all events before we exec tracee program. That actually screws whole enable_on_exec logic, because the event is enabled before the traced program got executed.

What we actually want is:

1) For any type of traced program:
- all independent events and group leaders are disabled
- all group members are enabled

Group members are ruled by group leaders. They need to be enabled, because the group scheduling relies on that.

2) For traced programs executed by perf:
- all independent events and group leaders have enable_on_exec set
- we don't specifically enable or disable any event during the record command

Independent events and group leaders are initially disabled and get enabled by exec. Group members are ruled by group leaders as stated in 1).

3) For traced programs attached by perf (pid/tid):
- we specifically enable or disable all events during the record command

When attaching events to already running traced we enable/disable events specifically, as there's no initial traced exec call.

Fixing appropriate perf_event_attr test case to cover this change.

Cc Corey Ashford <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
---
 tools/perf/builtin-record.c              | 15 ++++++++++--
 tools/perf/tests/attr/test-record-group  |  1 +
 tools/perf/tests/attr/test-record-group1 |  1 +
 tools/perf/util/evsel.c                  | 42 +++++++++++++++++++++++++++++++-
 4 files changed, 56 insertions(+), 3 deletions(-)
tools/perf/builtin-record.c +13 -2
index 3717027..268b356 100644
@@ -701,7 +701,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 		}
 	}
 
-	perf_evlist__enable(evsel_list);
+	/*
+	 * When perf is starting the traced process, all the events
+	 * (apart from group members) have enable_on_exec=1 set,
+	 * so don't spoil it by prematurely enabling them.
+	 */
+	if (!perf_target__none(&opts->target))
+		perf_evlist__enable(evsel_list);
 
 	/*
 	 * Let the child rip
@@ -724,7 +730,12 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 			waking++;
 		}
 
-		if (done)
+		/*
+		 * When perf is starting the traced process, at the end events
+		 * die with the process and we wait for that. Thus no need to
+		 * disable events in this case.
+		 */
+		if (done && !perf_target__none(&opts->target))
 			perf_evlist__disable(evsel_list);
 	}
 
tools/perf/tests/attr/test-record-group +1 -0
index b945f77..a6599e9 100644
@@ -15,3 +15,4 @@ sample_type=327
 mmap=0
 comm=0
 enable_on_exec=0
+disabled=0
tools/perf/tests/attr/test-record-group1 +1 -0
index 013572f..5a8359d 100644
@@ -16,3 +16,4 @@ sample_type=327
 mmap=0
 comm=0
 enable_on_exec=0
+disabled=0
tools/perf/util/evsel.c +41 -1

60 lines not on this page · raw message

Signature · 1 line
1.7.11.7
#4 lore raw

[tip:perf/core] perf tools: Fix 'disabled' attribute config for record command

Commit-ID:  774cb499ca9ab0e5950a149d1fe102b125da1cee
Gitweb:     http://git.kernel.org/tip/774cb499ca9ab0e5950a149d1fe102b125da1cee
Author:     Jiri Olsa <[email protected]>
AuthorDate: Mon, 12 Nov 2012 18:34:01 +0100
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 14 Nov 2012 16:52:03 -0300

perf tools: Fix 'disabled' attribute config for record command

Currently the record command sets all events initially as disabled.

There's non conditional perf_evlist__enable call, that enables all events before we exec tracee program. That actually screws whole enable_on_exec logic, because the event is enabled before the traced program got executed.

What we actually want is:

1) For any type of traced program:
- all independent events and group leaders are disabled
- all group members are enabled

Group members are ruled by group leaders. They need to be enabled, because the group scheduling relies on that.

2) For traced programs executed by perf:
- all independent events and group leaders have enable_on_exec set
- we don't specifically enable or disable any event during the record command

Independent events and group leaders are initially disabled and get enabled by exec. Group members are ruled by group leaders as stated in 1).

3) For traced programs attached by perf (pid/tid):
- we specifically enable or disable all events during the record command

When attaching events to already running traced we enable/disable events specifically, as there's no initial traced exec call.

Fixing appropriate perf_event_attr test case to cover this change.

---
 tools/perf/builtin-record.c              | 15 ++++++++++--
 tools/perf/tests/attr/test-record-group  |  1 +
 tools/perf/tests/attr/test-record-group1 |  1 +
 tools/perf/util/evsel.c                  | 42 +++++++++++++++++++++++++++++++-
 4 files changed, 56 insertions(+), 3 deletions(-)
tools/perf/builtin-record.c +13 -2
index 3717027..268b356 100644
@@ -701,7 +701,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 		}
 	}
 
-	perf_evlist__enable(evsel_list);
+	/*
+	 * When perf is starting the traced process, all the events
+	 * (apart from group members) have enable_on_exec=1 set,
+	 * so don't spoil it by prematurely enabling them.
+	 */
+	if (!perf_target__none(&opts->target))
+		perf_evlist__enable(evsel_list);
 
 	/*
 	 * Let the child rip
@@ -724,7 +730,12 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 			waking++;
 		}
 
-		if (done)
+		/*
+		 * When perf is starting the traced process, at the end events
+		 * die with the process and we wait for that. Thus no need to
+		 * disable events in this case.
+		 */
+		if (done && !perf_target__none(&opts->target))
 			perf_evlist__disable(evsel_list);
 	}
 
tools/perf/tests/attr/test-record-group +1 -0
index b945f77..a6599e9 100644
@@ -15,3 +15,4 @@ sample_type=327
 mmap=0
 comm=0
 enable_on_exec=0
+disabled=0
tools/perf/tests/attr/test-record-group1 +1 -0
index 013572f..5a8359d 100644
@@ -16,3 +16,4 @@ sample_type=327
 mmap=0
 comm=0
 enable_on_exec=0
+disabled=0
tools/perf/util/evsel.c +41 -1

60 lines not on this page · raw message

author
#5 lore raw

PATCH 3/5 perf tool: Ensure single disable call per event in record comand

In reply to Jiri Olsa

It's possible we issue the event disable ioctl multiple times until we read the final portion of the mmap buffer.

Ensuring just single disable ioctl call for event, because there's no need to do that more than once.

Cc Corey Ashford <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
---
 tools/perf/builtin-record.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
tools/perf/builtin-record.c +4 -1
index 268b356..f3151d3 100644
@@ -502,6 +502,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 	struct perf_evlist *evsel_list = rec->evlist;
 	const char *output_name = rec->output_name;
 	struct perf_session *session;
+	bool disabled = false;
 
 	rec->progname = argv[0];
 
@@ -735,8 +736,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 		 * die with the process and we wait for that. Thus no need to
 		 * disable events in this case.
 		 */
-		if (done && !perf_target__none(&opts->target))
+		if (done && !disabled && !perf_target__none(&opts->target)) {
 			perf_evlist__disable(evsel_list);
+			disabled = true;
+		}
 	}
 
 	if (quiet || signr == SIGUSR1)
Signature · 1 line
1.7.11.7
#6 lore raw

[tip:perf/core] perf tools: Ensure single disable call per event in record comand

Commit-ID:  2711926a416733b853977a0e014c713955ad0d8a
Gitweb:     http://git.kernel.org/tip/2711926a416733b853977a0e014c713955ad0d8a
Author:     Jiri Olsa <[email protected]>
AuthorDate: Mon, 12 Nov 2012 18:34:02 +0100
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 14 Nov 2012 16:52:09 -0300

perf tools: Ensure single disable call per event in record comand

It's possible we issue the event disable ioctl multiple times until we read the final portion of the mmap buffer.

Ensuring just single disable ioctl call for event, because there's no need to do that more than once.

---
 tools/perf/builtin-record.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
tools/perf/builtin-record.c +4 -1
index 268b356..f3151d3 100644
@@ -502,6 +502,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 	struct perf_evlist *evsel_list = rec->evlist;
 	const char *output_name = rec->output_name;
 	struct perf_session *session;
+	bool disabled = false;
 
 	rec->progname = argv[0];
 
@@ -735,8 +736,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 		 * die with the process and we wait for that. Thus no need to
 		 * disable events in this case.
 		 */
-		if (done && !perf_target__none(&opts->target))
+		if (done && !disabled && !perf_target__none(&opts->target)) {
 			perf_evlist__disable(evsel_list);
+			disabled = true;
+		}
 	}
 
 	if (quiet || signr == SIGUSR1)
author
#7 lore raw

PATCH 4/5 perf tool: Omit group members from perf_evlist__disable/enable

In reply to Jiri Olsa

There's no need to disable/enable ordinary group member events, because they are initialy enabled and get scheduled by the leader.

Cc Corey Ashford <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
---
 tools/perf/util/evlist.c | 4 ++++
 1 file changed, 4 insertions(+)
tools/perf/util/evlist.c +4 -0
index 04acae0..e9d2d5d 100644
@@ -222,6 +222,8 @@ void perf_evlist__disable(struct perf_evlist *evlist)
 
 	for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
 		list_for_each_entry(pos, &evlist->entries, node) {
+			if (pos->leader)
+				continue;
 			for (thread = 0; thread < evlist->threads->nr; thread++)
 				ioctl(FD(pos, cpu, thread),
 				      PERF_EVENT_IOC_DISABLE, 0);
@@ -236,6 +238,8 @@ void perf_evlist__enable(struct perf_evlist *evlist)
 
 	for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) {
 		list_for_each_entry(pos, &evlist->entries, node) {
+			if (pos->leader)
+				continue;
 			for (thread = 0; thread < evlist->threads->nr; thread++)
 				ioctl(FD(pos, cpu, thread),
 				      PERF_EVENT_IOC_ENABLE, 0);
Signature · 1 line
1.7.11.7
#8 lore raw

[tip:perf/core] perf tools: Omit group members from perf_evlist__disable/enable

Commit-ID:  3fe4430dd66837d8fcdb63c167e908655fc842e3
Gitweb:     http://git.kernel.org/tip/3fe4430dd66837d8fcdb63c167e908655fc842e3
Author:     Jiri Olsa <[email protected]>
AuthorDate: Mon, 12 Nov 2012 18:34:03 +0100
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 14 Nov 2012 16:52:15 -0300

perf tools: Omit group members from perf_evlist__disable/enable

There's no need to disable/enable ordinary group member events, because they are initialy enabled and get scheduled by the leader.

---
 tools/perf/util/evlist.c | 4 ++++
 1 file changed, 4 insertions(+)
tools/perf/util/evlist.c +4 -0
index 04acae0..e9d2d5d 100644
@@ -222,6 +222,8 @@ void perf_evlist__disable(struct perf_evlist *evlist)
 
 	for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
 		list_for_each_entry(pos, &evlist->entries, node) {
+			if (pos->leader)
+				continue;
 			for (thread = 0; thread < evlist->threads->nr; thread++)
 				ioctl(FD(pos, cpu, thread),
 				      PERF_EVENT_IOC_DISABLE, 0);
@@ -236,6 +238,8 @@ void perf_evlist__enable(struct perf_evlist *evlist)
 
 	for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) {
 		list_for_each_entry(pos, &evlist->entries, node) {
+			if (pos->leader)
+				continue;
 			for (thread = 0; thread < evlist->threads->nr; thread++)
 				ioctl(FD(pos, cpu, thread),
 				      PERF_EVENT_IOC_ENABLE, 0);
author
#9 lore raw

PATCH 5/5 perf tool: Add basic event modifier sanity check

In reply to Jiri Olsa

Updating event parser to allow any non zero string containing [ukhpGH] characters for event modifier.

The modifier sanity is checked later in parse-event object logic. The check validates modifier to contain only one instance of any modifier (apart from 'p') present.

Cc Corey Ashford <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
---
 tools/perf/util/parse-events.c | 20 ++++++++++++++++++++
 tools/perf/util/parse-events.l |  2 +-
 2 files changed, 21 insertions(+), 1 deletion(-)
tools/perf/util/parse-events.c +20 -0
index c0b785b..b321d43 100644
@@ -722,6 +722,23 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
 	return 0;
 }
 
+/*
+ * Basic modifier sanity check to validate it contains only one
+ * instance of any modifier (apart from 'p') present.
+ */
+static int check_modifier(char *str)
+{
+	char *p = str;
+
+	while (*p) {
+		if (*p != 'p' && strchr(p + 1, *p))
+			return -1;
+		p++;
+	}
+
+	return 0;
+}
+
 int parse_events__modifier_event(struct list_head *list, char *str, bool add)
 {
 	struct perf_evsel *evsel;
@@ -730,6 +747,9 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
 	if (str == NULL)
 		return 0;
 
+	if (check_modifier(str))
+		return -EINVAL;
+
 	if (!add && get_event_modifier(&mod, str, NULL))
 		return -EINVAL;
 
tools/perf/util/parse-events.l +1 -1
index 66959fa..e9d1134 100644
@@ -82,7 +82,7 @@ num_hex		0x[a-fA-F0-9]+
 num_raw_hex	[a-fA-F0-9]+
 name		[a-zA-Z_*?][a-zA-Z0-9_*?]*
 name_minus	[a-zA-Z_*?][a-zA-Z0-9\-_*?]*
-modifier_event	[ukhpGH]{1,8}
+modifier_event	[ukhpGH]+
 modifier_bp	[rwx]{1,3}
 
 %%
Signature · 1 line
1.7.11.7
maintainer
#10 lore raw

Re: [PATCH 5/5] perf tool: Add basic event modifier sanity check

Hi Jiri,

Quoted 6 lines · Jiri Olsa

Updating event parser to allow any non zero string containing [ukhpGH] characters for event modifier.

The modifier sanity is checked later in parse-event object logic. The check validates modifier to contain only one instance of any modifier (apart from 'p') present.

[snip]

tools/perf/util/parse-events.c static int get_event_modifier(struct event_modifier *mod, char *str, · line 737

Quoted 13 lines
tools/perf/util/parse-events.c +13 -0
+/*
+ * Basic modifier sanity check to validate it contains only one
+ * instance of any modifier (apart from 'p') present.
+ */
+static int check_modifier(char *str)
+{
+	char *p = str;
+
+	while (*p) {
+		if (*p != 'p' && strchr(p + 1, *p))
+			return -1;
+		p++;
+	}

How about adding a length check too? i.e. something like:

	if ((p - str) > strlen("ukhGHppp"))
        	return -1;

Thanks,
Namhyung

Quoted 30 lines
tools/perf/util/parse-events.c +7 -0
+
+	return 0;
+}
+
 int parse_events__modifier_event(struct list_head *list, char *str, bool add)
 {
 	struct perf_evsel *evsel;
@@ -730,6 +747,9 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
 	if (str == NULL)
 		return 0;
 
+	if (check_modifier(str))
+		return -EINVAL;
+
 	if (!add && get_event_modifier(&mod, str, NULL))
 		return -EINVAL;
 
tools/perf/util/parse-events.l +1 -1
index 66959fa..e9d1134 100644
@@ -82,7 +82,7 @@ num_hex		0x[a-fA-F0-9]+
 num_raw_hex	[a-fA-F0-9]+
 name		[a-zA-Z_*?][a-zA-Z0-9_*?]*
 name_minus	[a-zA-Z_*?][a-zA-Z0-9\-_*?]*
-modifier_event	[ukhpGH]{1,8}
+modifier_event	[ukhpGH]+
 modifier_bp	[rwx]{1,3}
 
 %%
author
#11 lore raw

PATCH v2 5/5 perf tool: Add basic event modifier sanity check

Quoted 26 lines · Namhyung Kim

Hi Jiri,

Quoted 6 lines · Jiri Olsa

Updating event parser to allow any non zero string containing [ukhpGH] characters for event modifier.

The modifier sanity is checked later in parse-event object logic. The check validates modifier to contain only one instance of any modifier (apart from 'p') present.

[snip]

Review

Quoted 13 lines
(quoted diff) +13 -0
+/*
+ * Basic modifier sanity check to validate it contains only one
+ * instance of any modifier (apart from 'p') present.
+ */
+static int check_modifier(char *str)
+{
+	char *p = str;
+
+	while (*p) {
+		if (*p != 'p' && strchr(p + 1, *p))
+			return -1;
+		p++;
+	}

How about adding a length check too? i.e. something like:

Quoted 2 lines
	if ((p - str) > strlen("ukhGHppp"))
        	return -1;

ok, v2 attached

thanks,
jirka

---
Updating event parser to allow any non zero string containing [ukhpGH] characters for event modifier.

The modifier sanity is checked later in parse-event object logic. The check validates modifier to contain only one instance of any modifier (apart from 'p') present.

v2:
- added length check suggested Namhyung Kim

Cc Corey Ashford <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Namhyung Kim <[email protected]>
---
 tools/perf/util/parse-events.c | 24 ++++++++++++++++++++++++
 tools/perf/util/parse-events.l |  2 +-
 2 files changed, 25 insertions(+), 1 deletion(-)
tools/perf/util/parse-events.c +24 -0
index c0b785b..020323a 100644
@@ -722,6 +722,27 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
 	return 0;
 }
 
+/*
+ * Basic modifier sanity check to validate it contains only one
+ * instance of any modifier (apart from 'p') present.
+ */
+static int check_modifier(char *str)
+{
+	char *p = str;
+
+	/* The sizeof includes 0 byte as well. */
+	if (strlen(str) > (sizeof("ukhGHppp") - 1))
+		return -1;
+
+	while (*p) {
+		if (*p != 'p' && strchr(p + 1, *p))
+			return -1;
+		p++;
+	}
+
+	return 0;
+}
+
 int parse_events__modifier_event(struct list_head *list, char *str, bool add)
 {
 	struct perf_evsel *evsel;
@@ -730,6 +751,9 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
 	if (str == NULL)
 		return 0;
 
+	if (check_modifier(str))
+		return -EINVAL;
+
 	if (!add && get_event_modifier(&mod, str, NULL))
 		return -EINVAL;
 
tools/perf/util/parse-events.l +1 -1
index 66959fa..e9d1134 100644
@@ -82,7 +82,7 @@ num_hex		0x[a-fA-F0-9]+
 num_raw_hex	[a-fA-F0-9]+
 name		[a-zA-Z_*?][a-zA-Z0-9_*?]*
 name_minus	[a-zA-Z_*?][a-zA-Z0-9\-_*?]*
-modifier_event	[ukhpGH]{1,8}
+modifier_event	[ukhpGH]+
 modifier_bp	[rwx]{1,3}
 
 %%
Signature · 1 line
1.7.11.7
#12 lore raw

[tip:perf/core] perf tools: Add basic event modifier sanity check

Commit-ID:  534123f458f196bcc269f97d20ccf125925c2e7b
Gitweb:     http://git.kernel.org/tip/534123f458f196bcc269f97d20ccf125925c2e7b
Author:     Jiri Olsa <[email protected]>
AuthorDate: Tue, 13 Nov 2012 15:32:58 +0100
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 14 Nov 2012 16:52:24 -0300

perf tools: Add basic event modifier sanity check

Updating event parser to allow any non zero string containing [ukhpGH] characters for event modifier.

The modifier sanity is checked later in parse-event object logic. The check validates modifier to contain only one instance of any modifier (apart from 'p') present.

v2:
- added length check suggested Namhyung Kim

---
 tools/perf/util/parse-events.c | 24 ++++++++++++++++++++++++
 tools/perf/util/parse-events.l |  2 +-
 2 files changed, 25 insertions(+), 1 deletion(-)
tools/perf/util/parse-events.c +24 -0
index c0b785b..020323a 100644
@@ -722,6 +722,27 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
 	return 0;
 }
 
+/*
+ * Basic modifier sanity check to validate it contains only one
+ * instance of any modifier (apart from 'p') present.
+ */
+static int check_modifier(char *str)
+{
+	char *p = str;
+
+	/* The sizeof includes 0 byte as well. */
+	if (strlen(str) > (sizeof("ukhGHppp") - 1))
+		return -1;
+
+	while (*p) {
+		if (*p != 'p' && strchr(p + 1, *p))
+			return -1;
+		p++;
+	}
+
+	return 0;
+}
+
 int parse_events__modifier_event(struct list_head *list, char *str, bool add)
 {
 	struct perf_evsel *evsel;
@@ -730,6 +751,9 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
 	if (str == NULL)
 		return 0;
 
+	if (check_modifier(str))
+		return -EINVAL;
+
 	if (!add && get_event_modifier(&mod, str, NULL))
 		return -EINVAL;
 
tools/perf/util/parse-events.l +1 -1
index 66959fa..e9d1134 100644
@@ -82,7 +82,7 @@ num_hex		0x[a-fA-F0-9]+
 num_raw_hex	[a-fA-F0-9]+
 name		[a-zA-Z_*?][a-zA-Z0-9_*?]*
 name_minus	[a-zA-Z_*?][a-zA-Z0-9\-_*?]*
-modifier_event	[ukhpGH]{1,8}
+modifier_event	[ukhpGH]+
 modifier_bp	[rwx]{1,3}
 
 %%
maintainer Acked-by on the v1 series
#13 lore raw
In reply to Jiri Olsa
Quoted 18 lines · Jiri Olsa

hi,
this patchset fixes the event enable/disable logic for record command (patches 1 - 4) plus small fix for event parsing (patch 5).

Attached patches:
1/5 perf tool: Fix attributes for '{}' defined event groups 2/5 perf tool: Fix 'disabled' attribute config for record command 3/5 perf tool: Ensure single disable call per event in record comand 4/5 perf tool: Omit group members from perf_evlist__disable/enable 5/5 perf tool: Add basic event modifier sanity check

Also available in:
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/linux.git
perf/enable5

thanks,
jirka

Quoted 7 lines
Cc Corey Ashford <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>

I commented on the patch 5/5, anyway looks good to me:

Thanks,
Namhyung