diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-06-03 18:45:26 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-06-03 18:45:26 -0400 |
| commit | f150dba6d4a1e275b62ca76572c2786c71b91e85 (patch) | |
| tree | 1fb8ed0a64f69431e8a3304a1b346a19979028b9 | |
| parent | 636667a545b2d16797f27002a65d688c195c9b60 (diff) | |
| parent | c6df8d5ab87a246942d138321e1721edbb69f6e1 (diff) | |
Merge branch 'perf-fixes-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perf-fixes-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
perf: Fix crash in swevents
perf buildid-list: Fix --with-hits event processing
perf scripts python: Give field dict to unhandled callback
perf hist: fix objdump output parsing
perf-record: Check correct pid when forking
perf: Do the comm inheritance per thread in event__process_task
perf: Use event__process_task from perf sched
perf: Process comm events by tid
blktrace: Fix new kernel-doc warnings
perf_events: Fix unincremented buffer base on partial copy
perf_events: Fix event scheduling issues introduced by transactional API
perf_events, trace: Fix perf_trace_destroy(), mutex went missing
perf_events, trace: Fix probe unregister race
perf_events: Fix races in group composition
perf_events: Fix races and clean up perf_event and perf_mmap_data interaction
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 22 | ||||
| -rw-r--r-- | include/linux/perf_event.h | 9 | ||||
| -rw-r--r-- | include/trace/ftrace.h | 2 | ||||
| -rw-r--r-- | kernel/perf_event.c | 351 | ||||
| -rw-r--r-- | kernel/trace/blktrace.c | 2 | ||||
| -rw-r--r-- | kernel/trace/trace_event_perf.c | 15 | ||||
| -rw-r--r-- | kernel/trace/trace_kprobe.c | 4 | ||||
| -rw-r--r-- | kernel/trace/trace_syscalls.c | 4 | ||||
| -rw-r--r-- | tools/perf/builtin-buildid-list.c | 4 | ||||
| -rw-r--r-- | tools/perf/builtin-record.c | 3 | ||||
| -rw-r--r-- | tools/perf/builtin-sched.c | 1 | ||||
| -rw-r--r-- | tools/perf/scripts/python/check-perf-trace.py | 3 | ||||
| -rw-r--r-- | tools/perf/util/event.c | 13 | ||||
| -rw-r--r-- | tools/perf/util/hist.c | 2 | ||||
| -rw-r--r-- | tools/perf/util/scripting-engines/trace-event-python.c | 50 |
15 files changed, 309 insertions, 176 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index c77586061bcb..5db5b7d65a18 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
| @@ -106,6 +106,7 @@ struct cpu_hw_events { | |||
| 106 | 106 | ||
| 107 | int n_events; | 107 | int n_events; |
| 108 | int n_added; | 108 | int n_added; |
| 109 | int n_txn; | ||
| 109 | int assign[X86_PMC_IDX_MAX]; /* event to counter assignment */ | 110 | int assign[X86_PMC_IDX_MAX]; /* event to counter assignment */ |
| 110 | u64 tags[X86_PMC_IDX_MAX]; | 111 | u64 tags[X86_PMC_IDX_MAX]; |
| 111 | struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */ | 112 | struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */ |
| @@ -983,6 +984,7 @@ static int x86_pmu_enable(struct perf_event *event) | |||
| 983 | out: | 984 | out: |
| 984 | cpuc->n_events = n; | 985 | cpuc->n_events = n; |
| 985 | cpuc->n_added += n - n0; | 986 | cpuc->n_added += n - n0; |
| 987 | cpuc->n_txn += n - n0; | ||
| 986 | 988 | ||
| 987 | return 0; | 989 | return 0; |
| 988 | } | 990 | } |
| @@ -1089,6 +1091,14 @@ static void x86_pmu_disable(struct perf_event *event) | |||
| 1089 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 1091 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
| 1090 | int i; | 1092 | int i; |
| 1091 | 1093 | ||
| 1094 | /* | ||
| 1095 | * If we're called during a txn, we don't need to do anything. | ||
| 1096 | * The events never got scheduled and ->cancel_txn will truncate | ||
| 1097 | * the event_list. | ||
| 1098 | */ | ||
| 1099 | if (cpuc->group_flag & PERF_EVENT_TXN_STARTED) | ||
| 1100 | return; | ||
| 1101 | |||
| 1092 | x86_pmu_stop(event); | 1102 | x86_pmu_stop(event); |
| 1093 | 1103 | ||
| 1094 | for (i = 0; i < cpuc->n_events; i++) { | 1104 | for (i = 0; i < cpuc->n_events; i++) { |
| @@ -1379,6 +1389,7 @@ static void x86_pmu_start_txn(const struct pmu *pmu) | |||
| 1379 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 1389 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
| 1380 | 1390 | ||
| 1381 | cpuc->group_flag |= PERF_EVENT_TXN_STARTED; | 1391 | cpuc->group_flag |= PERF_EVENT_TXN_STARTED; |
| 1392 | cpuc->n_txn = 0; | ||
| 1382 | } | 1393 | } |
| 1383 | 1394 | ||
| 1384 | /* | 1395 | /* |
| @@ -1391,6 +1402,11 @@ static void x86_pmu_cancel_txn(const struct pmu *pmu) | |||
| 1391 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 1402 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
| 1392 | 1403 | ||
| 1393 | cpuc->group_flag &= ~PERF_EVENT_TXN_STARTED; | 1404 | cpuc->group_flag &= ~PERF_EVENT_TXN_STARTED; |
| 1405 | /* | ||
| 1406 | * Truncate the collected events. | ||
| 1407 | */ | ||
| 1408 | cpuc->n_added -= cpuc->n_txn; | ||
| 1409 | cpuc->n_events -= cpuc->n_txn; | ||
| 1394 | } | 1410 | } |
| 1395 | 1411 | ||
| 1396 | /* | 1412 | /* |
| @@ -1419,6 +1435,12 @@ static int x86_pmu_commit_txn(const struct pmu *pmu) | |||
| 1419 | */ | 1435 | */ |
| 1420 | memcpy(cpuc->assign, assign, n*sizeof(int)); | 1436 | memcpy(cpuc->assign, assign, n*sizeof(int)); |
| 1421 | 1437 | ||
| 1438 | /* | ||
| 1439 | * Clear out the txn count so that ->cancel_txn() which gets | ||
| 1440 | * run after ->commit_txn() doesn't undo things. | ||
| 1441 | */ | ||
| 1442 | cpuc->n_txn = 0; | ||
| 1443 | |||
| 1422 | return 0; | 1444 | return 0; |
| 1423 | } | 1445 | } |
| 1424 | 1446 | ||
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index fb6c91eac7e3..5d0266d94985 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
| @@ -585,6 +585,7 @@ enum perf_event_active_state { | |||
| 585 | struct file; | 585 | struct file; |
| 586 | 586 | ||
| 587 | struct perf_mmap_data { | 587 | struct perf_mmap_data { |
| 588 | atomic_t refcount; | ||
| 588 | struct rcu_head rcu_head; | 589 | struct rcu_head rcu_head; |
| 589 | #ifdef CONFIG_PERF_USE_VMALLOC | 590 | #ifdef CONFIG_PERF_USE_VMALLOC |
| 590 | struct work_struct work; | 591 | struct work_struct work; |
| @@ -592,7 +593,6 @@ struct perf_mmap_data { | |||
| 592 | #endif | 593 | #endif |
| 593 | int nr_pages; /* nr of data pages */ | 594 | int nr_pages; /* nr of data pages */ |
| 594 | int writable; /* are we writable */ | 595 | int writable; /* are we writable */ |
| 595 | int nr_locked; /* nr pages mlocked */ | ||
| 596 | 596 | ||
| 597 | atomic_t poll; /* POLL_ for wakeups */ | 597 | atomic_t poll; /* POLL_ for wakeups */ |
| 598 | 598 | ||
| @@ -631,6 +631,9 @@ struct swevent_hlist { | |||
| 631 | struct rcu_head rcu_head; | 631 | struct rcu_head rcu_head; |
| 632 | }; | 632 | }; |
| 633 | 633 | ||
| 634 | #define PERF_ATTACH_CONTEXT 0x01 | ||
| 635 | #define PERF_ATTACH_GROUP 0x02 | ||
| 636 | |||
| 634 | /** | 637 | /** |
| 635 | * struct perf_event - performance event kernel representation: | 638 | * struct perf_event - performance event kernel representation: |
| 636 | */ | 639 | */ |
| @@ -643,10 +646,10 @@ struct perf_event { | |||
| 643 | int nr_siblings; | 646 | int nr_siblings; |
| 644 | int group_flags; | 647 | int group_flags; |
| 645 | struct perf_event *group_leader; | 648 | struct perf_event *group_leader; |
| 646 | struct perf_event *output; | ||
| 647 | const struct pmu *pmu; | 649 | const struct pmu *pmu; |
| 648 | 650 | ||
| 649 | enum perf_event_active_state state; | 651 | enum perf_event_active_state state; |
| 652 | unsigned int attach_state; | ||
| 650 | atomic64_t count; | 653 | atomic64_t count; |
| 651 | 654 | ||
| 652 | /* | 655 | /* |
| @@ -704,6 +707,8 @@ struct perf_event { | |||
| 704 | /* mmap bits */ | 707 | /* mmap bits */ |
| 705 | struct mutex mmap_mutex; | 708 | struct mutex mmap_mutex; |
| 706 | atomic_t mmap_count; | 709 | atomic_t mmap_count; |
| 710 | int mmap_locked; | ||
| 711 | struct user_struct *mmap_user; | ||
| 707 | struct perf_mmap_data *data; | 712 | struct perf_mmap_data *data; |
| 708 | 713 | ||
| 709 | /* poll related */ | 714 | /* poll related */ |
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index 3d685d1f2a03..5a64905d7278 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h | |||
| @@ -725,7 +725,7 @@ perf_trace_##call(void *__data, proto) \ | |||
| 725 | \ | 725 | \ |
| 726 | { assign; } \ | 726 | { assign; } \ |
| 727 | \ | 727 | \ |
| 728 | head = per_cpu_ptr(event_call->perf_events, smp_processor_id());\ | 728 | head = this_cpu_ptr(event_call->perf_events); \ |
| 729 | perf_trace_buf_submit(entry, __entry_size, rctx, __addr, \ | 729 | perf_trace_buf_submit(entry, __entry_size, rctx, __addr, \ |
| 730 | __count, &__regs, head); \ | 730 | __count, &__regs, head); \ |
| 731 | } | 731 | } |
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index bd7ce8ca5bb9..31d6afe92594 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
| @@ -283,14 +283,15 @@ ctx_group_list(struct perf_event *event, struct perf_event_context *ctx) | |||
| 283 | static void | 283 | static void |
| 284 | list_add_event(struct perf_event *event, struct perf_event_context *ctx) | 284 | list_add_event(struct perf_event *event, struct perf_event_context *ctx) |
| 285 | { | 285 | { |
| 286 | struct perf_event *group_leader = event->group_leader; | ||
