2012-08-03 14:01:49

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [GIT PULL 00/18] perf/core fixes and improvements

Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit 194f8dcbe9629d8e9346cf96345a9c0bbf0e67ae:

uprobes: __replace_page() needs munlock_vma_page() (2012-07-30 11:27:25 +0200)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux tags/perf-core-for-mingo

for you to fetch changes up to 7f309ed6453926a81e2a97d274f67f1e48f0d74c:

perf tools: Remove brace expansion from clean target (2012-08-03 10:46:32 -0300)

----------------------------------------------------------------
perf/core improvements and fixes

. Prep work for the DWARF CFI post unwinder, so that it doesn't
uses perf_session in lots of places, just evlist/evsel is enough.

. Make clean brace expansion fix for some shells, from Palmer Cox

. Warn user just once per guest kernel when not finding kernel info,
from David Ahern

. perf test fix from Jiri Olsa

. Fix error handling on event creation in perf top, from David Ahern

. Fix check on perf_target__strnerror, from Namhyung Kim

. Save the whole cmdline, from David Ahern

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>

----------------------------------------------------------------
Arnaldo Carvalho de Melo (7):
perf evsel: Precalculate the sample size
perf session: Use perf_evlist__sample_type more extensively
perf session: Use perf_evlist__sample_id_all more extensively
perf session: Use perf_evlist__id_hdr_size more extensively
perf evlist: Introduce perf_evlist__parse_sample
perf evsel: Adopt parse_sample method from perf_event
perf session: Remove no longer used synthesize_sample method

David Ahern (7):
perf top: Error handling for counter creation should parallel perf-record
perf tool: Save cmdline from user in file header vs what is passed to record
perf kvm: Use strtol for walking guestmount directory
perf tools: Introducing rblist
perf tools: Change strlist to use the new rblist
perf tools: Introduce intlist
perf kvm top: Limit guest kernel info message to once

Jiri Olsa (2):
perf test: Fix parse events automated tests
perf symbols: Fix array sizes for binary types arrays

Namhyung Kim (1):
perf target: Fix check on buffer size

Palmer Cox (1):
perf tools: Remove brace expansion from clean target

tools/perf/Makefile | 7 +-
tools/perf/builtin-record.c | 4 +-
tools/perf/builtin-report.c | 5 +-
tools/perf/builtin-test.c | 19 ++---
tools/perf/builtin-top.c | 23 +++++--
tools/perf/util/event.h | 3 -
tools/perf/util/evlist.c | 7 ++
tools/perf/util/evlist.h | 3 +
tools/perf/util/evsel.c | 15 ++--
tools/perf/util/evsel.h | 10 +--
tools/perf/util/header.c | 9 +++
tools/perf/util/intlist.c | 101 +++++++++++++++++++++++++++
tools/perf/util/intlist.h | 75 ++++++++++++++++++++
tools/perf/util/parse-events-test.c | 12 ++--
tools/perf/util/parse-options.c | 3 +
tools/perf/util/python.c | 6 +-
tools/perf/util/rblist.c | 107 ++++++++++++++++++++++++++++
tools/perf/util/rblist.h | 47 +++++++++++++
tools/perf/util/session.c | 48 +++++++------
tools/perf/util/session.h | 24 +------
tools/perf/util/strlist.c | 130 ++++++++++++++---------------------
tools/perf/util/strlist.h | 11 +--
tools/perf/util/symbol.c | 14 +++-
tools/perf/util/target.c | 2 +-
24 files changed, 498 insertions(+), 187 deletions(-)
create mode 100644 tools/perf/util/intlist.c
create mode 100644 tools/perf/util/intlist.h
create mode 100644 tools/perf/util/rblist.c
create mode 100644 tools/perf/util/rblist.h


2012-08-03 14:01:27

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 16/18] perf tools: Introduce intlist

From: David Ahern <[email protected]>

Built on rblist - like strlist. Used in the next patch.

Signed-off-by: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 2 +
tools/perf/util/intlist.c | 101 +++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/intlist.h | 75 +++++++++++++++++++++++++++++++++
3 files changed, 178 insertions(+), 0 deletions(-)
create mode 100644 tools/perf/util/intlist.c
create mode 100644 tools/perf/util/intlist.h

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 285f700..32912af 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -320,6 +320,7 @@ LIB_H += util/cgroup.h
LIB_H += $(TRACE_EVENT_DIR)event-parse.h
LIB_H += util/target.h
LIB_H += util/rblist.h
+LIB_H += util/intlist.h

LIB_OBJS += $(OUTPUT)util/abspath.o
LIB_OBJS += $(OUTPUT)util/alias.o
@@ -385,6 +386,7 @@ LIB_OBJS += $(OUTPUT)util/cpumap.o
LIB_OBJS += $(OUTPUT)util/cgroup.o
LIB_OBJS += $(OUTPUT)util/target.o
LIB_OBJS += $(OUTPUT)util/rblist.o
+LIB_OBJS += $(OUTPUT)util/intlist.o

BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o

diff --git a/tools/perf/util/intlist.c b/tools/perf/util/intlist.c
new file mode 100644
index 0000000..fd530dc
--- /dev/null
+++ b/tools/perf/util/intlist.c
@@ -0,0 +1,101 @@
+/*
+ * Based on intlist.c by:
+ * (c) 2009 Arnaldo Carvalho de Melo <[email protected]>
+ *
+ * Licensed under the GPLv2.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <linux/compiler.h>
+
+#include "intlist.h"
+
+static struct rb_node *intlist__node_new(struct rblist *rblist __used,
+ const void *entry)
+{
+ int i = (int)((long)entry);
+ struct rb_node *rc = NULL;
+ struct int_node *node = malloc(sizeof(*node));
+
+ if (node != NULL) {
+ node->i = i;
+ rc = &node->rb_node;
+ }
+
+ return rc;
+}
+
+static void int_node__delete(struct int_node *ilist)
+{
+ free(ilist);
+}
+
+static void intlist__node_delete(struct rblist *rblist __used,
+ struct rb_node *rb_node)
+{
+ struct int_node *node = container_of(rb_node, struct int_node, rb_node);
+
+ int_node__delete(node);
+}
+
+static int intlist__node_cmp(struct rb_node *rb_node, const void *entry)
+{
+ int i = (int)((long)entry);
+ struct int_node *node = container_of(rb_node, struct int_node, rb_node);
+
+ return node->i - i;
+}
+
+int intlist__add(struct intlist *ilist, int i)
+{
+ return rblist__add_node(&ilist->rblist, (void *)((long)i));
+}
+
+void intlist__remove(struct intlist *ilist __used, struct int_node *node)
+{
+ int_node__delete(node);
+}
+
+struct int_node *intlist__find(struct intlist *ilist, int i)
+{
+ struct int_node *node = NULL;
+ struct rb_node *rb_node = rblist__find(&ilist->rblist, (void *)((long)i));
+
+ if (rb_node)
+ node = container_of(rb_node, struct int_node, rb_node);
+
+ return node;
+}
+
+struct intlist *intlist__new(void)
+{
+ struct intlist *ilist = malloc(sizeof(*ilist));
+
+ if (ilist != NULL) {
+ rblist__init(&ilist->rblist);
+ ilist->rblist.node_cmp = intlist__node_cmp;
+ ilist->rblist.node_new = intlist__node_new;
+ ilist->rblist.node_delete = intlist__node_delete;
+ }
+
+ return ilist;
+}
+
+void intlist__delete(struct intlist *ilist)
+{
+ if (ilist != NULL)
+ rblist__delete(&ilist->rblist);
+}
+
+struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx)
+{
+ struct int_node *node = NULL;
+ struct rb_node *rb_node;
+
+ rb_node = rblist__entry(&ilist->rblist, idx);
+ if (rb_node)
+ node = container_of(rb_node, struct int_node, rb_node);
+
+ return node;
+}
diff --git a/tools/perf/util/intlist.h b/tools/perf/util/intlist.h
new file mode 100644
index 0000000..6d63ab9
--- /dev/null
+++ b/tools/perf/util/intlist.h
@@ -0,0 +1,75 @@
+#ifndef __PERF_INTLIST_H
+#define __PERF_INTLIST_H
+
+#include <linux/rbtree.h>
+#include <stdbool.h>
+
+#include "rblist.h"
+
+struct int_node {
+ struct rb_node rb_node;
+ int i;
+};
+
+struct intlist {
+ struct rblist rblist;
+};
+
+struct intlist *intlist__new(void);
+void intlist__delete(struct intlist *ilist);
+
+void intlist__remove(struct intlist *ilist, struct int_node *in);
+int intlist__add(struct intlist *ilist, int i);
+
+struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx);
+struct int_node *intlist__find(struct intlist *ilist, int i);
+
+static inline bool intlist__has_entry(struct intlist *ilist, int i)
+{
+ return intlist__find(ilist, i) != NULL;
+}
+
+static inline bool intlist__empty(const struct intlist *ilist)
+{
+ return rblist__empty(&ilist->rblist);
+}
+
+static inline unsigned int intlist__nr_entries(const struct intlist *ilist)
+{
+ return rblist__nr_entries(&ilist->rblist);
+}
+
+/* For intlist iteration */
+static inline struct int_node *intlist__first(struct intlist *ilist)
+{
+ struct rb_node *rn = rb_first(&ilist->rblist.entries);
+ return rn ? rb_entry(rn, struct int_node, rb_node) : NULL;
+}
+static inline struct int_node *intlist__next(struct int_node *in)
+{
+ struct rb_node *rn;
+ if (!in)
+ return NULL;
+ rn = rb_next(&in->rb_node);
+ return rn ? rb_entry(rn, struct int_node, rb_node) : NULL;
+}
+
+/**
+ * intlist_for_each - iterate over a intlist
+ * @pos: the &struct int_node to use as a loop cursor.
+ * @ilist: the &struct intlist for loop.
+ */
+#define intlist__for_each(pos, ilist) \
+ for (pos = intlist__first(ilist); pos; pos = intlist__next(pos))
+
+/**
+ * intlist_for_each_safe - iterate over a intlist safe against removal of
+ * int_node
+ * @pos: the &struct int_node to use as a loop cursor.
+ * @n: another &struct int_node to use as temporary storage.
+ * @ilist: the &struct intlist for loop.
+ */
+#define intlist__for_each_safe(pos, n, ilist) \
+ for (pos = intlist__first(ilist), n = intlist__next(pos); pos;\
+ pos = n, n = intlist__next(n))
+#endif /* __PERF_INTLIST_H */
--
1.7.1

2012-08-03 14:01:31

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 12/18] perf tool: Save cmdline from user in file header vs what is passed to record

From: David Ahern <[email protected]>

A number of builtin commands process some user args and then pass the rest to
cmd_record. cmd_record then saves argc/argv that it receives into the header of
the perf data file. But this loses the arguments handled by the first command
-- ie., the real command line from the user. This patch saves the command line
as typed by the user rather than what was passed to cmd_record.

As an example consider the command:
$ perf kvm --guest --host --guestmount=/tmp/guest-mount record
-fo /tmp/perf.data -ag -- sleep 10

Currently the command saved to the header is:
cmdline : /tmp/p3.5/perf record -o perf.data.kvm -fo /tmp/perf.data -ag -- sleep 1

(ignore the duplicated -o -- the first would be yet another bug with perf-kvm).

With this patch the command line saved to the header is:
cmdline : /tmp/p3.5/perf kvm --guest --host --guestmount=/tmp/guest-mount
record -fo /tmp/perf.data -ag -- sleep 1

v2: simplified to saving the command in parse_options per Stephane's suggestion

Signed-off-by: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-record.c | 2 --
tools/perf/util/header.c | 9 +++++++++
tools/perf/util/parse-options.c | 3 +++
3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index dc2b625..4db6e1b 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -844,8 +844,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
struct perf_record *rec = &record;
char errbuf[BUFSIZ];

- perf_header__set_cmdline(argc, argv);
-
evsel_list = perf_evlist__new(NULL, NULL);
if (evsel_list == NULL)
return -ENOMEM;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3a6d204..74ea3c2 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -174,6 +174,15 @@ perf_header__set_cmdline(int argc, const char **argv)
{
int i;

+ /*
+ * If header_argv has already been set, do not override it.
+ * This allows a command to set the cmdline, parse args and
+ * then call another builtin function that implements a
+ * command -- e.g, cmd_kvm calling cmd_record.
+ */
+ if (header_argv)
+ return 0;
+
header_argc = (u32)argc;

/* do not include NULL termination */
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 99d02aa..594f8fa 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -1,6 +1,7 @@
#include "util.h"
#include "parse-options.h"
#include "cache.h"
+#include "header.h"

#define OPT_SHORT 1
#define OPT_UNSET 2
@@ -413,6 +414,8 @@ int parse_options(int argc, const char **argv, const struct option *options,
{
struct parse_opt_ctx_t ctx;

+ perf_header__set_cmdline(argc, argv);
+
parse_options_start(&ctx, argc, argv, flags);
switch (parse_options_step(&ctx, options, usagestr)) {
case PARSE_OPT_HELP:
--
1.7.1

2012-08-03 14:02:01

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 02/18] perf symbols: Fix array sizes for binary types arrays

From: Jiri Olsa <[email protected]>

Following commit introduced wrong array boundaries, that could lead to
SIGSEGV.

perf symbols: Factor DSO symtab types to generic binary types
commit 44f24cb3156a1e7d2b6bb501b7f6153aed08994c
Author: Jiri Olsa <[email protected]>

Fixing to use proper array size.

Reported-by: Markus Trippelsdorf <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Markus Trippelsdorf <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/symbol.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index fdad4ee..fe86612 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -64,7 +64,7 @@ static enum dso_binary_type binary_type_symtab[] = {
DSO_BINARY_TYPE__NOT_FOUND,
};

-#define DSO_BINARY_TYPE__SYMTAB_CNT sizeof(binary_type_symtab)
+#define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab)

static enum dso_binary_type binary_type_data[] = {
DSO_BINARY_TYPE__BUILD_ID_CACHE,
@@ -72,7 +72,7 @@ static enum dso_binary_type binary_type_data[] = {
DSO_BINARY_TYPE__NOT_FOUND,
};

-#define DSO_BINARY_TYPE__DATA_CNT sizeof(binary_type_data)
+#define DSO_BINARY_TYPE__DATA_CNT ARRAY_SIZE(binary_type_data)

int dso__name_len(const struct dso *dso)
{
--
1.7.1

2012-08-03 14:01:54

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 09/18] perf evsel: Adopt parse_sample method from perf_event

From: Arnaldo Carvalho de Melo <[email protected]>

Since we need evsel->{attr.{sample_{id_all,type}},sample_size},
reducing the number of parameters tools have to pass.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/event.h | 3 ---
tools/perf/util/evlist.c | 6 ++----
tools/perf/util/evlist.h | 3 +--
tools/perf/util/evsel.c | 12 ++++++------
tools/perf/util/evsel.h | 2 ++
5 files changed, 11 insertions(+), 15 deletions(-)

diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 1b19728..d84870b 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -197,9 +197,6 @@ int perf_event__preprocess_sample(const union perf_event *self,

const char *perf_event__name(unsigned int id);

-int perf_event__parse_sample(const union perf_event *event, u64 type,
- int sample_size, bool sample_id_all,
- struct perf_sample *sample, bool swapped);
int perf_event__synthesize_sample(union perf_event *event, u64 type,
const struct perf_sample *sample,
bool swapped);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 1a560e0..9b38681 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -882,11 +882,9 @@ int perf_evlist__start_workload(struct perf_evlist *evlist)
return 0;
}

-int perf_evlist__parse_sample(struct perf_evlist *evlist,
- const union perf_event *event,
+int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
struct perf_sample *sample, bool swapped)
{
struct perf_evsel *e = list_entry(evlist->entries.next, struct perf_evsel, node);
- return perf_event__parse_sample(event, e->attr.sample_type, e->sample_size,
- e->attr.sample_id_all, sample, swapped);
+ return perf_evsel__parse_sample(e, event, sample, swapped);
}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index a5a4911..528c1ac 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -122,8 +122,7 @@ u64 perf_evlist__sample_type(const struct perf_evlist *evlist);
bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist);
u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist);

-int perf_evlist__parse_sample(struct perf_evlist *evlist,
- const union perf_event *event,
+int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
struct perf_sample *sample, bool swapped);

bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 8feec40..2eaae14 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -729,10 +729,10 @@ static bool sample_overlap(const union perf_event *event,
return false;
}

-int perf_event__parse_sample(const union perf_event *event, u64 type,
- int sample_size, bool sample_id_all,
+int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
struct perf_sample *data, bool swapped)
{
+ u64 type = evsel->attr.sample_type;
const u64 *array;

/*
@@ -747,14 +747,14 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
data->period = 1;

if (event->header.type != PERF_RECORD_SAMPLE) {
- if (!sample_id_all)
+ if (!evsel->attr.sample_id_all)
return 0;
return perf_event__parse_id_sample(event, type, data, swapped);
}

array = event->sample.array;

- if (sample_size + sizeof(event->header) > event->header.size)
+ if (evsel->sample_size + sizeof(event->header) > event->header.size)
return -EFAULT;

if (type & PERF_SAMPLE_IP) {
@@ -896,7 +896,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
u.val32[1] = sample->tid;
if (swapped) {
/*
- * Inverse of what is done in perf_event__parse_sample
+ * Inverse of what is done in perf_evsel__parse_sample
*/
u.val32[0] = bswap_32(u.val32[0]);
u.val32[1] = bswap_32(u.val32[1]);
@@ -931,7 +931,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
u.val32[0] = sample->cpu;
if (swapped) {
/*
- * Inverse of what is done in perf_event__parse_sample
+ * Inverse of what is done in perf_evsel__parse_sample
*/
u.val32[0] = bswap_32(u.val32[0]);
u.val64 = bswap_64(u.val64);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 894bd77..b559929 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -180,4 +180,6 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,

void hists__init(struct hists *hists);

+int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
+ struct perf_sample *sample, bool swapped);
#endif /* __PERF_EVSEL_H */
--
1.7.1

2012-08-03 14:01:58

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 10/18] perf session: Remove no longer used synthesize_sample method

From: Arnaldo Carvalho de Melo <[email protected]>

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/session.c | 8 --------
tools/perf/util/session.h | 4 ----
2 files changed, 0 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 7d07324..2437fb0 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -16,14 +16,6 @@
#include "cpumap.h"
#include "event-parse.h"

-int perf_session__synthesize_sample(struct perf_session *session,
- union perf_event *event,
- const struct perf_sample *sample)
-{
- return perf_event__synthesize_sample(event, perf_evlist__sample_type(session->evlist),
- sample, session->header.needs_swap);
-}
-
static int perf_session__open(struct perf_session *self, bool force)
{
struct stat input_stat;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 7389fb1..1f7ec87 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -126,10 +126,6 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *self,

size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);

-int perf_session__synthesize_sample(struct perf_session *session,
- union perf_event *event,
- const struct perf_sample *sample);
-
struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
unsigned int type);

--
1.7.1

2012-08-03 14:02:57

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 07/18] perf session: Use perf_evlist__id_hdr_size more extensively

