mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Frederic Weisbecker <fweisbec@gmail.com>
To: Ingo Molnar <mingo@elte.hu>
Cc: LKML <linux-kernel@vger.kernel.org>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Arnaldo Carvalho de Melo <acme@redhat.com>,
	Steven Rostedt <rostedt@goodmis.org>,
	Paul Mackerras <paulus@samba.org>,
	Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>,
	Li Zefan <lizf@cn.fujitsu.com>,
	Lai Jiangshan <laijs@cn.fujitsu.com>,
	Masami Hiramatsu <mhiramat@redhat.com>,
	Jens Axboe <jens.axboe@oracle.com>
Subject: [PATCH 08/11] perf/lock: Add support for lock_class_init events
Date: Wed,  3 Feb 2010 10:14:32 +0100	[thread overview]
Message-ID: <1265188475-23509-9-git-send-regression-fweisbec@gmail.com> (raw)
In-Reply-To: <1265188475-23509-1-git-send-regression-fweisbec@gmail.com>

Add support for the new lock_class_init event from perf lock.
Retrieve the name of the locks from these events and remove
support of the name from other lock events.

Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
Cc: Li Zefan <lizf@cn.fujitsu.com>
Cc: Lai Jiangshan <laijs@cn.fujitsu.com>
Cc: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Jens Axboe <jens.axboe@oracle.com>
---
 tools/perf/builtin-lock.c |  197 +++++++++++++++++++++++++++++++++++++--------
 1 files changed, 163 insertions(+), 34 deletions(-)

diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index fb9ab2a..e1133b7 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -28,24 +28,38 @@
 #define LOCKHASH_SIZE		(1UL << LOCKHASH_BITS)
 
 static struct list_head lockhash_table[LOCKHASH_SIZE];
+static struct list_head classhash_table[LOCKHASH_SIZE];
 
 #define __lockhashfn(key)	hash_long((unsigned long)key, LOCKHASH_BITS)
 #define lockhashentry(key)	(lockhash_table + __lockhashfn((key)))
+#define classhashentry(key)	(classhash_table + __lockhashfn((key)))
 
 #define LOCK_STATE_UNLOCKED	0	       /* initial state */
 #define LOCK_STATE_LOCKED	1
 
+/*
+ * Can be extended for class scope profiling
+ */
+struct class_stat {
+	struct list_head	hash_entry;
+	void			*addr;
+	char			*name;
+	struct list_head	lock_list;
+};
+
 struct lock_stat {
 	struct list_head	hash_entry;
 	struct rb_node		rb;		/* used for sorting */
 
+	struct list_head	lock_list;	/* list in the class */
+
 	/*
 	 * FIXME: raw_field_value() returns unsigned long long,
 	 * so address of lockdep_map should be dealed as 64bit.
 	 * Is there more better solution?
 	 */
 	void			*addr;		/* address of lockdep_map, used as ID */
-	char			*name;		/* for strcpy(), we cannot use const */
+	struct class_stat	*class;
 
 	int			state;
 	u64			prev_event_time; /* timestamp of previous event */
@@ -155,34 +169,89 @@ static struct lock_stat *pop_from_result(void)
 	return container_of(node, struct lock_stat, rb);
 }
 
