public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Corey Ashford <cjashfor@linux.vnet.ibm.com>
To: LKML <linux-kernel@vger.kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@elte.hu>,
	Frederic Weisbecker <fweisbec@gmail.com>
Subject: [RFC] [PATCH 1/1] perf: add support for arch-dependent symbolic event names to "perf stat"
Date: Wed, 03 Mar 2010 18:30:48 -0800	[thread overview]
Message-ID: <4B8F1B58.5000702@linux.vnet.ibm.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1762 bytes --]

For your review, this patch adds support for arch-dependent symbolic event names 
to the "perf stat" tool, and could be expanded to other "perf *" commands fairly 
easily, I suspect.

To support arch-dependent event names without adding arch-dependent code to 
perf, I added a callout mechanism whereby perf will look for the environment 
variable: PERF_ARCH_DEP_LIB, and if it exists, it will try to open it as a 
shared object.  If that succeeds, it looks for the symbol 
"parse_arch_dep_event".  If that exists, that function will be called by 
parse_events() before all of the other event parsing functions in 
parse-events.c.  It is passed the same arguments as the other parse_*_event 
functions, namely the event string and a pointer to an event attribute structure.

As the code existed, "perf stat" would print out the count results, but for raw 
events (which is how arch-dependent events are supported in perf_events), it 
would just print out a raw code.  This is not acceptable, especially when a 
symbolic name was placed on the command line.  So I changed the code to save 
away the event name that was passed on the command line, rather than doing a 
reverse translation to an event string based on the event type and config fields 
of the attr structure.  In this way, there's no need for a reverse translation 
function in the arch-dependent library; only a event string->attr struct 
function is needed.

I could well be missing something, but I don't understand why reverse 
translation is ever needed in perf, as long as the tool keeps track of the 
original event strings.

Thanks for your consideration,

- Corey

Corey Ashford
Software Engineer
IBM Linux Technology Center, Linux Toolchain
Beaverton, OR
503-578-3507
cjashfor@us.ibm.com


[-- Attachment #2: perf_symbolic_event.diff --]
[-- Type: text/plain, Size: 4284 bytes --]

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 54a5b50..20d3255 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -199,7 +199,7 @@ ifndef PERF_DEBUG
 endif
 
 CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
-EXTLIBS = -lpthread -lrt -lelf -lm
+EXTLIBS = -lpthread -lrt -lelf -lm -ldl
 ALL_CFLAGS = $(CFLAGS)
 ALL_LDFLAGS = $(LDFLAGS)
 STRIP ?= strip
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 05d0c5c..ba4a663 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -8,11 +8,13 @@
 #include "cache.h"
 #include "header.h"
 #include "debugfs.h"
+#include "dlfcn.h"
 
 int				nr_counters;
 
 struct perf_event_attr		attrs[MAX_COUNTERS];
 char				*filters[MAX_COUNTERS];
+char 				*event_names[MAX_COUNTERS];
 
 struct event_symbol {
 	u8		type;
@@ -267,10 +269,7 @@ static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
 
 const char *event_name(int counter)
 {
-	u64 config = attrs[counter].config;
-	int type = attrs[counter].type;
-
-	return __event_name(type, config);
+	return event_names[counter];
 }
 
 const char *__event_name(int type, u64 config)
@@ -324,6 +323,38 @@ const char *__event_name(int type, u64 config)
 	return "unknown";
 }
 
+#define PERF_ARCH_DEP_LIB_ENV_VAR "PERF_ARCH_DEP_LIB"
+
+static int arch_dep_lib_initialized = 0;
+static int (*parse_arch_dep_event_callout)(const char **strp,
+				   	   struct perf_event_attr *attr) = NULL;
+
+static void initialize_arch_dep_lib(void)
+{
+	char *lib_name = getenv(PERF_ARCH_DEP_LIB_ENV_VAR);
+	void *lib_handle;
+
+	if (!lib_name)
+		return;
+
+	lib_handle = dlopen(lib_name, RTLD_NOW);
+	if (!lib_handle) {
+		fprintf(stderr, "The environment variable %s is set to %s, "
+				"but we couldn't open it.  error: %s\n",
+				PERF_ARCH_DEP_LIB_ENV_VAR, lib_name, dlerror());
+		exit(1);
+	}
+	parse_arch_dep_event_callout = dlsym(lib_handle, "parse_arch_dep_event");
+	if (!parse_arch_dep_event_callout) {
+		fprintf(stderr, "The environment variable %s is set to %s, "
+				"but we couldn't obtain from it the required function - "
+				"parse_arch_dep_event.  error: %s\n",
+				PERF_ARCH_DEP_LIB_ENV_VAR, lib_name, dlerror());
+		exit(1);
+	}
+	arch_dep_lib_initialized = 1;
+}
+
 static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size)
 {
 	int i, j;
@@ -686,6 +717,18 @@ parse_numeric_event(const char **strp, struct perf_event_attr *attr)
 	return EVT_FAILED;
 }
 