From: Arnaldo Carvalho de Melo <[email protected]>

Removing perf_session->id_hdr_size, as it can be obtained from the
evsel/evlist.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-record.c | 2 +-
tools/perf/builtin-top.c | 2 +-
tools/perf/util/session.c | 13 +++++++------
tools/perf/util/session.h | 3 +--
4 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index f5a6452..dc2b625 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -313,7 +313,7 @@ try_again:
}
}

- perf_session__update_sample_type(session);
+ perf_session__set_id_hdr_size(session);
}

static int process_buildids(struct perf_record *rec)
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 35e86c6..520e425 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1032,7 +1032,7 @@ static int __cmd_top(struct perf_top *top)
&top->session->host_machine);
perf_top__start_counters(top);
top->session->evlist = top->evlist;
- perf_session__update_sample_type(top->session);
+ perf_session__set_id_hdr_size(top->session);

/* Wait for a minimal set of events before starting the snapshot */
poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 348cc11..5b8601d 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -101,11 +101,12 @@ out_close:
return -1;
}

-void perf_session__update_sample_type(struct perf_session *self)
+void perf_session__set_id_hdr_size(struct perf_session *session)
{
- self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist);
- self->host_machine.id_hdr_size = self->id_hdr_size;
- machines__set_id_hdr_size(&self->machines, self->id_hdr_size);
+ u16 id_hdr_size = perf_evlist__id_hdr_size(session->evlist);
+
+ session->host_machine.id_hdr_size = id_hdr_size;
+ machines__set_id_hdr_size(&session->machines, id_hdr_size);
}

int perf_session__create_kernel_maps(struct perf_session *self)
@@ -165,7 +166,7 @@ struct perf_session *perf_session__new(const char *filename, int mode,
if (mode == O_RDONLY) {
if (perf_session__open(self, force) < 0)
goto out_delete;
- perf_session__update_sample_type(self);
+ perf_session__set_id_hdr_size(self);
} else if (mode == O_WRONLY) {
/*
* In O_RDONLY mode this will be performed when reading the
@@ -1054,7 +1055,7 @@ static int perf_session__process_user_event(struct perf_session *session, union
case PERF_RECORD_HEADER_ATTR:
err = tool->attr(event, &session->evlist);
if (err == 0)
- perf_session__update_sample_type(session);
+ perf_session__set_id_hdr_size(session);
return err;
case PERF_RECORD_HEADER_EVENT_TYPE:
return tool->event_type(tool, event);
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index a2c3ce9..e2a1a4b 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -44,7 +44,6 @@ struct perf_session {
int fd;
bool fd_pipe;
bool repipe;
- u16 id_hdr_size;
int cwdlen;
char *cwd;
struct ordered_samples ordered_samples;
@@ -83,7 +82,7 @@ void perf_event__attr_swap(struct perf_event_attr *attr);

int perf_session__create_kernel_maps(struct perf_session *self);

-void perf_session__update_sample_type(struct perf_session *self);
+void perf_session__set_id_hdr_size(struct perf_session *session);
void perf_session__remove_thread(struct perf_session *self, struct thread *th);

static inline
--
1.7.1

2012-08-03 14:03:00

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 18/18] perf tools: Remove brace expansion from clean target

From: Palmer Cox <[email protected]>

The clean target uses brace expansion to remove some generated files. However,
the default shells on many systems do not support this feature resulting in
some generated files not being removed by clean.

Signed-off-by: Palmer Cox <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 32912af..35655c3 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -987,7 +987,8 @@ clean:
$(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
$(MAKE) -C Documentation/ clean
$(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS
- $(RM) $(OUTPUT)util/*-{bison,flex}*
+ $(RM) $(OUTPUT)util/*-bison*
+ $(RM) $(OUTPUT)util/*-flex*
$(python-clean)

.PHONY: all install clean strip $(LIBTRACEEVENT)
--
1.7.1

2012-08-03 14:03:04

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 08/18] perf evlist: Introduce perf_evlist__parse_sample

From: Arnaldo Carvalho de Melo <[email protected]>

That is a more compact form of perf_session__parse_sample and to support
multiple evlists per perf_session is the way to go anyway.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-test.c | 8 ++------
tools/perf/builtin-top.c | 2 +-
tools/perf/util/evlist.c | 9 +++++++++
tools/perf/util/evlist.h | 4 ++++
tools/perf/util/python.c | 6 +-----
tools/perf/util/session.c | 19 ++++---------------
tools/perf/util/session.h | 4 ----
7 files changed, 21 insertions(+), 31 deletions(-)

diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index e5032ed..1d592f5 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -562,9 +562,7 @@ static int test__basic_mmap(void)
goto out_munmap;
}

- err = perf_event__parse_sample(event, attr.sample_type,
- evsels[0]->sample_size,
- false, &sample, false);
+ err = perf_evlist__parse_sample(evlist, event, &sample, false);
if (err) {
pr_err("Can't parse sample, err = %d\n", err);
goto out_munmap;
@@ -781,9 +779,7 @@ static int test__PERF_RECORD(void)
if (type < PERF_RECORD_MAX)
nr_events[type]++;

- err = perf_event__parse_sample(event, evsel->attr.sample_type,
- evsel->sample_size, true,
- &sample, false);
+ err = perf_evlist__parse_sample(evlist, event, &sample, false);
if (err < 0) {
if (verbose)
perf_event__fprintf(event, stderr);
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 520e425..40264ea 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -811,7 +811,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
int ret;

while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) {
- ret = perf_session__parse_sample(session, event, &sample);
+ ret = perf_evlist__parse_sample(top->evlist, event, &sample, false);
if (ret) {
pr_err("Can't parse sample, err = %d\n", ret);
continue;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 3edfd34..1a560e0 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -881,3 +881,12 @@ int perf_evlist__start_workload(struct perf_evlist *evlist)

return 0;
}
+
+int perf_evlist__parse_sample(struct perf_evlist *evlist,
+ const union perf_event *event,
+ struct perf_sample *sample, bool swapped)
+{
+ struct perf_evsel *e = list_entry(evlist->entries.next, struct perf_evsel, node);
+ return perf_event__parse_sample(event, e->attr.sample_type, e->sample_size,
+ e->attr.sample_id_all, sample, swapped);
+}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 40d4d3c..a5a4911 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -122,6 +122,10 @@ u64 perf_evlist__sample_type(const struct perf_evlist *evlist);
bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist);
u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist);

+int perf_evlist__parse_sample(struct perf_evlist *evlist,
+ const union perf_event *event,
+ struct perf_sample *sample, bool swapped);
+
bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);
bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist);

diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index b0d6f85..0688bfb 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -797,17 +797,13 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,

event = perf_evlist__mmap_read(evlist, cpu);
if (event != NULL) {
- struct perf_evsel *first;
PyObject *pyevent = pyrf_event__new(event);
struct pyrf_event *pevent = (struct pyrf_event *)pyevent;

if (pyevent == NULL)
return PyErr_NoMemory();

- first = list_entry(evlist->entries.next, struct perf_evsel, node);
- err = perf_event__parse_sample(event, first->attr.sample_type,
- first->sample_size,
- sample_id_all, &pevent->sample, false);
+ err = perf_evlist__parse_sample(evlist, event, &pevent->sample, false);
if (err)
return PyErr_Format(PyExc_OSError,
"perf: can't parse sample, err=%d", err);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5b8601d..7d07324 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -16,19 +16,6 @@
#include "cpumap.h"
#include "event-parse.h"

-int perf_session__parse_sample(struct perf_session *session,
- const union perf_event *event,
- struct perf_sample *sample)
-{
- struct perf_evsel *first;
- first = list_entry(session->evlist->entries.next, struct perf_evsel, node);
-
- return perf_event__parse_sample(event, first->attr.sample_type,
- first->sample_size,
- first->attr.sample_id_all, sample,
- session->header.needs_swap);
-}
-
int perf_session__synthesize_sample(struct perf_session *session,
union perf_event *event,
const struct perf_sample *sample)
@@ -692,7 +679,8 @@ static void flush_sample_queue(struct perf_session *s,
if (iter->timestamp > limit)
break;

- ret = perf_session__parse_sample(s, iter->event, &sample);
+ ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample,
+ s->header.needs_swap);
if (ret)
pr_err("Can't parse sample, err = %d\n", ret);
else
@@ -1103,7 +1091,8 @@ static int perf_session__process_event(struct perf_session *session,
/*
* For all kernel events we get the sample data
*/
- ret = perf_session__parse_sample(session, event, &sample);
+ ret = perf_evlist__parse_sample(session->evlist, event, &sample,
+ session->header.needs_swap);
if (ret)
return ret;

diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index e2a1a4b..7389fb1 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -126,10 +126,6 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *self,

size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);

-int perf_session__parse_sample(struct perf_session *session,
- const union perf_event *event,
- struct perf_sample *sample);
-
int perf_session__synthesize_sample(struct perf_session *session,
union perf_event *event,
const struct perf_sample *sample);
--
1.7.1

2012-08-03 14:02:53

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 05/18] perf session: Use perf_evlist__sample_type more extensively