-static struct lock_stat *lock_stat_findnew(void *addr, const char *name)
+static void class_add_lock(struct class_stat *class, struct lock_stat *lock)
+{
+	if (!class)
+		return;
+
+	/* NOTE: we may want to handle class changes in the future */
+	list_del(&lock->lock_list);
+	list_add_tail(&lock->lock_list, &class->lock_list);
+	lock->class = class;
+}
+
+static struct lock_stat *lock_stat_findnew(void *addr, struct class_stat *class)
 {
 	struct list_head *entry = lockhashentry(addr);
-	struct lock_stat *ret, *new;
+	struct lock_stat *ret;
+
+	if (class) {
+		list_for_each_entry(ret, &class->lock_list, lock_list) {
+			if (ret->addr == addr)
+				return ret;
+		}
+	}
 
 	list_for_each_entry(ret, entry, hash_entry) {
-		if (ret->addr == addr)
+		if (ret->addr == addr) {
+			class_add_lock(class, ret);
 			return ret;
+		}
 	}
 
-	new = zalloc(sizeof(struct lock_stat));
-	if (!new)
+	ret = zalloc(sizeof(struct lock_stat));
+	if (!ret)
 		goto alloc_failed;
 
-	new->addr = addr;
-	new->name = zalloc(sizeof(char) * strlen(name) + 1);
-	if (!new->name)
-		goto alloc_failed;
-	strcpy(new->name, name);
+	ret->addr = addr;
+	INIT_LIST_HEAD(&ret->lock_list);
+	class_add_lock(class, ret);
 
 	/* LOCK_STATE_UNLOCKED == 0 isn't guaranteed forever */
-	new->state = LOCK_STATE_UNLOCKED;
-	new->wait_time_min = ULLONG_MAX;
+	ret->state = LOCK_STATE_UNLOCKED;
+	ret->wait_time_min = ULLONG_MAX;
+
+	list_add_tail(&ret->hash_entry, entry);
+
+	return ret;
 
-	list_add(&new->hash_entry, entry);
-	return new;
+ alloc_failed:
+	die("memory allocation failed\n");
+}
+
+static struct class_stat *class_stat_findnew(void *addr, const char *name)
+{
+	struct list_head *entry = classhashentry(addr);
+	struct class_stat *ret;
+
+	list_for_each_entry(ret, entry, hash_entry) {
+		if (ret->addr == addr) {
+			if (!ret->name && name) {
+				ret->name = strdup(name);
+				if (!ret->name)
+					goto alloc_failed;
+			}
+			return ret;
+		}
+	}
+
+	ret = zalloc(sizeof(struct class_stat));
+	if (!ret)
+		goto alloc_failed;
+
+	ret->addr = addr;
+	INIT_LIST_HEAD(&ret->lock_list);
+	if (name) {
+		ret->name = strdup(name);
+		if (!ret->name)
+			goto alloc_failed;
+	}
+
+	list_add_tail(&ret->hash_entry, entry);
 
-alloc_failed:
+	return ret;
+
+ alloc_failed:
 	die("memory allocation failed\n");
 }
 
@@ -195,23 +264,29 @@ struct raw_event_sample {
 	char			data[0];
 };
 
+/*
+ * For now we keep the below as is with only one field.
+ * These structures may be filled further
+ */
 struct trace_acquire_event {
 	void			*addr;
-	const char		*name;
+	void			*class_id;
 };
 
 struct trace_acquired_event {
 	void			*addr;
-	const char		*name;
 };
 
 struct trace_contended_event {
 	void			*addr;
-	const char		*name;
 };
 
 struct trace_release_event {
 	void			*addr;
+};
+
+struct trace_init_event {
+	void			*class_id;
 	const char		*name;
 };
 
@@ -239,6 +314,12 @@ struct trace_lock_handler {
 			      int cpu,
 			      u64 timestamp,
 			      struct thread *thread);
+
+	void (*init_event)(struct trace_init_event *,
+			      struct event *,
+			      int cpu,
+			      u64 timestamp,
+			      struct thread *thread);
 };
 
 static void
