diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2009-06-02 09:08:15 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-06-02 15:45:29 -0400 |
commit | 8e5799b1ad2a0567fdfaaf0e91b40efee010f2c1 (patch) | |
tree | bd3f45c348f48411a4496229572643211cbd59b8 | |
parent | 53e111a730ea8b002d57dd226098c12789993329 (diff) |
perf_counter: Add unique counter id
Stephan raised the issue that we currently cannot distinguish between
similar counters within a group (PERF_RECORD_GROUP uses the config
value as identifier).
Therefore, generate a new ID for each counter using a global u64
sequence counter.
Reported-by: Stephane Eranian <eranian@googlemail.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: John Kacur <jkacur@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | include/linux/perf_counter.h | 8 | ||||
-rw-r--r-- | kernel/perf_counter.c | 9 |
2 files changed, 12 insertions, 5 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index 9ec20fc6bd36..4845a214b9e7 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h | |||
@@ -114,8 +114,9 @@ enum perf_counter_record_format { | |||
114 | * in increasing order of bit value, after the counter value. | 114 | * in increasing order of bit value, after the counter value. |
115 | */ | 115 | */ |
116 | enum perf_counter_read_format { | 116 | enum perf_counter_read_format { |
117 | PERF_FORMAT_TOTAL_TIME_ENABLED = 1, | 117 | PERF_FORMAT_TOTAL_TIME_ENABLED = 1U << 0, |
118 | PERF_FORMAT_TOTAL_TIME_RUNNING = 2, | 118 | PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1, |
119 | PERF_FORMAT_ID = 1U << 2, | ||
119 | }; | 120 | }; |
120 | 121 | ||
121 | /* | 122 | /* |
@@ -290,7 +291,7 @@ enum perf_event_type { | |||
290 | * { u32 cpu, res; } && PERF_RECORD_CPU | 291 | * { u32 cpu, res; } && PERF_RECORD_CPU |
291 | * | 292 | * |
292 | * { u64 nr; | 293 | * { u64 nr; |
293 | * { u64 event, val; } cnt[nr]; } && PERF_RECORD_GROUP | 294 | * { u64 id, val; } cnt[nr]; } && PERF_RECORD_GROUP |
294 | * | 295 | * |
295 | * { u16 nr, | 296 | * { u16 nr, |
296 | * hv, | 297 | * hv, |
@@ -503,6 +504,7 @@ struct perf_counter { | |||
503 | struct rcu_head rcu_head; | 504 | struct rcu_head rcu_head; |
504 | 505 | ||
505 | struct pid_namespace *ns; | 506 | struct pid_namespace *ns; |
507 | u64 id; | ||
506 | #endif | 508 | #endif |
507 | }; | 509 | }; |
508 | 510 | ||
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index caa012cfe49a..978ecfcc7aaf 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c | |||
@@ -1510,6 +1510,8 @@ perf_read_hw(struct perf_counter *counter, char __user *buf, size_t count) | |||
1510 | if (counter->hw_event.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) | 1510 | if (counter->hw_event.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) |
1511 | values[n++] = counter->total_time_running + | 1511 | values[n++] = counter->total_time_running + |
1512 | atomic64_read(&counter->child_total_time_running); | 1512 | atomic64_read(&counter->child_total_time_running); |
1513 | if (counter->hw_event.read_format & PERF_FORMAT_ID) | ||
1514 | values[n++] = counter->id; | ||
1513 | mutex_unlock(&counter->child_mutex); | 1515 | mutex_unlock(&counter->child_mutex); |
1514 | 1516 | ||
1515 | if (count < n * sizeof(u64)) | 1517 | if (count < n * sizeof(u64)) |
@@ -2303,7 +2305,7 @@ static void perf_counter_output(struct perf_counter *counter, | |||
2303 | u32 pid, tid; | 2305 | u32 pid, tid; |
2304 | } tid_entry; | 2306 | } tid_entry; |
2305 | struct { | 2307 | struct { |
2306 | u64 event; | 2308 | u64 id; |
2307 | u64 counter; | 2309 | u64 counter; |
2308 | } group_entry; | 2310 | } group_entry; |
2309 | struct perf_callchain_entry *callchain = NULL; | 2311 | struct perf_callchain_entry *callchain = NULL; |
@@ -2416,7 +2418,7 @@ static void perf_counter_output(struct perf_counter *counter, | |||
2416 | if (sub != counter) | 2418 | if (sub != counter) |
2417 | sub->pmu->read(sub); | 2419 | sub->pmu->read(sub); |
2418 | 2420 | ||
2419 | group_entry.event = sub->hw_event.config; | 2421 | group_entry.id = sub->id; |
2420 | group_entry.counter = atomic64_read(&sub->count); | 2422 | group_entry.counter = atomic64_read(&sub->count); |
2421 | 2423 | ||
2422 | perf_output_put(&handle, group_entry); | 2424 | perf_output_put(&handle, group_entry); |
@@ -3375,6 +3377,8 @@ done: | |||
3375 | return counter; | 3377 | return counter; |
3376 | } | 3378 | } |
3377 | 3379 | ||
3380 | static atomic64_t perf_counter_id; | ||
3381 | |||
3378 | /** | 3382 | /** |
3379 | * sys_perf_counter_open - open a performance counter, associate it to a task/cpu | 3383 | * sys_perf_counter_open - open a performance counter, associate it to a task/cpu |
3380 | * | 3384 | * |
@@ -3470,6 +3474,7 @@ SYSCALL_DEFINE5(perf_counter_open, | |||
3470 | mutex_unlock(¤t->perf_counter_mutex); | 3474 | mutex_unlock(¤t->perf_counter_mutex); |
3471 | 3475 | ||
3472 | counter->ns = get_pid_ns(current->nsproxy->pid_ns); | 3476 | counter->ns = get_pid_ns(current->nsproxy->pid_ns); |
3477 | counter->id = atomic64_inc_return(&perf_counter_id); | ||
3473 | 3478 | ||
3474 | fput_light(counter_file, fput_needed2); | 3479 | fput_light(counter_file, fput_needed2); |
3475 | 3480 | ||