From: Arnaldo Carvalho de Melo <[email protected]>

Removing perf_session->sample_type, as it can be obtained from the
evsel/evlist.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-report.c | 5 +++--
tools/perf/builtin-test.c | 10 ++--------
tools/perf/util/session.c | 31 ++++++++++++++++++++++---------
tools/perf/util/session.h | 11 +++--------
4 files changed, 30 insertions(+), 27 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 69b1c11..7c88a24 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -249,8 +249,9 @@ static int process_read_event(struct perf_tool *tool,
static int perf_report__setup_sample_type(struct perf_report *rep)
{
struct perf_session *self = rep->session;
+ u64 sample_type = perf_evlist__sample_type(self->evlist);

- if (!self->fd_pipe && !(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
+ if (!self->fd_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
if (sort__has_parent) {
ui__error("Selected --sort parent, but no "
"callchain data. Did you call "
@@ -274,7 +275,7 @@ static int perf_report__setup_sample_type(struct perf_report *rep)

if (sort__branch_mode == 1) {
if (!self->fd_pipe &&
- !(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) {
+ !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
ui__error("Selected -b but no branch data. "
"Did you call perf record without -b?\n");
return -1;
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 2ea5fe4..e5032ed 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -661,7 +661,7 @@ static int test__PERF_RECORD(void)
const char *cmd = "sleep";
const char *argv[] = { cmd, "1", NULL, };
char *bname;
- u64 sample_type, prev_time = 0;
+ u64 prev_time = 0;
bool found_cmd_mmap = false,
found_libc_mmap = false,
found_vdso_mmap = false,
@@ -757,12 +757,6 @@ static int test__PERF_RECORD(void)
}

/*
- * We'll need these two to parse the PERF_SAMPLE_* fields in each
- * event.
- */
- sample_type = perf_evlist__sample_type(evlist);
-
- /*
* Now that all is properly set up, enable the events, they will
* count just on workload.pid, which will start...
*/
@@ -787,7 +781,7 @@ static int test__PERF_RECORD(void)
if (type < PERF_RECORD_MAX)
nr_events[type]++;

- err = perf_event__parse_sample(event, sample_type,
+ err = perf_event__parse_sample(event, evsel->attr.sample_type,
evsel->sample_size, true,
&sample, false);
if (err < 0) {
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index b8da60d..00e180e 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -23,12 +23,20 @@ int perf_session__parse_sample(struct perf_session *session,
struct perf_evsel *first;
first = list_entry(session->evlist->entries.next, struct perf_evsel, node);

- return perf_event__parse_sample(event, session->sample_type,
+ return perf_event__parse_sample(event, first->attr.sample_type,
first->sample_size,
session->sample_id_all, sample,
session->header.needs_swap);
}

+int perf_session__synthesize_sample(struct perf_session *session,
+ union perf_event *event,
+ const struct perf_sample *sample)
+{
+ return perf_event__synthesize_sample(event, perf_evlist__sample_type(session->evlist),
+ sample, session->header.needs_swap);
+}
+
static int perf_session__open(struct perf_session *self, bool force)
{
struct stat input_stat;
@@ -95,7 +103,6 @@ out_close:

void perf_session__update_sample_type(struct perf_session *self)
{
- self->sample_type = perf_evlist__sample_type(self->evlist);
self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist);
self->host_machine.id_hdr_size = self->id_hdr_size;
@@ -877,16 +884,18 @@ static void perf_session__print_tstamp(struct perf_session *session,
union perf_event *event,
struct perf_sample *sample)
{
+ u64 sample_type = perf_evlist__sample_type(session->evlist);
+
if (event->header.type != PERF_RECORD_SAMPLE &&
!session->sample_id_all) {
fputs("-1 -1 ", stdout);
return;
}

- if ((session->sample_type & PERF_SAMPLE_CPU))
+ if ((sample_type & PERF_SAMPLE_CPU))
printf("%u ", sample->cpu);

- if (session->sample_type & PERF_SAMPLE_TIME)
+ if (sample_type & PERF_SAMPLE_TIME)
printf("%" PRIu64 " ", sample->time);
}

@@ -911,6 +920,8 @@ static void dump_event(struct perf_session *session, union perf_event *event,
static void dump_sample(struct perf_session *session, union perf_event *event,
struct perf_sample *sample)
{
+ u64 sample_type;
+
if (!dump_trace)
return;

@@ -918,10 +929,12 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
event->header.misc, sample->pid, sample->tid, sample->ip,
sample->period, sample->addr);

- if (session->sample_type & PERF_SAMPLE_CALLCHAIN)
+ sample_type = perf_evlist__sample_type(session->evlist);
+
+ if (sample_type & PERF_SAMPLE_CALLCHAIN)
callchain__printf(sample);

- if (session->sample_type & PERF_SAMPLE_BRANCH_STACK)
+ if (sample_type & PERF_SAMPLE_BRANCH_STACK)
branch_stack__printf(sample);
}

@@ -1018,7 +1031,7 @@ static int perf_session__preprocess_sample(struct perf_session *session,
union perf_event *event, struct perf_sample *sample)
{
if (event->header.type != PERF_RECORD_SAMPLE ||
- !(session->sample_type & PERF_SAMPLE_CALLCHAIN))
+ !(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_CALLCHAIN))
return 0;

if (!ip_callchain__valid(sample->callchain, event)) {
@@ -1401,9 +1414,9 @@ int perf_session__process_events(struct perf_session *self,
return err;
}

-bool perf_session__has_traces(struct perf_session *self, const char *msg)
+bool perf_session__has_traces(struct perf_session *session, const char *msg)
{
- if (!(self->sample_type & PERF_SAMPLE_RAW)) {
+ if (!(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_RAW)) {
pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg);
return false;
}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 4d549e2..c45ce43 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -41,7 +41,6 @@ struct perf_session {
* perf.data file.
*/
struct hists hists;
- u64 sample_type;
int fd;
bool fd_pipe;
bool repipe;
@@ -133,13 +132,9 @@ int perf_session__parse_sample(struct perf_session *session,
const union perf_event *event,
struct perf_sample *sample);

-static inline int perf_session__synthesize_sample(struct perf_session *session,
- union perf_event *event,
- const struct perf_sample *sample)
-{
- return perf_event__synthesize_sample(event, session->sample_type,
- sample, session->header.needs_swap);
-}
+int perf_session__synthesize_sample(struct perf_session *session,
+ union perf_event *event,
+ const struct perf_sample *sample);

struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
unsigned int type);
--
1.7.1

2012-08-03 14:02:49

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 04/18] perf evsel: Precalculate the sample size

From: Arnaldo Carvalho de Melo <[email protected]>

So that we don't have to store it in the perf_session instance, because
in the future perf_session instances may have multiple evlists, each
with different sample_type/sizes.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-test.c | 9 ++++-----
tools/perf/util/evsel.c | 3 ++-
tools/perf/util/evsel.h | 8 +-------
tools/perf/util/python.c | 2 +-
tools/perf/util/session.c | 14 +++++++++++++-
tools/perf/util/session.h | 13 +++----------
6 files changed, 24 insertions(+), 25 deletions(-)

diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index d909eb7..2ea5fe4 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -478,7 +478,6 @@ static int test__basic_mmap(void)
unsigned int nr_events[nsyscalls],
expected_nr_events[nsyscalls], i, j;
struct perf_evsel *evsels[nsyscalls], *evsel;
- int sample_size = __perf_evsel__sample_size(attr.sample_type);

for (i = 0; i < nsyscalls; ++i) {
char name[64];
@@ -563,7 +562,8 @@ static int test__basic_mmap(void)
goto out_munmap;
}

- err = perf_event__parse_sample(event, attr.sample_type, sample_size,
+ err = perf_event__parse_sample(event, attr.sample_type,
+ evsels[0]->sample_size,
false, &sample, false);
if (err) {
pr_err("Can't parse sample, err = %d\n", err);
@@ -666,7 +666,7 @@ static int test__PERF_RECORD(void)
found_libc_mmap = false,
found_vdso_mmap = false,
found_ld_mmap = false;
- int err = -1, errs = 0, i, wakeups = 0, sample_size;
+ int err = -1, errs = 0, i, wakeups = 0;
u32 cpu;
int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };

@@ -761,7 +761,6 @@ static int test__PERF_RECORD(void)
* event.
*/
sample_type = perf_evlist__sample_type(evlist);
- sample_size = __perf_evsel__sample_size(sample_type);

/*
* Now that all is properly set up, enable the events, they will
@@ -789,7 +788,7 @@ static int test__PERF_RECORD(void)
nr_events[type]++;

err = perf_event__parse_sample(event, sample_type,
- sample_size, true,
+ evsel->sample_size, true,
&sample, false);
if (err < 0) {
if (verbose)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index e817713..8feec40 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -20,7 +20,7 @@
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))

-int __perf_evsel__sample_size(u64 sample_type)
+static int __perf_evsel__sample_size(u64 sample_type)
{
u64 mask = sample_type & PERF_SAMPLE_MASK;
int size = 0;
@@ -53,6 +53,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
evsel->attr = *attr;
INIT_LIST_HEAD(&evsel->node);
hists__init(&evsel->hists);
+ evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
}

struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 67cc503..894bd77 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -65,6 +65,7 @@ struct perf_evsel {
void *func;
void *data;
} handler;
+ unsigned int sample_size;
bool supported;
};

@@ -177,13 +178,6 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
return __perf_evsel__read(evsel, ncpus, nthreads, true);
}

-int __perf_evsel__sample_size(u64 sample_type);
-
-static inline int perf_evsel__sample_size(struct perf_evsel *evsel)
-{
- return __perf_evsel__sample_size(evsel->attr.sample_type);
-}
-
void hists__init(struct hists *hists);

#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index e03b58a..b0d6f85 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -806,7 +806,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,

first = list_entry(evlist->entries.next, struct perf_evsel, node);
err = perf_event__parse_sample(event, first->attr.sample_type,
- perf_evsel__sample_size(first),
+ first->sample_size,
sample_id_all, &pevent->sample, false);
if (err)
return PyErr_Format(PyExc_OSError,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 8e4f075..b8da60d 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -16,6 +16,19 @@
#include "cpumap.h"
#include "event-parse.h"

+int perf_session__parse_sample(struct perf_session *session,
+ const union perf_event *event,
+ struct perf_sample *sample)
+{
+ struct perf_evsel *first;
+ first = list_entry(session->evlist->entries.next, struct perf_evsel, node);
+
+ return perf_event__parse_sample(event, session->sample_type,
+ first->sample_size,
+ session->sample_id_all, sample,
+ session->header.needs_swap);
+}
+
static int perf_session__open(struct perf_session *self, bool force)
{
struct stat input_stat;
@@ -83,7 +96,6 @@ out_close:
void perf_session__update_sample_type(struct perf_session *self)
{
self->sample_type = perf_evlist__sample_type(self->evlist);
- self->sample_size = __perf_evsel__sample_size(self->sample_type);
self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist);
self->host_machine.id_hdr_size = self->id_hdr_size;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 7c435bd..4d549e2 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -42,7 +42,6 @@ struct perf_session {
*/
struct hists hists;
u64 sample_type;
- int sample_size;
int fd;
bool fd_pipe;
bool repipe;
@@ -130,15 +129,9 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *self,

size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);

-static inline int perf_session__parse_sample(struct perf_session *session,
- const union perf_event *event,
- struct perf_sample *sample)
-{
- return perf_event__parse_sample(event, session->sample_type,
- session->sample_size,
- session->sample_id_all, sample,
- session->header.needs_swap);
-}
+int perf_session__parse_sample(struct perf_session *session,
+ const union perf_event *event,
+ struct perf_sample *sample);

static inline int perf_session__synthesize_sample(struct perf_session *session,
union perf_event *event,
--
1.7.1

2012-08-03 14:02:46

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 06/18] perf session: Use perf_evlist__sample_id_all more extensively

From: Arnaldo Carvalho de Melo <[email protected]>

Removing perf_session->sample_id_all, as it can be obtained from the
evsel/evlist.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/session.c | 9 ++++-----
tools/perf/util/session.h | 1 -
2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 00e180e..348cc11 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -25,7 +25,7 @@ int perf_session__parse_sample(struct perf_session *session,

return perf_event__parse_sample(event, first->attr.sample_type,
first->sample_size,
- session->sample_id_all, sample,
+ first->attr.sample_id_all, sample,
session->header.needs_swap);
}

@@ -103,7 +103,6 @@ out_close:

void perf_session__update_sample_type(struct perf_session *self)
{
- self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist);
self->host_machine.id_hdr_size = self->id_hdr_size;
machines__set_id_hdr_size(&self->machines, self->id_hdr_size);
@@ -177,7 +176,7 @@ struct perf_session *perf_session__new(const char *filename, int mode,
}

if (tool && tool->ordering_requires_timestamps &&
- tool->ordered_samples && !self->sample_id_all) {
+ tool->ordered_samples && !perf_evlist__sample_id_all(self->evlist)) {
dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
tool->ordered_samples = false;
}
@@ -887,7 +886,7 @@ static void perf_session__print_tstamp(struct perf_session *session,
u64 sample_type = perf_evlist__sample_type(session->evlist);

if (event->header.type != PERF_RECORD_SAMPLE &&
- !session->sample_id_all) {
+ !perf_evlist__sample_id_all(session->evlist)) {
fputs("-1 -1 ", stdout);
return;
}
@@ -1090,7 +1089,7 @@ static int perf_session__process_event(struct perf_session *session,
int ret;

if (session->header.needs_swap)
- event_swap(event, session->sample_id_all);
+ event_swap(event, perf_evlist__sample_id_all(session->evlist));

if (event->header.type >= PERF_RECORD_HEADER_MAX)
return -EINVAL;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index c45ce43..a2c3ce9 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -44,7 +44,6 @@ struct perf_session {
int fd;
bool fd_pipe;
bool repipe;
- bool sample_id_all;
u16 id_hdr_size;
int cwdlen;
char *cwd;
--
1.7.1

2012-08-03 14:01:24

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 14/18] perf tools: Introducing rblist

From: David Ahern <[email protected]>

rblist is the rbtree based code from strlist. It will be the common code
for strlist and the to-be-introduced intlist.

Signed-off-by: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 2 +
tools/perf/util/rblist.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/rblist.h | 47 ++++++++++++++++++++
3 files changed, 156 insertions(+), 0 deletions(-)
create mode 100644 tools/perf/util/rblist.c
create mode 100644 tools/perf/util/rblist.h

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 77f124f..285f700 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -319,6 +319,7 @@ LIB_H += $(ARCH_INCLUDE)
LIB_H += util/cgroup.h
LIB_H += $(TRACE_EVENT_DIR)event-parse.h
LIB_H += util/target.h
+LIB_H += util/rblist.h

LIB_OBJS += $(OUTPUT)util/abspath.o
LIB_OBJS += $(OUTPUT)util/alias.o
@@ -383,6 +384,7 @@ LIB_OBJS += $(OUTPUT)util/xyarray.o
LIB_OBJS += $(OUTPUT)util/cpumap.o
LIB_OBJS += $(OUTPUT)util/cgroup.o
LIB_OBJS += $(OUTPUT)util/target.o
+LIB_OBJS += $(OUTPUT)util/rblist.o

BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o

diff --git a/tools/perf/util/rblist.c b/tools/perf/util/rblist.c
new file mode 100644
index 0000000..0171fb6
--- /dev/null
+++ b/tools/perf/util/rblist.c
@@ -0,0 +1,107 @@
+/*
+ * Based on strlist.c by:
+ * (c) 2009 Arnaldo Carvalho de Melo <[email protected]>
+ *
+ * Licensed under the GPLv2.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "rblist.h"
+
+int rblist__add_node(struct rblist *rblist, const void *new_entry)
+{
+ struct rb_node **p = &rblist->entries.rb_node;
+ struct rb_node *parent = NULL, *new_node;
+
+ while (*p != NULL) {
+ int rc;
+
+ parent = *p;
+
+ rc = rblist->node_cmp(parent, new_entry);
+ if (rc > 0)
+ p = &(*p)->rb_left;
+ else if (rc < 0)
+ p = &(*p)->rb_right;
+ else
+ return -EEXIST;
+ }
+
+ new_node = rblist->node_new(rblist, new_entry);
+ if (new_node == NULL)
+ return -ENOMEM;
+
+ rb_link_node(new_node, parent, p);
+ rb_insert_color(new_node, &rblist->entries);
+ ++rblist->nr_entries;
+
+ return 0;
+}
+
+void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node)
+{
+ rb_erase(rb_node, &rblist->entries);
+ rblist->node_delete(rblist, rb_node);
+}
+
+struct rb_node *rblist__find(struct rblist *rblist, const void *entry)
+{
+ struct rb_node **p = &rblist->entries.rb_node;
+ struct rb_node *parent = NULL;
+
+ while (*p != NULL) {
+ int rc;
+
+ parent = *p;
+
+ rc = rblist->node_cmp(parent, entry);
+ if (rc > 0)
+ p = &(*p)->rb_left;
+ else if (rc < 0)
+ p = &(*p)->rb_right;
+ else
+ return parent;
+ }
+
+ return NULL;
+}
+
+void rblist__init(struct rblist *rblist)
+{
+ if (rblist != NULL) {
+ rblist->entries = RB_ROOT;
+ rblist->nr_entries = 0;
+ }
+
+ return;
+}
+
+void rblist__delete(struct rblist *rblist)
+{
+ if (rblist != NULL) {
+ struct rb_node *pos, *next = rb_first(&rblist->entries);
+
+ while (next) {
+ pos = next;
+ next = rb_next(pos);
+ rb_erase(pos, &rblist->entries);
+ rblist->node_delete(rblist, pos);
+ }
+ free(rblist);
+ }
+}
+
+struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx)
+{
+ struct rb_node *node;
+
+ for (node = rb_first(&rblist->entries); node; node = rb_next(node)) {
+ if (!idx--)
+ return node;
+ }
+
+ return NULL;
+}
diff --git a/tools/perf/util/rblist.h b/tools/perf/util/rblist.h
new file mode 100644
index 0000000..6d0cae5
--- /dev/null
+++ b/tools/perf/util/rblist.h
@@ -0,0 +1,47 @@
+#ifndef __PERF_RBLIST_H
+#define __PERF_RBLIST_H
+
+#include <linux/rbtree.h>
+#include <stdbool.h>
+
+/*
+ * create node structs of the form:
+ * struct my_node {
+ * struct rb_node rb_node;
+ * ... my data ...
+ * };
+ *
+ * create list structs of the form:
+ * struct mylist {
+ * struct rblist rblist;
+ * ... my data ...
+ * };
+ */
+
+struct rblist {
+ struct rb_root entries;
+ unsigned int nr_entries;
+
+ int (*node_cmp)(struct rb_node *rbn, const void *entry);
+ struct rb_node *(*node_new)(struct rblist *rlist, const void *new_entry);
+ void (*node_delete)(struct rblist *rblist, struct rb_node *rb_node);
+};
+
+void rblist__init(struct rblist *rblist);
+void rblist__delete(struct rblist *rblist);
+int rblist__add_node(struct rblist *rblist, const void *new_entry);
+void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node);
+struct rb_node *rblist__find(struct rblist *rblist, const void *entry);
+struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx);
+
+static inline bool rblist__empty(const struct rblist *rblist)
+{
+ return rblist->nr_entries == 0;
+}
+
+static inline unsigned int rblist__nr_entries(const struct rblist *rblist)
+{
+ return rblist->nr_entries;
+}
+
+#endif /* __PERF_RBLIST_H */
--
1.7.1

2012-08-03 14:04:13

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 03/18] perf target: Fix check on buffer size

From: Namhyung Kim <[email protected]>

It was a mistake just replace assert to BUG_ON since its condition
should be negated. Fix it.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: "Kirill A. Shutemov" <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Kirill A. Shutemov <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Ulrich Drepper <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/target.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c
index 3f59c49..051eaa6 100644
--- a/tools/perf/util/target.c
+++ b/tools/perf/util/target.c
@@ -110,7 +110,7 @@ int perf_target__strerror(struct perf_target *target, int errnum,
int idx;
const char *msg;

- BUG_ON(buflen > 0);
+ BUG_ON(buflen == 0);

if (errnum >= 0) {
const char *err = strerror_r(errnum, buf, buflen);
--
1.7.1

2012-08-03 14:04:17

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 13/18] perf kvm: Use strtol for walking guestmount directory

From: David Ahern <[email protected]>

Only want to process directories under the guestmnount directory that
have a pid as a name (ie, all digits). Other entries in the guestmount
directory should be ignored. There is already a check that requires the
first character of each entry to be a digit, but atoi is used to convert
the directory name to a pid. For example if guestmount contains a
directory with the name 1foo, atoi converts it to a pid of 1 and a
machine is created with a pid of 1. This is wrong; this directory really
should be ignored. Use strtol to do that.

Signed-off-by: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/symbol.c | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index fe86612..8b63b67 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -2875,6 +2875,7 @@ int machines__create_guest_kernel_maps(struct rb_root *machines)
int i, items = 0;
char path[PATH_MAX];
pid_t pid;
+ char *endp;

if (symbol_conf.default_guest_vmlinux_name ||
symbol_conf.default_guest_modules ||
@@ -2891,7 +2892,14 @@ int machines__create_guest_kernel_maps(struct rb_root *machines)
/* Filter out . and .. */
continue;
}
- pid = atoi(namelist[i]->d_name);
+ pid = (pid_t)strtol(namelist[i]->d_name, &endp, 10);
+ if ((*endp != '\0') ||
+ (endp == namelist[i]->d_name) ||
+ (errno == ERANGE)) {
+ pr_debug("invalid directory (%s). Skipping.\n",
+ namelist[i]->d_name);
+ continue;
+ }
sprintf(path, "%s/%s/proc/kallsyms",
symbol_conf.guestmount,
namelist[i]->d_name);
--
1.7.1

2012-08-03 14:04:26

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 17/18] perf kvm top: Limit guest kernel info message to once

From: David Ahern <[email protected]>

'perf kvm top' shows a continual flurry of:
Can't find guest [5201]'s kernel information

if it can't find the guest info and with a lot of VMs running a user has no
chance of reading them all. Limit message to once per guest.

Signed-off-by: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-top.c | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 3409627..68cd61e 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -38,6 +38,7 @@
#include "util/cpumap.h"
#include "util/xyarray.h"
#include "util/sort.h"
+#include "util/intlist.h"

#include "util/debug.h"

@@ -706,8 +707,16 @@ static void perf_event__process_sample(struct perf_tool *tool,
int err;

if (!machine && perf_guest) {
- pr_err("Can't find guest [%d]'s kernel information\n",
- event->ip.pid);
+ static struct intlist *seen;
+
+ if (!seen)
+ seen = intlist__new();
+
+ if (!intlist__has_entry(seen, event->ip.pid)) {
+ pr_err("Can't find guest [%d]'s kernel information\n",
+ event->ip.pid);
+ intlist__add(seen, event->ip.pid);
+ }
return;
}

--
1.7.1

2012-08-03 14:04:22

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 01/18] perf test: Fix parse events automated tests

From: Jiri Olsa <[email protected]>

Parse events tests got broken after following commit:

perf tools: Fix trace events storms due to weight demux
commit 0983cc0dbca45250cbb5984bec7c303ac265b8e5
Author: Frederic Weisbecker <[email protected]>

that added PERF_SAMPLE_PERIOD sample type for tracepoints.

Updating related tests.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/parse-events-test.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index 1b997d2..127d648 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -13,6 +13,9 @@ do { \
} \
} while (0)

+#define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \
+ PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD)
+
static int test__checkevent_tracepoint(struct perf_evlist *evlist)
{
struct perf_evsel *evsel = list_entry(evlist->entries.next,
@@ -21,8 +24,7 @@ static int test__checkevent_tracepoint(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
TEST_ASSERT_VAL("wrong sample_type",
- (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) ==
- evsel->attr.sample_type);
+ PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
return 0;
}
@@ -37,8 +39,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong type",
PERF_TYPE_TRACEPOINT == evsel->attr.type);
TEST_ASSERT_VAL("wrong sample_type",
- (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU)
- == evsel->attr.sample_type);
+ PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
TEST_ASSERT_VAL("wrong sample_period",
1 == evsel->attr.sample_period);
}
@@ -428,8 +429,7 @@ static int test__checkevent_list(struct perf_evlist *evlist)
evsel = list_entry(evsel->node.next, struct perf_evsel, node);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
TEST_ASSERT_VAL("wrong sample_type",
- (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) ==
- evsel->attr.sample_type);
+ PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
--
1.7.1

2012-08-03 14:04:20

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 15/18] perf tools: Change strlist to use the new rblist

From: David Ahern <[email protected]>

Replaces the direct use of rbtree code with the rblist API. In the end
the patch is a no-op on strlist functionality; the API for strlist is
not changed, only its implementaton.

Signed-off-by: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/strlist.c | 130 ++++++++++++++++++---------------------------
tools/perf/util/strlist.h | 11 ++--
2 files changed, 57 insertions(+), 84 deletions(-)

diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c
index 6783a20..95856ff 100644
--- a/tools/perf/util/strlist.c
+++ b/tools/perf/util/strlist.c
@@ -10,23 +10,28 @@
#include <stdlib.h>
#include <string.h>

-static struct str_node *str_node__new(const char *s, bool dupstr)
+static
+struct rb_node *strlist__node_new(struct rblist *rblist, const void *entry)
{
- struct str_node *self = malloc(sizeof(*self));
+ const char *s = entry;
+ struct rb_node *rc = NULL;
+ struct strlist *strlist = container_of(rblist, struct strlist, rblist);
+ struct str_node *snode = malloc(sizeof(*snode));

- if (self != NULL) {
- if (dupstr) {
+ if (snode != NULL) {
+ if (strlist->dupstr) {
s = strdup(s);
if (s == NULL)
goto out_delete;
}
- self->s = s;
+ snode->s = s;
+ rc = &snode->rb_node;
}

- return self;
+ return rc;

out_delete:
- free(self);
+ free(snode);
return NULL;
}

@@ -37,36 +42,26 @@ static void str_node__delete(struct str_node *self, bool dupstr)
free(self);
}

-int strlist__add(struct strlist *self, const char *new_entry)
+static
+void strlist__node_delete(struct rblist *rblist, struct rb_node *rb_node)
{
- struct rb_node **p = &self->entries.rb_node;
- struct rb_node *parent = NULL;
- struct str_node *sn;
-
- while (*p != NULL) {
- int rc;
-
- parent = *p;
- sn = rb_entry(parent, struct str_node, rb_node);
- rc = strcmp(sn->s, new_entry);
-
- if (rc > 0)
- p = &(*p)->rb_left;
- else if (rc < 0)
- p = &(*p)->rb_right;
- else
- return -EEXIST;
- }
+ struct strlist *slist = container_of(rblist, struct strlist, rblist);
+ struct str_node *snode = container_of(rb_node, struct str_node, rb_node);

- sn = str_node__new(new_entry, self->dupstr);
- if (sn == NULL)
- return -ENOMEM;
+ str_node__delete(snode, slist->dupstr);
+}

- rb_link_node(&sn->rb_node, parent, p);
- rb_insert_color(&sn->rb_node, &self->entries);
- ++self->nr_entries;
+static int strlist__node_cmp(struct rb_node *rb_node, const void *entry)
+{
+ const char *str = entry;
+ struct str_node *snode = container_of(rb_node, struct str_node, rb_node);
+
+ return strcmp(snode->s, str);
+}

- return 0;
+int strlist__add(struct strlist *self, const char *new_entry)
+{
+ return rblist__add_node(&self->rblist, new_entry);
}

int strlist__load(struct strlist *self, const char *filename)
@@ -96,34 +91,20 @@ out:
return err;
}

-void strlist__remove(struct strlist *self, struct str_node *sn)
+void strlist__remove(struct strlist *slist, struct str_node *snode)
{
- rb_erase(&sn->rb_node, &self->entries);
- str_node__delete(sn, self->dupstr);
+ str_node__delete(snode, slist->dupstr);
}

-struct str_node *strlist__find(struct strlist *self, const char *entry)
+struct str_node *strlist__find(struct strlist *slist, const char *entry)
{
- struct rb_node **p = &self->entries.rb_node;
- struct rb_node *parent = NULL;
-
- while (*p != NULL) {
- struct str_node *sn;
- int rc;
-
- parent = *p;
- sn = rb_entry(parent, struct str_node, rb_node);
- rc = strcmp(sn->s, entry);
-
- if (rc > 0)
- p = &(*p)->rb_left;
- else if (rc < 0)
- p = &(*p)->rb_right;
- else
- return sn;
- }
+ struct str_node *snode = NULL;
+ struct rb_node *rb_node = rblist__find(&slist->rblist, entry);

- return NULL;
+ if (rb_node)
+ snode = container_of(rb_node, struct str_node, rb_node);
+
+ return snode;
}

static int strlist__parse_list_entry(struct strlist *self, const char *s)
@@ -156,9 +137,12 @@ struct strlist *strlist__new(bool dupstr, const char *slist)
struct strlist *self = malloc(sizeof(*self));

if (self != NULL) {
- self->entries = RB_ROOT;
+ rblist__init(&self->rblist);
+ self->rblist.node_cmp = strlist__node_cmp;
+ self->rblist.node_new = strlist__node_new;
+ self->rblist.node_delete = strlist__node_delete;
+
self->dupstr = dupstr;
- self->nr_entries = 0;
if (slist && strlist__parse_list(self, slist) != 0)
goto out_error;
}
@@ -171,30 +155,18 @@ out_error:

void strlist__delete(struct strlist *self)
{
- if (self != NULL) {
- struct str_node *pos;
- struct rb_node *next = rb_first(&self->entries);
-
- while (next) {
- pos = rb_entry(next, struct str_node, rb_node);
- next = rb_next(&pos->rb_node);
- strlist__remove(self, pos);
- }
- self->entries = RB_ROOT;
- free(self);
- }
+ if (self != NULL)
+ rblist__delete(&self->rblist);
}

-struct str_node *strlist__entry(const struct strlist *self, unsigned int idx)
+struct str_node *strlist__entry(const struct strlist *slist, unsigned int idx)
{
- struct rb_node *nd;
+ struct str_node *snode = NULL;
+ struct rb_node *rb_node;

- for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
- struct str_node *pos = rb_entry(nd, struct str_node, rb_node);
+ rb_node = rblist__entry(&slist->rblist, idx);
+ if (rb_node)
+ snode = container_of(rb_node, struct str_node, rb_node);

- if (!idx--)
- return pos;
- }
-
- return NULL;
+ return snode;
}
diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h
index 3ba8390..dd9f922 100644
--- a/tools/perf/util/strlist.h
+++ b/tools/perf/util/strlist.h
@@ -4,14 +4,15 @@
#include <linux/rbtree.h>
#include <stdbool.h>

+#include "rblist.h"
+
struct str_node {
struct rb_node rb_node;
const char *s;
};

struct strlist {
- struct rb_root entries;
- unsigned int nr_entries;
+ struct rblist rblist;
bool dupstr;
};

@@ -32,18 +33,18 @@ static inline bool strlist__has_entry(struct strlist *self, const char *entry)

static inline bool strlist__empty(const struct strlist *self)
{
- return self->nr_entries == 0;
+ return rblist__empty(&self->rblist);
}

static inline unsigned int strlist__nr_entries(const struct strlist *self)
{
- return self->nr_entries;
+ return rblist__nr_entries(&self->rblist);
}

/* For strlist iteration */
static inline struct str_node *strlist__first(struct strlist *self)
{
- struct rb_node *rn = rb_first(&self->entries);
+ struct rb_node *rn = rb_first(&self->rblist.entries);
return rn ? rb_entry(rn, struct str_node, rb_node) : NULL;
}
static inline struct str_node *strlist__next(struct str_node *sn)
--
1.7.1

2012-08-03 14:04:08

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 11/18] perf top: Error handling for counter creation should parallel perf-record

From: David Ahern <[email protected]>

5a7ed29 fixed up perf-record but not perf-top. Similar argument holds
for it -- fallback to PMU only if it does not exist and handle invalid
attributes separately.

Signed-off-by: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Robert Richter <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-top.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 40264ea..3409627 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -943,8 +943,10 @@ try_again:
* based cpu-clock-tick sw counter, which
* is always available even if no PMU support:
*/
- if (attr->type == PERF_TYPE_HARDWARE &&
- attr->config == PERF_COUNT_HW_CPU_CYCLES) {
+ if ((err == ENOENT || err == ENXIO) &&
+ (attr->type == PERF_TYPE_HARDWARE) &&
+ (attr->config == PERF_COUNT_HW_CPU_CYCLES)) {
+
if (verbose)
ui__warning("Cycles event not supported,\n"
"trying to fall back to cpu-clock-ticks\n");
--
1.7.1

2012-08-03 14:15:54

by Kirill A. Shutemov

[permalink] [raw]
Subject: Re: [PATCH 03/18] perf target: Fix check on buffer size

On Fri, Aug 03, 2012 at 11:00:55AM -0300, Arnaldo Carvalho de Melo wrote:
> From: Namhyung Kim <[email protected]>
>
> It was a mistake just replace assert to BUG_ON since its condition
> should be negated. Fix it.
>
> Signed-off-by: Namhyung Kim <[email protected]>
> Cc: "Kirill A. Shutemov" <[email protected]>
> Cc: Ingo Molnar <[email protected]>
> Cc: Kirill A. Shutemov <[email protected]>
> Cc: Paul Mackerras <[email protected]>
> Cc: Peter Zijlstra <[email protected]>
> Cc: Ulrich Drepper <[email protected]>
> Link: http://lkml.kernel.org/r/[email protected]
> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>

Acked-by: Kirill A. Shutemov <[email protected]>

--
Kirill A. Shutemov

2012-08-03 15:24:31

by David Ahern

[permalink] [raw]
Subject: Re: [PATCH 08/18] perf evlist: Introduce perf_evlist__parse_sample

On 8/3/12 8:01 AM, Arnaldo Carvalho de Melo wrote:
> From: Arnaldo Carvalho de Melo <[email protected]>
>
> That is a more compact form of perf_session__parse_sample and to support
> multiple evlists per perf_session is the way to go anyway.

So then all events in an evlist will have the same sample type? If you
want different sample types (at some point in the future) you will have
to create separate evlists?

David

2012-08-03 17:28:40

by Stephane Eranian

[permalink] [raw]
Subject: Re: [PATCH 08/18] perf evlist: Introduce perf_evlist__parse_sample

On Fri, Aug 3, 2012 at 5:24 PM, David Ahern <[email protected]> wrote:
> On 8/3/12 8:01 AM, Arnaldo Carvalho de Melo wrote:
>>
>> From: Arnaldo Carvalho de Melo <[email protected]>
>>
>> That is a more compact form of perf_session__parse_sample and to support
>> multiple evlists per perf_session is the way to go anyway.
>
>
> So then all events in an evlist will have the same sample type? If you want
> different sample types (at some point in the future) you will have to create
> separate evlists?
>
Yes, you do want separate sample_type, otherwise you may be wasting a lot
of buffer space and thus disk space for data you don't want. This is especially
true once you start using the branch stack feature. But for that the
kernel buffer
format has to be extended. I have a patch that does that. Just haven't
had the time
to finish the perf support for it.

2012-08-05 10:41:02

by Ingo Molnar

[permalink] [raw]
Subject: Re: [GIT PULL 00/18] perf/core fixes and improvements


* Arnaldo Carvalho de Melo <[email protected]> wrote:

> Hi Ingo,
>
> Please consider pulling,
>
> - Arnaldo
>
> The following changes since commit 194f8dcbe9629d8e9346cf96345a9c0bbf0e67ae:
>
> uprobes: __replace_page() needs munlock_vma_page() (2012-07-30 11:27:25 +0200)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux tags/perf-core-for-mingo
>
> for you to fetch changes up to 7f309ed6453926a81e2a97d274f67f1e48f0d74c:
>
> perf tools: Remove brace expansion from clean target (2012-08-03 10:46:32 -0300)
>
> ----------------------------------------------------------------
> perf/core improvements and fixes
>
> . Prep work for the DWARF CFI post unwinder, so that it doesn't
> uses perf_session in lots of places, just evlist/evsel is enough.
>
> . Make clean brace expansion fix for some shells, from Palmer Cox
>
> . Warn user just once per guest kernel when not finding kernel info,
> from David Ahern
>
> . perf test fix from Jiri Olsa
>
> . Fix error handling on event creation in perf top, from David Ahern
>
> . Fix check on perf_target__strnerror, from Namhyung Kim
>
> . Save the whole cmdline, from David Ahern
>
> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
>
> ----------------------------------------------------------------
> Arnaldo Carvalho de Melo (7):
> perf evsel: Precalculate the sample size
> perf session: Use perf_evlist__sample_type more extensively
> perf session: Use perf_evlist__sample_id_all more extensively
> perf session: Use perf_evlist__id_hdr_size more extensively
> perf evlist: Introduce perf_evlist__parse_sample
> perf evsel: Adopt parse_sample method from perf_event
> perf session: Remove no longer used synthesize_sample method
>
> David Ahern (7):
> perf top: Error handling for counter creation should parallel perf-record
> perf tool: Save cmdline from user in file header vs what is passed to record
> perf kvm: Use strtol for walking guestmount directory
> perf tools: Introducing rblist
> perf tools: Change strlist to use the new rblist
> perf tools: Introduce intlist
> perf kvm top: Limit guest kernel info message to once
>
> Jiri Olsa (2):
> perf test: Fix parse events automated tests
> perf symbols: Fix array sizes for binary types arrays
>
> Namhyung Kim (1):
> perf target: Fix check on buffer size
>
> Palmer Cox (1):
> perf tools: Remove brace expansion from clean target
>
> tools/perf/Makefile | 7 +-
> tools/perf/builtin-record.c | 4 +-
> tools/perf/builtin-report.c | 5 +-
> tools/perf/builtin-test.c | 19 ++---
> tools/perf/builtin-top.c | 23 +++++--
> tools/perf/util/event.h | 3 -
> tools/perf/util/evlist.c | 7 ++
> tools/perf/util/evlist.h | 3 +
> tools/perf/util/evsel.c | 15 ++--
> tools/perf/util/evsel.h | 10 +--
> tools/perf/util/header.c | 9 +++
> tools/perf/util/intlist.c | 101 +++++++++++++++++++++++++++
> tools/perf/util/intlist.h | 75 ++++++++++++++++++++
> tools/perf/util/parse-events-test.c | 12 ++--
> tools/perf/util/parse-options.c | 3 +
> tools/perf/util/python.c | 6 +-
> tools/perf/util/rblist.c | 107 ++++++++++++++++++++++++++++
> tools/perf/util/rblist.h | 47 +++++++++++++
> tools/perf/util/session.c | 48 +++++++------
> tools/perf/util/session.h | 24 +------
> tools/perf/util/strlist.c | 130 ++++++++++++++---------------------
> tools/perf/util/strlist.h | 11 +--
> tools/perf/util/symbol.c | 14 +++-
> tools/perf/util/target.c | 2 +-
> 24 files changed, 498 insertions(+), 187 deletions(-)
> create mode 100644 tools/perf/util/intlist.c
> create mode 100644 tools/perf/util/intlist.h
> create mode 100644 tools/perf/util/rblist.c
> create mode 100644 tools/perf/util/rblist.h

Pulled, thanks Arnaldo!

Ingo

2012-08-06 03:59:45

by Namhyung Kim

[permalink] [raw]
Subject: Re: [PATCH 03/18] perf target: Fix check on buffer size

Hi, Arnaldo

On Fri, 3 Aug 2012 17:17:03 +0300, Kirill A. Shutemov wrote:
> On Fri, Aug 03, 2012 at 11:00:55AM -0300, Arnaldo Carvalho de Melo wrote:
>> From: Namhyung Kim <[email protected]>
>>
>> It was a mistake just replace assert to BUG_ON since its condition
>> should be negated. Fix it.
>>
>> Signed-off-by: Namhyung Kim <[email protected]>
>> Cc: "Kirill A. Shutemov" <[email protected]>
>> Cc: Ingo Molnar <[email protected]>
>> Cc: Kirill A. Shutemov <[email protected]>
>> Cc: Paul Mackerras <[email protected]>
>> Cc: Peter Zijlstra <[email protected]>
>> Cc: Ulrich Drepper <[email protected]>
>> Link: http://lkml.kernel.org/r/[email protected]
>> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
>
> Acked-by: Kirill A. Shutemov <[email protected]>

I think this should go to the urgent branch too as the offending patch
seemed to go to the mainline already.

Thanks,
Namhyung

2012-08-06 04:14:51

by David Ahern

[permalink] [raw]
Subject: Re: [PATCH 03/18] perf target: Fix check on buffer size

On 8/5/12 9:53 PM, Namhyung Kim wrote:
>
> I think this should go to the urgent branch too as the offending patch
> seemed to go to the mainline already.
>

It was picked up by Ingo today and included in his pull request sent to
Linus.

David

2012-08-06 04:22:31

by Namhyung Kim

[permalink] [raw]
Subject: Re: [PATCH 03/18] perf target: Fix check on buffer size

Hi, David

On Sun, 05 Aug 2012 22:14:42 -0600, David Ahern wrote:
> On 8/5/12 9:53 PM, Namhyung Kim wrote:
>>
>> I think this should go to the urgent branch too as the offending patch
>> seemed to go to the mainline already.
>>
>
> It was picked up by Ingo today and included in his pull request sent
> to Linus.
>

Oh, I didn't see the mail for some reason. Thanks for pointing it out.

Thanks,
Namhyung