2009-07-06 08:32:00

by Chris Wilson

[permalink] [raw]
Subject: [PATCH 1/2] perfcounters: Fix build for tracepoint profiling

Signed-off-by: Chris Wilson <[email protected]>
---
init/Kconfig | 2 +-
kernel/perf_counter.c | 10 +++-------
2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/init/Kconfig b/init/Kconfig
index 0e8784e..13473ac 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -955,7 +955,7 @@ config PERF_COUNTERS

config EVENT_PROFILE
bool "Tracepoint profile sources"
- depends on PERF_COUNTERS && EVENT_TRACER
+ depends on PERF_COUNTERS && EVENT_TRACING
default y

endmenu
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index d55a50d..c6c38fb 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -3671,7 +3671,7 @@ static const struct pmu perf_ops_task_clock = {
void perf_tpcounter_event(int event_id)
{
struct perf_sample_data data = {
- .regs = get_irq_regs();
+ .regs = get_irq_regs(),
.addr = 0,
};

@@ -3687,16 +3687,12 @@ extern void ftrace_profile_disable(int);

static void tp_perf_counter_destroy(struct perf_counter *counter)
{
- ftrace_profile_disable(perf_event_id(&counter->attr));
+ ftrace_profile_disable(counter->attr.config);
}

static const struct pmu *tp_perf_counter_init(struct perf_counter *counter)
{
- int event_id = perf_event_id(&counter->attr);
- int ret;
-
- ret = ftrace_profile_enable(event_id);
- if (ret)
+ if (ftrace_profile_enable(counter->attr.config))
return NULL;

counter->destroy = tp_perf_counter_destroy;
--
1.6.3.3


2009-07-06 08:31:50

by Chris Wilson

[permalink] [raw]
Subject: [PATCH 2/2] perf tool: Add a trace point event parser.

Accept events of the form tp=i915/i915_wait and convert those to the
ftrace event id by expanding the short name to
'/sys/kernel/debug/tracing/events/i915/i915_wait/id'. (Substituting the
real debugfs mount path as appropriate.)

Signed-off-by: Chris Wilson <[email protected]>
---
tools/perf/util/parse-events.c | 133 +++++++++++++++++++++++++++++++++++++++-
1 files changed, 131 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 5184959..36078a6 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,11 +1,12 @@
-
-#include "../perf.h"
#include "util.h"
+#include "../perf.h"
#include "parse-options.h"
#include "parse-events.h"
#include "exec_cmd.h"
#include "string.h"

+#include <sys/mount.h>
+
extern char *strcasestr(const char *haystack, const char *needle);

int nr_counters;
@@ -339,6 +340,133 @@ parse_numeric_event(const char **strp, struct perf_counter_attr *attr)
return 0;
}

+/* mini /proc/mounts parser: searching for "^blah /mount/point debugfs" */
+static const char *
+debug_mntpt (void)
+{
+ static char mntpt[4096];
+ FILE *file;
+ size_t line_len;
+ char *line;
+
+ if (mntpt[0])
+ return mntpt;
+
+ file = fopen("/proc/mounts", "r");
+ if (file == NULL)
+ return NULL;
+
+ while (getline(&line, &line_len, file) >= 0) {
+ char *start, *end;
+
+ if (strstr(line, " debugfs ") == NULL)
+ continue;
+
+ start = strchr(line, ' ') + 1;
+ end = strchr(start + 1, ' ');
+ if(end - start > 4095)
+ goto err_file;
+ memcpy(mntpt, start, end-start);
+ break;
+ }
+ free(line);
+ fclose(file);
+
+ if (mntpt[0] == '\0') {
+ if (mount("none", "/sys/kernel/debug", "debugfs", 0, NULL))
+ return NULL;
+
+ strcpy(mntpt, "/sys/kernel/debug");
+ }
+
+ return mntpt;
+
+err_file:
+ free(line);
+ fclose(file);
+ return NULL;
+}
+
+static int
+safe_strcat(char **strp, int *rem, const char *src, int len)
+{
+ if (len < 0)
+ len = strlen(src);
+ if (len >= *rem)
+ return 0;
+
+ memcpy(*strp, src, len);
+ *strp += len;
+ *rem -= len;
+ **strp = '\0';
+
+ return 1;
+}
+
+static int
+parse_tracepoint_event(const char **strp, struct perf_counter_attr *attr)
+{
+ const char *str = *strp;
+ const char *mntpt;
+ char buf[4096], *bufp;
+ int rem;
+ int fd;
+ int ret;
+ char *comma;
+
+ if (strncmp(str, "tp=", 3))
+ return 0;
+
+ str += 3;
+
+ /* Expand the tracepoint event to:
+ * /sys/kernel/debug/tracing/events/<tracepoint>/id
+ * and then read that file to determine the ftrace event id to
+ * pass to perf_counters. Substituting the real debugfs mount path
+ * as appropriate.
+ */
+
+ mntpt = debug_mntpt();
+ if (mntpt == NULL)
+ return 0;
+
+ bufp = buf, rem = sizeof(buf);
+ if (!safe_strcat(&bufp, &rem, mntpt, -1))
+ return 0;
+ if (!safe_strcat(&bufp, &rem, "/tracing/events/", -1))
+ return 0;
+
+ comma = strchr(str, ',');
+ if (comma) {
+ if (!safe_strcat(&bufp, &rem, str, comma - str))
+ return 0;
+ *strp = comma;
+ } else {
+ if (!safe_strcat(&bufp, &rem, str, -1))
+ return 0;
+ *strp = str + strlen (str);
+ }
+ if (!safe_strcat(&bufp, &rem, "/id", -1))
+ return 0;
+
+ fd = open(buf, O_RDONLY);
+ if (fd == 0)
+ return 0;
+
+ /* We expect to read a string of "integer\n". */
+ ret = read(fd, buf, sizeof(buf));
+ close(fd);
+ if (ret == -1 || ret == sizeof(buf))
+ return 0;
+
+ buf[ret] = '\0';
+
+ attr->config = strtoul(buf, &bufp, 0);
+ attr->type = PERF_TYPE_TRACEPOINT;
+
+ return bufp == buf + ret-1;
+}
+
static int
parse_event_modifier(const char **strp, struct perf_counter_attr *attr)
{
@@ -377,6 +505,7 @@ static int parse_event_symbols(const char **str, struct perf_counter_attr *attr)
if (!(parse_raw_event(str, attr) ||
parse_numeric_event(str, attr) ||
parse_symbolic_event(str, attr) ||
+ parse_tracepoint_event(str, attr) ||
parse_generic_hw_event(str, attr)))
return 0;

--
1.6.3.3

2009-07-10 09:22:44

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 2/2] perf tool: Add a trace point event parser.


* Chris Wilson <[email protected]> wrote:

> Accept events of the form tp=i915/i915_wait and convert those to the
> ftrace event id by expanding the short name to
> '/sys/kernel/debug/tracing/events/i915/i915_wait/id'. (Substituting the
> real debugfs mount path as appropriate.)
>
> Signed-off-by: Chris Wilson <[email protected]>
> ---
> tools/perf/util/parse-events.c | 133 +++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 131 insertions(+), 2 deletions(-)

Ok - this looks useful. Mind working with Jason Baron (Cc:-ed) who
incidentally posted a similar series on some joint solution?

Thanks,

Ingo

2009-07-13 09:02:05

by Chris Wilson

[permalink] [raw]
Subject: [tip:perfcounters/urgent] perf_counter: Fix the tracepoint channel to perfcounters

Commit-ID: d4d7d0b9545721d3cabb19d15163bbc66b797707
Gitweb: http://git.kernel.org/tip/d4d7d0b9545721d3cabb19d15163bbc66b797707
Author: Chris Wilson <[email protected]>
AuthorDate: Mon, 6 Jul 2009 09:31:33 +0100
Committer: Ingo Molnar <[email protected]>
CommitDate: Mon, 13 Jul 2009 09:23:10 +0200

perf_counter: Fix the tracepoint channel to perfcounters

Fix a missed rename in EVENT_PROFILE support so that it gets
built and allows tracepoint tracing from the 'perf' tool.

Fix a typo in the (never before built & enabled) portion in
perf_counter.c as well, and update that code to the
attr.config changes as well.

Signed-off-by: Chris Wilson <[email protected]>
Cc: Ben Gamari <[email protected]>
Cc: Jason Baron <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Steven Rostedt <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>


---
init/Kconfig | 2 +-
kernel/perf_counter.c | 10 +++-------
2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/init/Kconfig b/init/Kconfig
index 1ce05a4..cb2c092 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -962,7 +962,7 @@ config PERF_COUNTERS

config EVENT_PROFILE
bool "Tracepoint profile sources"
- depends on PERF_COUNTERS && EVENT_TRACER
+ depends on PERF_COUNTERS && EVENT_TRACING
default y

endmenu
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index d55a50d..c6c38fb 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -3671,7 +3671,7 @@ static const struct pmu perf_ops_task_clock = {
void perf_tpcounter_event(int event_id)
{
struct perf_sample_data data = {
- .regs = get_irq_regs();
+ .regs = get_irq_regs(),
.addr = 0,
};

@@ -3687,16 +3687,12 @@ extern void ftrace_profile_disable(int);

static void tp_perf_counter_destroy(struct perf_counter *counter)
{
- ftrace_profile_disable(perf_event_id(&counter->attr));
+ ftrace_profile_disable(counter->attr.config);
}

static const struct pmu *tp_perf_counter_init(struct perf_counter *counter)
{
- int event_id = perf_event_id(&counter->attr);
- int ret;
-
- ret = ftrace_profile_enable(event_id);
- if (ret)
+ if (ftrace_profile_enable(counter->attr.config))
return NULL;

counter->destroy = tp_perf_counter_destroy;