+static int
+parse_arch_dep_event(const char **strp, struct perf_event_attr *attr)
+{
+	if (! arch_dep_lib_initialized)
+		initialize_arch_dep_lib();
+
+	if (arch_dep_lib_initialized)
+		return parse_arch_dep_event_callout(strp, attr);
+	else
+		return 0;
+}
+
 static enum event_result
 parse_event_modifier(const char **strp, struct perf_event_attr *attr)
 {
@@ -724,6 +767,11 @@ parse_event_symbols(const char **str, struct perf_event_attr *attr)
 {
 	enum event_result ret;
 
+	ret = parse_arch_dep_event(str, attr);
+	if (ret != EVT_FAILED)
+		/* modifiers are already processed */
+		return ret;
+
 	ret = parse_tracepoint_event(str, attr);
 	if (ret != EVT_FAILED)
 		goto modifier;
@@ -784,6 +832,17 @@ static int store_event_type(const char *orgname)
 	return perf_header__push_event(id, orgname);
 }
 
+static char *make_substr(char *start, char *end)
+{
+	int length = end - start;
+	char *result = malloc(length + 1);
+
+	strncpy(result, start, length);
+	result[length] = '\0';
+
+	return result;
+}
+
 int parse_events(const struct option *opt __used, const char *str, int unset __used)
 {
 	struct perf_event_attr attr;
@@ -794,19 +853,23 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
 			return -1;
 
 	for (;;) {
+		char *start, *end;
 		if (nr_counters == MAX_COUNTERS)
 			return -1;
 
 		memset(&attr, 0, sizeof(attr));
+		start = (char *)str;
 		ret = parse_event_symbols(&str, &attr);
 		if (ret == EVT_FAILED)
 			return -1;
 
 		if (!(*str == 0 || *str == ',' || isspace(*str)))
 			return -1;
+		end = (char *)str;
 
 		if (ret != EVT_HANDLED_ALL) {
 			attrs[nr_counters] = attr;
+			event_names[nr_counters] = make_substr(start, end);
 			nr_counters++;
 		}
 

             reply	other threads:[~2010-03-04  2:31 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-03-04  2:30 Corey Ashford [this message]
2010-03-04 18:39 ` [RFC] [PATCH 1/1] perf: add support for arch-dependent symbolic event names to "perf stat" Corey Ashford
2010-03-11 12:46   ` Ingo Molnar
2010-03-11 18:47     ` Corey Ashford
2010-03-11 19:14       ` Ingo Molnar
2010-03-11 20:46         ` Corey Ashford
2010-03-15 23:38           ` Corey Ashford
2010-03-16  9:40             ` Ingo Molnar
2010-03-16 18:24               ` Corey Ashford
2010-03-12  2:41     ` Paul Mackerras
2010-03-12  6:53       ` Corey Ashford
2010-03-16  9:34       ` Ingo Molnar
2010-03-05 17:42 ` Corey Ashford

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4B8F1B58.5000702@linux.vnet.ibm.com \
    --to=cjashfor@linux.vnet.ibm.com \
    --cc=fweisbec@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=peterz@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox