aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-06-03 18:45:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-06-03 18:45:26 -0400
commitf150dba6d4a1e275b62ca76572c2786c71b91e85 (patch)
tree1fb8ed0a64f69431e8a3304a1b346a19979028b9
parent636667a545b2d16797f27002a65d688c195c9b60 (diff)
parentc6df8d5ab87a246942d138321e1721edbb69f6e1 (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.c22
-rw-r--r--include/linux/perf_event.h9
-rw-r--r--include/trace/ftrace.h2
-rw-r--r--kernel/perf_event.c351
-rw-r--r--kernel/trace/blktrace.c2
-rw-r--r--kernel/trace/trace_event_perf.c15
-rw-r--r--kernel/trace/trace_kprobe.c4
-rw-r--r--kernel/trace/trace_syscalls.c4
-rw-r--r--tools/perf/builtin-buildid-list.c4
-rw-r--r--tools/perf/builtin-record.c3
-rw-r--r--tools/perf/builtin-sched.c1
-rw-r--r--tools/perf/scripts/python/check-perf-trace.py3
-rw-r--r--tools/perf/util/event.c13
-rw-r--r--tools/perf/util/hist.c2
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c50
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)
983out: 984out:
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 {
585struct file; 585struct file;
586 586
587struct perf_mmap_data { 587struct 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)
283static void 283static void
284list_add_event(struct perf_event *event, struct perf_event_context *ctx) 284list_add_event(struct perf_event *event, struct perf_event_context *ctx)
285{ 285{
286 struct perf_event *group_leader = event->group_leader;