diff options
author | Jason Baron <jbaron@redhat.com> | 2011-03-16 17:29:47 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2011-04-04 12:48:08 -0400 |
commit | d430d3d7e646eb1eac2bb4aa244a644312e67c76 (patch) | |
tree | 0f52534f54d89e41042536ff2f1b2ce74c45c033 /include/linux/perf_event.h | |
parent | ee5e51f51be755830f57445e268ba50e88ccbdbb (diff) |
jump label: Introduce static_branch() interface
Introduce:
static __always_inline bool static_branch(struct jump_label_key *key);
instead of the old JUMP_LABEL(key, label) macro.
In this way, jump labels become really easy to use:
Define:
struct jump_label_key jump_key;
Can be used as:
if (static_branch(&jump_key))
do unlikely code
enable/disale via:
jump_label_inc(&jump_key);
jump_label_dec(&jump_key);
that's it!
For the jump labels disabled case, the static_branch() becomes an
atomic_read(), and jump_label_inc()/dec() are simply atomic_inc(),
atomic_dec() operations. We show testing results for this change below.
Thanks to H. Peter Anvin for suggesting the 'static_branch()' construct.
Since we now require a 'struct jump_label_key *key', we can store a pointer into
the jump table addresses. In this way, we can enable/disable jump labels, in
basically constant time. This change allows us to completely remove the previous
hashtable scheme. Thanks to Peter Zijlstra for this re-write.
Testing:
I ran a series of 'tbench 20' runs 5 times (with reboots) for 3
configurations, where tracepoints were disabled.
jump label configured in
avg: 815.6
jump label *not* configured in (using atomic reads)
avg: 800.1
jump label *not* configured in (regular reads)
avg: 803.4
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <20110316212947.GA8792@redhat.com>
Signed-off-by: Jason Baron <jbaron@redhat.com>
Suggested-by: H. Peter Anvin <hpa@linux.intel.com>
Tested-by: David Daney <ddaney@caviumnetworks.com>
Acked-by: Ralf Baechle <ralf@linux-mips.org>
Acked-by: David S. Miller <davem@davemloft.net>
Acked-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'include/linux/perf_event.h')
-rw-r--r-- | include/linux/perf_event.h | 26 |
1 files changed, 13 insertions, 13 deletions
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 311b4dc785a1..730b7821690f 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
@@ -505,7 +505,7 @@ struct perf_guest_info_callbacks { | |||
505 | #include <linux/ftrace.h> | 505 | #include <linux/ftrace.h> |
506 | #include <linux/cpu.h> | 506 | #include <linux/cpu.h> |
507 | #include <linux/irq_work.h> | 507 | #include <linux/irq_work.h> |
508 | #include <linux/jump_label_ref.h> | 508 | #include <linux/jump_label.h> |
509 | #include <asm/atomic.h> | 509 | #include <asm/atomic.h> |
510 | #include <asm/local.h> | 510 | #include <asm/local.h> |
511 | 511 | ||
@@ -1034,7 +1034,7 @@ static inline int is_software_event(struct perf_event *event) | |||
1034 | return event->pmu->task_ctx_nr == perf_sw_context; | 1034 | return event->pmu->task_ctx_nr == perf_sw_context; |
1035 | } | 1035 | } |
1036 | 1036 | ||
1037 | extern atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX]; | 1037 | extern struct jump_label_key perf_swevent_enabled[PERF_COUNT_SW_MAX]; |
1038 | 1038 | ||
1039 | extern void __perf_sw_event(u32, u64, int, struct pt_regs *, u64); | 1039 | extern void __perf_sw_event(u32, u64, int, struct pt_regs *, u64); |
1040 | 1040 | ||
@@ -1063,22 +1063,21 @@ perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr) | |||
1063 | { | 1063 | { |
1064 | struct pt_regs hot_regs; | 1064 | struct pt_regs hot_regs; |
1065 | 1065 | ||
1066 | JUMP_LABEL(&perf_swevent_enabled[event_id], have_event); | 1066 | if (static_branch(&perf_swevent_enabled[event_id])) { |
1067 | return; | 1067 | if (!regs) { |
1068 | 1068 | perf_fetch_caller_regs(&hot_regs); | |
1069 | have_event: | 1069 | regs = &hot_regs; |
1070 | if (!regs) { | 1070 | } |
1071 | perf_fetch_caller_regs(&hot_regs); | 1071 | __perf_sw_event(event_id, nr, nmi, regs, addr); |
1072 | regs = &hot_regs; | ||
1073 | } | 1072 | } |
1074 | __perf_sw_event(event_id, nr, nmi, regs, addr); | ||
1075 | } | 1073 | } |
1076 | 1074 | ||
1077 | extern atomic_t perf_sched_events; | 1075 | extern struct jump_label_key perf_sched_events; |
1078 | 1076 | ||
1079 | static inline void perf_event_task_sched_in(struct task_struct *task) | 1077 | static inline void perf_event_task_sched_in(struct task_struct *task) |
1080 | { | 1078 | { |
1081 | COND_STMT(&perf_sched_events, __perf_event_task_sched_in(task)); | 1079 | if (static_branch(&perf_sched_events)) |
1080 | __perf_event_task_sched_in(task); | ||
1082 | } | 1081 | } |
1083 | 1082 | ||
1084 | static inline | 1083 | static inline |
@@ -1086,7 +1085,8 @@ void perf_event_task_sched_out(struct task_struct *task, struct task_struct *nex | |||
1086 | { | 1085 | { |
1087 | perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0); | 1086 | perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0); |
1088 | 1087 | ||
1089 | COND_STMT(&perf_sched_events, __perf_event_task_sched_out(task, next)); | 1088 | if (static_branch(&perf_sched_events)) |
1089 | __perf_event_task_sched_out(task, next); | ||
1090 | } | 1090 | } |
1091 | 1091 | ||
1092 | extern void perf_event_mmap(struct vm_area_struct *vma); | 1092 | extern void perf_event_mmap(struct vm_area_struct *vma); |