@@ -248,11 +329,13 @@ report_lock_acquire_event(struct trace_acquire_event *acquire_event,
 			u64 timestamp,
 			struct thread *thread __used)
 {
-	struct lock_stat *st;
+	struct class_stat *class;
+	struct lock_stat *lock;
 
-	st = lock_stat_findnew(acquire_event->addr, acquire_event->name);
+	class = class_stat_findnew(acquire_event->class_id, NULL);
+	lock = lock_stat_findnew(acquire_event->addr, class);
 
-	switch (st->state) {
+	switch (lock->state) {
 	case LOCK_STATE_UNLOCKED:
 		break;
 	case LOCK_STATE_LOCKED:
@@ -262,7 +345,7 @@ report_lock_acquire_event(struct trace_acquire_event *acquire_event,
 		break;
 	}
 
-	st->prev_event_time = timestamp;
+	lock->prev_event_time = timestamp;
 }
 
 static void
@@ -274,7 +357,7 @@ report_lock_acquired_event(struct trace_acquired_event *acquired_event,
 {
 	struct lock_stat *st;
 
-	st = lock_stat_findnew(acquired_event->addr, acquired_event->name);
+	st = lock_stat_findnew(acquired_event->addr, NULL);
 
 	switch (st->state) {
 	case LOCK_STATE_UNLOCKED:
@@ -300,7 +383,7 @@ report_lock_contended_event(struct trace_contended_event *contended_event,
 {
 	struct lock_stat *st;
 
-	st = lock_stat_findnew(contended_event->addr, contended_event->name);
+	st = lock_stat_findnew(contended_event->addr, NULL);
 
 	switch (st->state) {
 	case LOCK_STATE_UNLOCKED:
@@ -326,7 +409,7 @@ report_lock_release_event(struct trace_release_event *release_event,
 	struct lock_stat *st;
 	u64 hold_time;
 
-	st = lock_stat_findnew(release_event->addr, release_event->name);
+	st = lock_stat_findnew(release_event->addr, NULL);
 
 	switch (st->state) {
 	case LOCK_STATE_UNLOCKED:
@@ -357,6 +440,16 @@ end:
 	st->prev_event_time = timestamp;
 }
 
+static void
+report_lock_class_init_event(struct trace_init_event *init_event,
+			struct event *__event __used,
+			int cpu __used,
+			u64 timestamp __used,
+			struct thread *thread __used)
+{
+	class_stat_findnew(init_event->class_id, init_event->name);
+}
+
 /* lock oriented handlers */
 /* TODO: handlers for CPU oriented, thread oriented */
 static struct trace_lock_handler report_lock_ops  = {
@@ -364,6 +457,7 @@ static struct trace_lock_handler report_lock_ops  = {
 	.acquired_event		= report_lock_acquired_event,
 	.contended_event	= report_lock_contended_event,
 	.release_event		= report_lock_release_event,
+	.init_event		= report_lock_class_init_event,
 };
 
 static struct trace_lock_handler *trace_handler;
@@ -380,7 +474,8 @@ process_lock_acquire_event(void *data,
 
 	tmp = raw_field_value(event, "lockdep_addr", data);
 	memcpy(&acquire_event.addr, &tmp, sizeof(void *));
-	acquire_event.name = (char *)raw_field_ptr(event, "name", data);
+	tmp = raw_field_value(event, "class_id", data);
+	memcpy(&acquire_event.class_id, &tmp, sizeof(void *));
 
 	if (trace_handler->acquire_event)
 		trace_handler->acquire_event(&acquire_event, event, cpu, timestamp, thread);
@@ -398,7 +493,6 @@ process_lock_acquired_event(void *data,
 
 	tmp = raw_field_value(event, "lockdep_addr", data);
 	memcpy(&acquired_event.addr, &tmp, sizeof(void *));
-	acquired_event.name = (char *)raw_field_ptr(event, "name", data);
 
 	if (trace_handler->acquire_event)
 		trace_handler->acquired_event(&acquired_event, event, cpu, timestamp, thread);
@@ -416,7 +510,6 @@ process_lock_contended_event(void *data,
 
 	tmp = raw_field_value(event, "lockdep_addr", data);
 	memcpy(&contended_event.addr, &tmp, sizeof(void *));
-	contended_event.name = (char *)raw_field_ptr(event, "name", data);
 
 	if (trace_handler->acquire_event)
 		trace_handler->contended_event(&contended_event, event, cpu, timestamp, thread);
@@ -434,13 +527,30 @@ process_lock_release_event(void *data,
 
 	tmp = raw_field_value(event, "lockdep_addr", data);
 	memcpy(&release_event.addr, &tmp, sizeof(void *));
-	release_event.name = (char *)raw_field_ptr(event, "name", data);
 
 	if (trace_handler->acquire_event)
 		trace_handler->release_event(&release_event, event, cpu, timestamp, thread);
 }
 
 static void
+process_lock_class_init_event(void *data,
+			struct event *event __used,
+			int cpu __used,
+			u64 timestamp __used,
+			struct thread *thread __used)
+{
+	struct trace_init_event init_event;
+	u64 tmp;
+
+	tmp = raw_field_value(event, "class_id", data);
+	memcpy(&init_event.class_id, &tmp, sizeof(void *));
+	init_event.name = (char *)raw_field_ptr(event, "class_name", data);
+
+	if (trace_handler->init_event)
+		trace_handler->init_event(&init_event, event, cpu, timestamp, thread);
+}
+
+static void
 process_raw_event(void *data, int cpu,
 		  u64 timestamp, struct thread *thread)
 {
@@ -458,6 +568,8 @@ process_raw_event(void *data, int cpu,
 		process_lock_contended_event(data, event, cpu, timestamp, thread);
 	if (!strcmp(event->name, "lock_release"))
 		process_lock_release_event(data, event, cpu, timestamp, thread);
+	if (!strcmp(event->name, "lock_class_init"))
+		process_lock_class_init_event(data, event, cpu, timestamp, thread);
 }
 
 static int process_sample_event(event_t *event, struct perf_session *session)
@@ -503,15 +615,23 @@ static void print_result(void)
 	printf("\n\n");
 
 	while ((st = pop_from_result())) {
+		char *name;
 		bzero(cut_name, 20);
 
 		printf("%p ", st->addr);
 
-		if (strlen(st->name) < 16) {
+		if (!st->class)
+			name = (char *)"<unknown>";
+		else if (!st->class->name)
+			name = (char *)"<unknown2>";
+		else
+			name = st->class->name;
+
+		if (strlen(name) < 16) {
 			/* output raw name */
-			printf("%20s ", st->name);
+			printf("%20s ", name);
 		} else {
-			strncpy(cut_name, st->name, 16);
+			strncpy(cut_name, name, 16);
 			cut_name[16] = '.';
 			cut_name[17] = '.';
 			cut_name[18] = '.';
@@ -533,12 +653,18 @@ static void print_result(void)
 
 static void dump_map(void)
 {
+	char *name;
 	unsigned int i;
 	struct lock_stat *st;
 
 	for (i = 0; i < LOCKHASH_SIZE; i++) {
 		list_for_each_entry(st, &lockhash_table[i], hash_entry) {
-			printf("%p: %s\n", st->addr, st->name);
+			if (!st->class || !st->class->name)
+				name = (char *)"<unknown>";
+			else
+				name = st->class->name;
+
+			printf("%p: %s\n", st->addr, name);
 		}
 	}
 }
@@ -612,6 +738,7 @@ static const char *record_args[] = {
 	"-f",
 	"-m", "1024",
 	"-c", "1",
+	"-e", "lock:lock_class_init:r",
 	"-e", "lock:lock_acquire:r",
 	"-e", "lock:lock_acquired:r",
 	"-e", "lock:lock_contended:r",
@@ -644,6 +771,8 @@ int cmd_lock(int argc, const char **argv, const char *prefix __used)
 	symbol__init();
 	for (i = 0; i < LOCKHASH_SIZE; i++)
 		INIT_LIST_HEAD(lockhash_table + i);
+	for (i = 0; i < LOCKHASH_SIZE; i++)
+		INIT_LIST_HEAD(classhash_table + i);
 
 	argc = parse_options(argc, argv, lock_options, lock_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
-- 
1.6.2.3


  parent reply	other threads:[~2010-02-03  9:14 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-02-03  9:14 [RFC GIT PULL] perf/trace/lock optimization/scalability improvements Frederic Weisbecker
2010-02-03  9:14 ` [PATCH 01/11] tracing: Add lock_class_init event Frederic Weisbecker
2010-02-03  9:14 ` [PATCH 02/11] tracing: Introduce TRACE_EVENT_INJECT Frederic Weisbecker
2010-02-05 14:08   ` Steven Rostedt
2010-02-05 14:47   ` Steven Rostedt
2010-02-05 14:53     ` Peter Zijlstra
2010-02-05 15:07       ` Steven Rostedt
2010-02-06 12:20         ` Frederic Weisbecker
2010-02-06 13:19           ` Steven Rostedt
2010-02-10 10:04             ` Frederic Weisbecker
2010-02-10 14:05               ` Steven Rostedt
2010-02-11 18:57                 ` Frederic Weisbecker
2010-02-11 19:23                   ` Steven Rostedt
2010-02-03  9:14 ` [PATCH 03/11] tracing: Inject lock_class_init events on registration Frederic Weisbecker
2010-02-05 14:13   ` Steven Rostedt
2010-02-05 14:30     ` Peter Zijlstra
2010-02-05 14:44       ` Steven Rostedt
2010-02-03  9:14 ` [PATCH 04/11] tracing: Add lock class id in lock_acquire event Frederic Weisbecker
2010-02-03  9:14 ` [PATCH 05/11] perf: New PERF_EVENT_IOC_INJECT ioctl Frederic Weisbecker
2010-02-03  9:19   ` Frederic Weisbecker
2010-02-03  9:14 ` [PATCH 06/11] perf: Handle injection ioctl with trace events Frederic Weisbecker
2010-02-03  9:14 ` [PATCH 07/11] perf: Handle injection iotcl for tracepoints from perf record Frederic Weisbecker
2010-02-03  9:14 ` Frederic Weisbecker [this message]
2010-02-03  9:14 ` [PATCH 09/11] tracing: Remove the lock name from most lock events Frederic Weisbecker
2010-02-03  9:14 ` [PATCH 10/11] tracing/perf: Fix lock events recursions in the fast path Frederic Weisbecker
2010-02-04 15:47   ` Paul E. McKenney
2010-02-05  2:38     ` Lai Jiangshan
2010-02-05  9:45       ` Peter Zijlstra
2010-02-05  9:50         ` Peter Zijlstra
2010-02-05 10:49           ` Ingo Molnar
2010-02-05 12:10             ` Peter Zijlstra
2010-02-05 12:12               ` Peter Zijlstra
2010-02-05 13:01                 ` Peter Zijlstra
2010-02-06 11:12                   ` Frederic Weisbecker
2010-02-06 11:24                     ` Peter Zijlstra
2010-02-06 11:40                       ` Frederic Weisbecker
2010-02-06 14:17                         ` Peter Zijlstra
2010-02-06 16:10                           ` Frederic Weisbecker
2010-02-07  9:45                             ` Peter Zijlstra
2010-02-10 10:17                               ` Frederic Weisbecker
2010-02-28 22:24                   ` Frederic Weisbecker
2010-02-03  9:14 ` [PATCH 11/11] perf lock: Drop the buffers multiplexing dependency Frederic Weisbecker
2010-02-03 10:25 ` [RFC GIT PULL] perf/trace/lock optimization/scalability improvements Jens Axboe
2010-02-03 20:50   ` Frederic Weisbecker
2010-02-03 21:21     ` Jens Axboe
2010-02-03 22:13       ` Frederic Weisbecker
2010-02-04 19:40     ` Jens Axboe
2010-02-06 10:37       ` Frederic Weisbecker
2010-02-03 10:26 ` Ingo Molnar
2010-02-03 21:26   ` Frederic Weisbecker
2010-02-03 10:33 ` Peter Zijlstra
2010-02-03 22:07   ` Frederic Weisbecker
2010-02-04  6:33     ` Ingo Molnar
2010-02-07 17:10     ` Peter Zijlstra
2010-02-10 10:49       ` Frederic Weisbecker

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=1265188475-23509-9-git-send-regression-fweisbec@gmail.com \
    --to=fweisbec@gmail.com \
    --cc=acme@redhat.com \
    --cc=jens.axboe@oracle.com \
    --cc=laijs@cn.fujitsu.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lizf@cn.fujitsu.com \
    --cc=mhiramat@redhat.com \
    --cc=mingo@elte.hu \
    --cc=mitake@dcl.info.waseda.ac.jp \
    --cc=paulus@samba.org \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.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

all inboxes | Powered by JetHome®