diff options
author | Frederic Weisbecker <fweisbec@gmail.com> | 2010-04-05 09:35:57 -0400 |
---|---|---|
committer | Frederic Weisbecker <fweisbec@gmail.com> | 2010-04-14 12:20:33 -0400 |
commit | 76e1d9047e4edefb8ada20aa90d5762306082bd6 (patch) | |
tree | 60384bd206878d2c440e07b33d97b1bb00a103dc /include/linux/perf_event.h | |
parent | c05556421742eb47f80301767653a4bcb19de9de (diff) |
perf: Store active software events in a hashlist
Each time a software event triggers, we need to walk through
the entire list of events from the current cpu and task contexts
to retrieve a running perf event that matches.
We also need to check a matching perf event is actually counting.
This walk is wasteful and makes the event fast path scaling
down with a growing number of events running on the same
contexts.
To solve this, we store the running perf events in a hashlist to
get an immediate access to them against their type:event_id when
they trigger.
v2: - Fix SWEVENT_HLIST_SIZE definition (and re-learn some basic
maths along the way)
- Only allocate hlist for online cpus, but keep track of the
refcount on offline possible cpus too, so that we allocate it
if needed when it becomes online.
- Drop the kref use as it's not adapted to our tricks anymore.
v3: - Fix bad refcount check (address instead of value). Thanks to
Eric Dumazet who spotted this.
- While exiting cpu, move the hlist release out of the IPI path
to lock the hlist mutex sanely.
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include/linux/perf_event.h')
-rw-r--r-- | include/linux/perf_event.h | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 6e96cc8225d4..bf896d0b2e9c 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
@@ -589,6 +589,14 @@ enum perf_group_flag { | |||
589 | PERF_GROUP_SOFTWARE = 0x1, | 589 | PERF_GROUP_SOFTWARE = 0x1, |
590 | }; | 590 | }; |
591 | 591 | ||
592 | #define SWEVENT_HLIST_BITS 8 | ||
593 | #define SWEVENT_HLIST_SIZE (1 << SWEVENT_HLIST_BITS) | ||
594 | |||
595 | struct swevent_hlist { | ||
596 | struct hlist_head heads[SWEVENT_HLIST_SIZE]; | ||
597 | struct rcu_head rcu_head; | ||
598 | }; | ||
599 | |||
592 | /** | 600 | /** |
593 | * struct perf_event - performance event kernel representation: | 601 | * struct perf_event - performance event kernel representation: |
594 | */ | 602 | */ |
@@ -597,6 +605,7 @@ struct perf_event { | |||
597 | struct list_head group_entry; | 605 | struct list_head group_entry; |
598 | struct list_head event_entry; | 606 | struct list_head event_entry; |
599 | struct list_head sibling_list; | 607 | struct list_head sibling_list; |
608 | struct hlist_node hlist_entry; | ||
600 | int nr_siblings; | 609 | int nr_siblings; |
601 | int group_flags; | 610 | int group_flags; |
602 | struct perf_event *group_leader; | 611 | struct perf_event *group_leader; |
@@ -744,6 +753,9 @@ struct perf_cpu_context { | |||
744 | int active_oncpu; | 753 | int active_oncpu; |
745 | int max_pertask; | 754 | int max_pertask; |
746 | int exclusive; | 755 | int exclusive; |
756 | struct swevent_hlist *swevent_hlist; | ||
757 | struct mutex hlist_mutex; | ||
758 | int hlist_refcount; | ||
747 | 759 | ||
748 | /* | 760 | /* |
749 | * Recursion avoidance: | 761 | * Recursion avoidance: |