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
next prev 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®