jump label: update for .39 v2
Subsystems (10)
v2 cover jump label: update for .39 v2
Hi,
Update against tip/perf/urgent. I've incorporated feedback from the last round. Hopefully these can still be considered for .39.
thanks,
-Jason
v2:
-add initial s390 support
-add jump section alignment for x86
-add types.h and compiler.h to jump_label.h
-moved jump_label_sort_entries() into jump_label_add_module()
Jan Glauber (1):
jump label: add s390 support
Jason Baron (3):
jump label: introduce static_branch() interface
dynamic debug: add jump label support
jump label: add _ASM_ALIGN for x86 and x86_64
arch/mips/include/asm/jump_label.h | 22 +- arch/s390/Kconfig | 1 + arch/s390/include/asm/jump_label.h | 37 +++ arch/s390/kernel/Makefile | 2 +- arch/s390/kernel/jump_label.c | 59 ++++ arch/sparc/include/asm/jump_label.h | 25 +- arch/x86/include/asm/alternative.h | 3 +- arch/x86/include/asm/jump_label.h | 27 +- arch/x86/kernel/alternative.c | 2 +- arch/x86/kernel/module.c | 1 + include/asm-generic/vmlinux.lds.h | 14 +- include/linux/dynamic_debug.h | 44 +++- include/linux/jump_label.h | 89 ++++--- include/linux/jump_label_ref.h | 44 --- include/linux/perf_event.h | 26 +- include/linux/tracepoint.h | 22 +- kernel/jump_label.c | 539 ++++++++++++++--------------------- kernel/perf_event.c | 4 +- kernel/tracepoint.c | 23 +- lib/dynamic_debug.c | 4 +- 20 files changed, 494 insertions(+), 494 deletions(-) create mode 100644 arch/s390/include/asm/jump_label.h create mode 100644 arch/s390/kernel/jump_label.c delete mode 100644 include/linux/jump_label_ref.h
PATCH v2 1/4 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
--- arch/mips/include/asm/jump_label.h | 22 +- arch/sparc/include/asm/jump_label.h | 25 +- arch/x86/include/asm/alternative.h | 3 +- arch/x86/include/asm/jump_label.h | 26 +- arch/x86/kernel/alternative.c | 2 +- arch/x86/kernel/module.c | 1 + include/asm-generic/vmlinux.lds.h | 14 +- include/linux/dynamic_debug.h | 2 - include/linux/jump_label.h | 89 ++++--- include/linux/jump_label_ref.h | 44 --- include/linux/perf_event.h | 26 +- include/linux/tracepoint.h | 22 +- kernel/jump_label.c | 539 ++++++++++++++--------------------- kernel/perf_event.c | 4 +- kernel/tracepoint.c | 23 +- 15 files changed, 356 insertions(+), 486 deletions(-) delete mode 100644 include/linux/jump_label_ref.h
arch/mips/include/asm/jump_label.h +12 -10
@@ -20,16 +20,18 @@#define WORD_INSN ".word"#endif -#define JUMP_LABEL (key, label) \ - do { \ - asm goto("1:\tnop\n\t" \ - "nop\n\t" \ - ".pushsection __jump_table, \"a\"\n\t" \ - WORD_INSN " 1b, %l[" #label "], %0\n\t" \ - ".popsection\n\t" \ - : : "i" (key) : : label); \ - } while (0) - +static __always_inline bool arch_static_branch(struct jump_label_key *key) +{ + asm goto("1:\tnop\n\t" +"nop\n\t" +".pushsection __jump_table, \"aw\"\n\t" +WORD_INSN " 1b, %l[l_yes], %0\n\t" +".popsection\n\t" + : :"i" (key) : : l_yes); +return false; +l_yes: +return true; +}#endif /* __KERNEL__ */
arch/sparc/include/asm/jump_label.h +14 -11
@@ -7,17 +7,20 @@#define JUMP_LABEL_NOP_SIZE 4 -#define JUMP_LABEL (key, label) \ - do { \ - asm goto("1:\n\t" \ - "nop\n\t" \ - "nop\n\t" \ - ".pushsection __jump_table, \"a\"\n\t"\ - ".align 4\n\t" \ - ".word 1b, %l[" #label "], %c0\n\t" \ - ".popsection \n\t" \ - : : "i" (key) : : label);\ - } while (0) +static __always_inline bool arch_static_branch(struct jump_label_key *key) +{ + asm goto("1:\n\t" +"nop\n\t" +"nop\n\t" +".pushsection __jump_table, \"aw\"\n\t" +".align 4\n\t" +".word 1b, %l[l_yes], %c0\n\t" +".popsection \n\t" + : :"i" (key) : : l_yes); +return false; +l_yes: +return true; +}#endif /* __KERNEL__ */
arch/x86/include/asm/alternative.h +1 -2
@@ -4,7 +4,6 @@#include <linux/types.h> #include <linux/stddef.h> #include <linux/stringify.h> -#include <linux/jump_label.h> #include <asm/asm.h> /*
@@ -191,7 +190,7 @@ extern void *text_poke(void *addr, const void *opcode, size_t len);extern void *text_poke_smp (void *addr,const void *opcode,size_t len);extern void text_poke_smp_batch (struct text_poke_param *params,int n); -#if defined(CONFIG_DYNAMIC_FTRACE ) || defined(HAVE_JUMP_LABEL ) +#if defined(CONFIG_DYNAMIC_FTRACE ) || defined(CONFIG_JUMP_LABEL )#define IDEAL_NOP_SIZE_5 5extern unsigned char ideal_nop5[IDEAL_NOP_SIZE_5 ];extern void arch_init_ideal_nop5 (void );
arch/x86/include/asm/jump_label.h +15 -11
@@ -5,20 +5,24 @@#include <linux/types.h> #include <asm/nops.h> +#include <asm/asm.h> #define JUMP_LABEL_NOP_SIZE 5 -# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t" - -# define JUMP_LABEL (key, label) \ - do { \ - asm goto("1:" \ - JUMP_LABEL_INITIAL_NOP \ - ".pushsection __jump_table, \"aw\" \n\t"\ - _ASM_PTR "1b, %l[" #label "], %c0 \n\t" \ - ".popsection \n\t" \ - : : "i" (key) : : label); \ - } while (0) +#define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t" + +static __always_inline bool arch_static_branch(struct jump_label_key *key) +{ + asm goto("1:" +JUMP_LABEL_INITIAL_NOP +".pushsection __jump_table, \"aw\" \n\t" + _ASM_PTR"1b, %l[l_yes], %c0 \n\t" +".popsection \n\t" + : :"i" (key) : : l_yes); +return false; +l_yes: +return true; +}#endif /* __KERNEL__ */
arch/x86/kernel/alternative.c +1 -1
@@ -674,7 +674,7 @@ void __kprobes text_poke_smp_batch(struct text_poke_param *params, int n)__stop_machine (stop_machine_text_poke, (void *)&tpp,NULL ); } -#if defined(CONFIG_DYNAMIC_FTRACE ) || defined(HAVE_JUMP_LABEL ) +#if defined(CONFIG_DYNAMIC_FTRACE ) || defined(CONFIG_JUMP_LABEL )#ifdef CONFIG_X86_64 unsigned char ideal_nop5[5 ] = {0x66 ,0x66 ,0x66 ,0x66 ,0x90 };
arch/x86/kernel/module.c +1 -0
@@ -24,6 +24,7 @@#include <linux/bug.h> #include <linux/mm.h> #include <linux/gfp.h> +#include <linux/jump_label.h> #include <asm/system.h> #include <asm/page.h>
include/asm-generic/vmlinux.lds.h +4 -10
@@ -170,6 +170,10 @@STRUCT_ALIGN (); \ *(__tracepoints) \/* implement dynamic printk debug */ \ + . = ALIGN(8); \ + VMLINUX_SYMBOL(__start___jump_table) = .; \ + *(__jump_table ) \ + VMLINUX_SYMBOL(__stop___jump_table) = .; \ . = ALIGN(8); \ VMLINUX_SYMBOL(__start___verbose) = .; \ *(__verbose) \
@@ -228,8 +232,6 @@ \ BUG_TABLE \ \ - JUMP_TABLE \ - \ /* PCI quirks */ \ .pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \ VMLINUX_SYMBOL(__start_pci_fixups_early) = .; \
@@ -583,14 +585,6 @@#define BUG_TABLE #endif -#define JUMP_TABLE \ - . = ALIGN(8); \ - __jump_table : AT(ADDR(__jump_table) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___jump_table) = .; \ - *(__jump_table) \ - VMLINUX_SYMBOL(__stop___jump_table) = .; \ - } -#ifdef CONFIG_PM_TRACE #define TRACEDATA \ . = ALIGN(4); \
include/linux/dynamic_debug.h +0 -2
@@ -1,8 +1,6 @@#ifndef _DYNAMIC_DEBUG_H#define _DYNAMIC_DEBUG_H -#include <linux/jump_label.h> -/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They * use independent hash functions, to reduce the chance of false positives.
include/linux/jump_label.h +56 -33
129 lines not on this page · raw message
include/linux/jump_label_ref.h deleted +0 -44
44 lines not on this page · raw message
include/linux/perf_event.h +13 -13
@@ -497,7 +497,7 @@ struct perf_guest_info_callbacks {#include <linux/ftrace.h> #include <linux/cpu.h> #include <linux/irq_work.h> -#include <linux/jump_label_ref.h> +#include <linux/jump_label.h> #include <asm/atomic.h> #include <asm/local.h>
@@ -1000,7 +1000,7 @@ static inline int is_software_event(struct perf_event *event)return event->pmu->task_ctx_nr == perf_sw_context; } -extern atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX ]; +extern struct jump_label_key perf_swevent_enabled[PERF_COUNT_SW_MAX ];extern void __perf_sw_event (u32 ,u64 ,int ,struct pt_regs *,u64 );
@@ -1029,22 +1029,21 @@ perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr) {struct pt_regs hot_regs; -JUMP_LABEL (&perf_swevent_enabled[event_id], have_event); -return ; - -have_event: -if (!regs) { -perf_fetch_caller_regs (&hot_regs); - regs = &hot_regs; +if (static_branch (&perf_swevent_enabled[event_id])) { +if (!regs) { +perf_fetch_caller_regs (&hot_regs); + regs = &hot_regs; + } +__perf_sw_event (event_id, nr, nmi, regs, addr); } -__perf_sw_event (event_id, nr, nmi, regs, addr); } -extern atomic_t perf_task_events; +extern struct jump_label_key perf_task_events;static inline void perf_event_task_sched_in (struct task_struct *task) { -COND_STMT (&perf_task_events,__perf_event_task_sched_in (task)); +if (static_branch (&perf_task_events)) +__perf_event_task_sched_in (task); } static inline
@@ -1052,7 +1051,8 @@ void perf_event_task_sched_out(struct task_struct *task, struct task_struct *nex {perf_sw_event (PERF_COUNT_SW_CONTEXT_SWITCHES ,1 ,1 ,NULL ,0 ); -COND_STMT (&perf_task_events,__perf_event_task_sched_out (task, next)); +if (static_branch (&perf_task_events)) +__perf_event_task_sched_out (task, next); }extern void perf_event_mmap (struct vm_area_struct *vma);
include/linux/tracepoint.h +10 -12
@@ -29,7 +29,7 @@ struct tracepoint_func {struct tracepoint {const char *name;/* Tracepoint name */ -int state;/* State. */ +struct jump_label_key key;void (*regfunc)(void );void (*unregfunc)(void );struct tracepoint_func __rcu *funcs;
@@ -146,9 +146,7 @@ void tracepoint_update_probe_range(struct tracepoint * const *begin, extern struct tracepoint __tracepoint_##name; \ static inline void trace_##name(proto) \ { \ - JUMP_LABEL(&__tracepoint_##name.state, do_trace); \ - return; \ -do_trace: \ + if (static_branch(&__tracepoint_##name.key)) \ __DO_TRACE(&__tracepoint_##name, \ TP_PROTO(data_proto), \ TP_ARGS(data_args), \
@@ -176,14 +174,14 @@ do_trace: \* structures, so we create an array of pointers that will be used for iteration * on the tracepoints. */ -#define DEFINE_TRACE_FN (name, reg, unreg) \ - static const char __tpstrtab_##name[] \ - __attribute__((section("__tracepoints_strings"))) = #name; \ - struct tracepoint __tracepoint_##name \ - __attribute__((section("__tracepoints"))) = \ - { __tpstrtab_##name, 0, reg, unreg, NULL }; \ - static struct tracepoint * const __tracepoint_ptr_##name __used \ - __attribute__((section("__tracepoints_ptrs"))) = \ +#define DEFINE_TRACE_FN (name, reg, unreg) \ + static const char __tpstrtab_##name[] \ + __attribute__((section("__tracepoints_strings"))) = #name; \ + struct tracepoint __tracepoint_##name \ + __attribute__((section("__tracepoints"))) = \ + { __tpstrtab_##name, JUMP_LABEL_INIT, reg, unreg, NULL };\ + static struct tracepoint * const __tracepoint_ptr_##name __used \ + __attribute__((section("__tracepoints_ptrs"))) = \ &__tracepoint_##name;#define DEFINE_TRACE (name) \
kernel/jump_label.c +218 -321
670 lines not on this page · raw message
kernel/perf_event.c +2 -2
@@ -44,7 +44,7 @@ enum event_type_t { EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED, }; -atomic_t perf_task_events__read_mostly ; +struct jump_label_key perf_task_events__read_mostly ;static atomic_t nr_mmap_events__read_mostly ;static atomic_t nr_comm_events__read_mostly ;static atomic_t nr_task_events__read_mostly ;
@@ -4851,7 +4851,7 @@ fail:return err; } -atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX ]; +struct jump_label_key perf_swevent_enabled[PERF_COUNT_SW_MAX ];static void sw_perf_event_destroy (struct perf_event *event) {
kernel/tracepoint.c +9 -14
@@ -251,9 +251,9 @@ static void set_tracepoint(struct tracepoint_entry **entry, {WARN_ON (strcmp ((*entry)->name, elem->name) !=0 ); -if (elem->regfunc && !elem->state && active) +if (elem->regfunc && !jump_label_enabled (&elem->key) && active) elem->regfunc (); -else if (elem->unregfunc && elem->state && !active) +else if (elem->unregfunc &&jump_label_enabled (&elem->key) && !active) elem->unregfunc ();/*
@@ -264,13 +264,10 @@ static void set_tracepoint(struct tracepoint_entry **entry,* is used. */ rcu_assign_pointer (elem->funcs, (*entry)->funcs); -if (!elem->state && active) { -jump_label_enable (&elem->state); - elem->state = active; - }else if (elem->state && !active) { -jump_label_disable (&elem->state); - elem->state = active; - } +if (active && !jump_label_enabled (&elem->key)) +jump_label_inc (&elem->key); +else if (!active &&jump_label_enabled (&elem->key)) +jump_label_dec (&elem->key); }/*
@@ -281,13 +278,11 @@ static void set_tracepoint(struct tracepoint_entry **entry,*/ static void disable_tracepoint (struct tracepoint *elem) { -if (elem->unregfunc && elem->state) +if (elem->unregfunc &&jump_label_enabled (&elem->key)) elem->unregfunc (); -if (elem->state) { -jump_label_disable (&elem->state); - elem->state =0 ; - } +if (jump_label_enabled (&elem->key)) +jump_label_dec (&elem->key);rcu_assign_pointer (elem->funcs,NULL ); }
Signature · 1 line
1.7.1
Steven Rostedt
maintainerNeed ack from sparc maintainer (was: [PATCH 1/4] jump label: introduce static_branch() interface)
Quoted 50 lines · Jason Baron
Introduce:
static
__always_inlineboolstatic_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 codeenable/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 anatomic_read(), and jump_label_inc()/dec() are simplyatomic_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.6jump label *not* configured in (using atomic reads)
avg: 800.1jump label *not* configured in (regular reads)
avg: 803.4
Quoted 8 lines
Signed-off-by Peter Zijlstra <[email protected]>Signed-off-by Jason Baron <[email protected]>Suggested-by H. Peter Anvin <[email protected]>Tested-by David Daney <[email protected]>Acked-by Ralf Baechle <[email protected]>--- arch/mips/include/asm/jump_label.h | 22 +- arch/sparc/include/asm/jump_label.h | 25 +-
Hi David,
Can you give your Acked-by for this change.
Thanks,
-- Steve
Quoted 52 lines
arch/x86/include/asm/alternative.h | 3 +- arch/x86/include/asm/jump_label.h | 26 +- arch/x86/kernel/alternative.c | 2 +- arch/x86/kernel/module.c | 1 + include/asm-generic/vmlinux.lds.h | 14 +- include/linux/dynamic_debug.h | 2 - include/linux/jump_label.h | 89 ++++--- include/linux/jump_label_ref.h | 44 --- include/linux/perf_event.h | 26 +- include/linux/tracepoint.h | 22 +- kernel/jump_label.c | 539 ++++++++++++++--------------------- kernel/perf_event.c | 4 +- kernel/tracepoint.c | 23 +- 15 files changed, 356 insertions(+), 486 deletions(-) delete mode 100644 include/linux/jump_label_ref.harch/sparc/include/asm/jump_label.h +14
-11@@ -7,17 +7,20 @@#define JUMP_LABEL_NOP_SIZE 4 -#define JUMP_LABEL (key, label) \ - do { \ - asm goto("1:\n\t" \ - "nop\n\t" \ - "nop\n\t" \ - ".pushsection __jump_table, \"a\"\n\t"\ - ".align 4\n\t" \ - ".word 1b, %l[" #label "], %c0\n\t" \ - ".popsection \n\t" \ - : : "i" (key) : : label);\ - } while (0) +static __always_inline bool arch_static_branch(struct jump_label_key *key) +{ + asm goto("1:\n\t" +"nop\n\t" +"nop\n\t" +".pushsection __jump_table, \"aw\"\n\t" +".align 4\n\t" +".word 1b, %l[l_yes], %c0\n\t" +".popsection \n\t" + : :"i" (key) : : l_yes); +return false; +l_yes: +return true; +}
Re: Need ack from sparc maintainer
From: Steven Rostedt <[email protected]>
Date: Wed, 16 Mar 2011 16:06:13 -0400
Quoted 1 line
Can you give your Acked-by for this change.
Steven Rostedt
maintainerRe: Need ack from sparc maintainer
Quoted 6 lines · David Miller
From: Steven Rostedt <[email protected]>
Date: Wed, 16 Mar 2011 16:06:13 -0400Quoted 1 line
Can you give your Acked-by for this change.
Acked-by David S. Miller <[email protected]>
Thanks David!
-- Steve
Re: [PATCH 1/4] jump label: introduce static_branch() interface
In reply to Jason BaronQuoted 2 lines · Jason Baron
Introduce:
oops. I forgot to update my tree. Here is the updated patch:
-------------------------------------------------------------
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
--- arch/mips/include/asm/jump_label.h | 22 +- arch/sparc/include/asm/jump_label.h | 25 +- arch/x86/include/asm/alternative.h | 3 +- arch/x86/include/asm/jump_label.h | 26 +- arch/x86/kernel/alternative.c | 2 +- arch/x86/kernel/module.c | 1 + include/asm-generic/vmlinux.lds.h | 14 +- include/linux/dynamic_debug.h | 2 - include/linux/jump_label.h | 89 ++++--- include/linux/jump_label_ref.h | 44 --- include/linux/perf_event.h | 26 +- include/linux/tracepoint.h | 22 +- kernel/jump_label.c | 539 ++++++++++++++--------------------- kernel/perf_event.c | 4 +- kernel/tracepoint.c | 23 +- 15 files changed, 356 insertions(+), 486 deletions(-) delete mode 100644 include/linux/jump_label_ref.h
arch/mips/include/asm/jump_label.h +12 -10
@@ -20,16 +20,18 @@#define WORD_INSN ".word"#endif -#define JUMP_LABEL (key, label) \ - do { \ - asm goto("1:\tnop\n\t" \ - "nop\n\t" \ - ".pushsection __jump_table, \"a\"\n\t" \ - WORD_INSN " 1b, %l[" #label "], %0\n\t" \ - ".popsection\n\t" \ - : : "i" (key) : : label); \ - } while (0) - +static __always_inline bool arch_static_branch(struct jump_label_key *key) +{ + asm goto("1:\tnop\n\t" +"nop\n\t" +".pushsection __jump_table, \"aw\"\n\t" +WORD_INSN " 1b, %l[l_yes], %0\n\t" +".popsection\n\t" + : :"i" (key) : : l_yes); +return false; +l_yes: +return true; +}#endif /* __KERNEL__ */
arch/sparc/include/asm/jump_label.h +14 -11
@@ -7,17 +7,20 @@#define JUMP_LABEL_NOP_SIZE 4 -#define JUMP_LABEL (key, label) \ - do { \ - asm goto("1:\n\t" \ - "nop\n\t" \ - "nop\n\t" \ - ".pushsection __jump_table, \"a\"\n\t"\ - ".align 4\n\t" \ - ".word 1b, %l[" #label "], %c0\n\t" \ - ".popsection \n\t" \ - : : "i" (key) : : label);\ - } while (0) +static __always_inline bool arch_static_branch(struct jump_label_key *key) +{ + asm goto("1:\n\t" +"nop\n\t" +"nop\n\t" +".pushsection __jump_table, \"aw\"\n\t" +".align 4\n\t" +".word 1b, %l[l_yes], %c0\n\t" +".popsection \n\t" + : :"i" (key) : : l_yes); +return false; +l_yes: +return true; +}#endif /* __KERNEL__ */
arch/x86/include/asm/alternative.h +1 -2
@@ -4,7 +4,6 @@#include <linux/types.h> #include <linux/stddef.h> #include <linux/stringify.h> -#include <linux/jump_label.h> #include <asm/asm.h> /*
@@ -191,7 +190,7 @@ extern void *text_poke(void *addr, const void *opcode, size_t len);extern void *text_poke_smp (void *addr,const void *opcode,size_t len);extern void text_poke_smp_batch (struct text_poke_param *params,int n); -#if defined(CONFIG_DYNAMIC_FTRACE ) || defined(HAVE_JUMP_LABEL ) +#if defined(CONFIG_DYNAMIC_FTRACE ) || defined(CONFIG_JUMP_LABEL )#define IDEAL_NOP_SIZE_5 5extern unsigned char ideal_nop5[IDEAL_NOP_SIZE_5 ];extern void arch_init_ideal_nop5 (void );
arch/x86/include/asm/jump_label.h +15 -11
@@ -5,20 +5,24 @@#include <linux/types.h> #include <asm/nops.h> +#include <asm/asm.h> #define JUMP_LABEL_NOP_SIZE 5 -# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t" - -# define JUMP_LABEL (key, label) \ - do { \ - asm goto("1:" \ - JUMP_LABEL_INITIAL_NOP \ - ".pushsection __jump_table, \"aw\" \n\t"\ - _ASM_PTR "1b, %l[" #label "], %c0 \n\t" \ - ".popsection \n\t" \ - : : "i" (key) : : label); \ - } while (0) +#define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t" + +static __always_inline bool arch_static_branch(struct jump_label_key *key) +{ + asm goto("1:" +JUMP_LABEL_INITIAL_NOP +".pushsection __jump_table, \"aw\" \n\t" + _ASM_PTR"1b, %l[l_yes], %c0 \n\t" +".popsection \n\t" + : :"i" (key) : : l_yes); +return false; +l_yes: +return true; +}#endif /* __KERNEL__ */
arch/x86/kernel/alternative.c +1 -1
@@ -674,7 +674,7 @@ void __kprobes text_poke_smp_batch(struct text_poke_param *params, int n)__stop_machine (stop_machine_text_poke, (void *)&tpp,NULL ); } -#if defined(CONFIG_DYNAMIC_FTRACE ) || defined(HAVE_JUMP_LABEL ) +#if defined(CONFIG_DYNAMIC_FTRACE ) || defined(CONFIG_JUMP_LABEL )#ifdef CONFIG_X86_64 unsigned char ideal_nop5[5 ] = {0x66 ,0x66 ,0x66 ,0x66 ,0x90 };
arch/x86/kernel/module.c +1 -0
@@ -24,6 +24,7 @@#include <linux/bug.h> #include <linux/mm.h> #include <linux/gfp.h> +#include <linux/jump_label.h> #include <asm/system.h> #include <asm/page.h>
include/asm-generic/vmlinux.lds.h +4 -10
@@ -170,6 +170,10 @@STRUCT_ALIGN (); \ *(__tracepoints) \/* implement dynamic printk debug */ \ + . = ALIGN(8); \ + VMLINUX_SYMBOL(__start___jump_table) = .; \ + *(__jump_table ) \ + VMLINUX_SYMBOL(__stop___jump_table) = .; \ . = ALIGN(8); \ VMLINUX_SYMBOL(__start___verbose) = .; \ *(__verbose) \
@@ -228,8 +232,6 @@ \ BUG_TABLE \ \ - JUMP_TABLE \ - \ /* PCI quirks */ \ .pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \ VMLINUX_SYMBOL(__start_pci_fixups_early) = .; \
@@ -589,14 +591,6 @@#define BUG_TABLE #endif -#define JUMP_TABLE \ - . = ALIGN(8); \ - __jump_table : AT(ADDR(__jump_table) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___jump_table) = .; \ - *(__jump_table) \ - VMLINUX_SYMBOL(__stop___jump_table) = .; \ - } -#ifdef CONFIG_PM_TRACE #define TRACEDATA \ . = ALIGN(4); \
include/linux/dynamic_debug.h +0 -2
@@ -1,8 +1,6 @@#ifndef _DYNAMIC_DEBUG_H#define _DYNAMIC_DEBUG_H -#include <linux/jump_label.h> -/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They * use independent hash functions, to reduce the chance of false positives.
include/linux/jump_label.h +56 -33
129 lines not on this page · raw message
include/linux/jump_label_ref.h deleted +0 -44
44 lines not on this page · raw message
include/linux/perf_event.h +13 -13
@@ -505,7 +505,7 @@ struct perf_guest_info_callbacks {#include <linux/ftrace.h> #include <linux/cpu.h> #include <linux/irq_work.h> -#include <linux/jump_label_ref.h> +#include <linux/jump_label.h> #include <asm/atomic.h> #include <asm/local.h>
@@ -1036,7 +1036,7 @@ static inline int is_software_event(struct perf_event *event)return event->pmu->task_ctx_nr == perf_sw_context; } -extern atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX ]; +extern struct jump_label_key perf_swevent_enabled[PERF_COUNT_SW_MAX ];extern void __perf_sw_event (u32 ,u64 ,int ,struct pt_regs *,u64 );
@@ -1065,22 +1065,21 @@ perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr) {struct pt_regs hot_regs; -JUMP_LABEL (&perf_swevent_enabled[event_id], have_event); -return ; - -have_event: -if (!regs) { -perf_fetch_caller_regs (&hot_regs); - regs = &hot_regs; +if (static_branch (&perf_swevent_enabled[event_id])) { +if (!regs) { +perf_fetch_caller_regs (&hot_regs); + regs = &hot_regs; + } +__perf_sw_event (event_id, nr, nmi, regs, addr); } -__perf_sw_event (event_id, nr, nmi, regs, addr); } -extern atomic_t perf_sched_events; +extern struct jump_label_key perf_sched_events;static inline void perf_event_task_sched_in (struct task_struct *task) { -COND_STMT (&perf_sched_events,__perf_event_task_sched_in (task)); +if (static_branch (&perf_sched_events)) +__perf_event_task_sched_in (task); } static inline
@@ -1088,7 +1087,8 @@ void perf_event_task_sched_out(struct task_struct *task, struct task_struct *nex {perf_sw_event (PERF_COUNT_SW_CONTEXT_SWITCHES ,1 ,1 ,NULL ,0 ); -COND_STMT (&perf_sched_events,__perf_event_task_sched_out (task, next)); +if (static_branch (&perf_sched_events)) +__perf_event_task_sched_out (task, next); }extern void perf_event_mmap (struct vm_area_struct *vma);
include/linux/tracepoint.h +10 -12
@@ -29,7 +29,7 @@ struct tracepoint_func {struct tracepoint {const char *name;/* Tracepoint name */ -int state;/* State. */ +struct jump_label_key key;void (*regfunc)(void );void (*unregfunc)(void );struct tracepoint_func __rcu *funcs;
@@ -146,9 +146,7 @@ void tracepoint_update_probe_range(struct tracepoint * const *begin, extern struct tracepoint __tracepoint_##name; \ static inline void trace_##name(proto) \ { \ - JUMP_LABEL(&__tracepoint_##name.state, do_trace); \ - return; \ -do_trace: \ + if (static_branch(&__tracepoint_##name.key)) \ __DO_TRACE(&__tracepoint_##name, \ TP_PROTO(data_proto), \ TP_ARGS(data_args), \
@@ -176,14 +174,14 @@ do_trace: \* structures, so we create an array of pointers that will be used for iteration * on the tracepoints. */ -#define DEFINE_TRACE_FN (name, reg, unreg) \ - static const char __tpstrtab_##name[] \ - __attribute__((section("__tracepoints_strings"))) = #name; \ - struct tracepoint __tracepoint_##name \ - __attribute__((section("__tracepoints"))) = \ - { __tpstrtab_##name, 0, reg, unreg, NULL }; \ - static struct tracepoint * const __tracepoint_ptr_##name __used \ - __attribute__((section("__tracepoints_ptrs"))) = \ +#define DEFINE_TRACE_FN (name, reg, unreg) \ + static const char __tpstrtab_##name[] \ + __attribute__((section("__tracepoints_strings"))) = #name; \ + struct tracepoint __tracepoint_##name \ + __attribute__((section("__tracepoints"))) = \ + { __tpstrtab_##name, JUMP_LABEL_INIT, reg, unreg, NULL };\ + static struct tracepoint * const __tracepoint_ptr_##name __used \ + __attribute__((section("__tracepoints_ptrs"))) = \ &__tracepoint_##name;#define DEFINE_TRACE (name) \
kernel/jump_label.c +218 -321
670 lines not on this page · raw message
kernel/perf_event.c +2 -2
@@ -125,7 +125,7 @@ enum event_type_t {* perf_sched_events : >0 events exist * perf_cgroup_events: >0 per-cpu cgroup events exist on this cpu */ -atomic_t perf_sched_events__read_mostly ; +struct jump_label_key perf_sched_events__read_mostly ; static DEFINE_PER_CPU(atomic_t, perf_cgroup_events);static atomic_t nr_mmap_events__read_mostly ;
@@ -5406,7 +5406,7 @@ fail:return err; } -atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX ]; +struct jump_label_key perf_swevent_enabled[PERF_COUNT_SW_MAX ];static void sw_perf_event_destroy (struct perf_event *event) {
kernel/tracepoint.c +9 -14
@@ -251,9 +251,9 @@ static void set_tracepoint(struct tracepoint_entry **entry, {WARN_ON (strcmp ((*entry)->name, elem->name) !=0 ); -if (elem->regfunc && !elem->state && active) +if (elem->regfunc && !jump_label_enabled (&elem->key) && active) elem->regfunc (); -else if (elem->unregfunc && elem->state && !active) +else if (elem->unregfunc &&jump_label_enabled (&elem->key) && !active) elem->unregfunc ();/*
@@ -264,13 +264,10 @@ static void set_tracepoint(struct tracepoint_entry **entry,* is used. */ rcu_assign_pointer (elem->funcs, (*entry)->funcs); -if (!elem->state && active) { -jump_label_enable (&elem->state); - elem->state = active; - }else if (elem->state && !active) { -jump_label_disable (&elem->state); - elem->state = active; - } +if (active && !jump_label_enabled (&elem->key)) +jump_label_inc (&elem->key); +else if (!active &&jump_label_enabled (&elem->key)) +jump_label_dec (&elem->key); }/*
@@ -281,13 +278,11 @@ static void set_tracepoint(struct tracepoint_entry **entry,*/ static void disable_tracepoint (struct tracepoint *elem) { -if (elem->unregfunc && elem->state) +if (elem->unregfunc &&jump_label_enabled (&elem->key)) elem->unregfunc (); -if (elem->state) { -jump_label_disable (&elem->state); - elem->state =0 ; - } +if (jump_label_enabled (&elem->key)) +jump_label_dec (&elem->key);rcu_assign_pointer (elem->funcs,NULL ); }
Signature · 1 line
1.7.1
[tip:perf/core] jump label: Introduce static_branch() interface
Commit-ID: d430d3d7e646eb1eac2bb4aa244a644312e67c76 Gitweb: http://git.kernel.org/tip/d430d3d7e646eb1eac2bb4aa244a644312e67c76 Author: Jason Baron <[email protected]> AuthorDate: Wed, 16 Mar 2011 17:29:47 -0400 Committer: Steven Rostedt <[email protected]> CommitDate: Mon, 4 Apr 2011 12:48:08 -0400
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
LKML-Reference: <[email protected]>
--- arch/mips/include/asm/jump_label.h | 22 +- arch/sparc/include/asm/jump_label.h | 25 +- arch/x86/include/asm/alternative.h | 3 +- arch/x86/include/asm/jump_label.h | 26 +- arch/x86/kernel/alternative.c | 2 +- arch/x86/kernel/module.c | 1 + include/asm-generic/vmlinux.lds.h | 14 +- include/linux/dynamic_debug.h | 2 - include/linux/jump_label.h | 89 ++++--- include/linux/jump_label_ref.h | 44 --- include/linux/perf_event.h | 26 +- include/linux/tracepoint.h | 22 +- kernel/jump_label.c | 539 ++++++++++++++--------------------- kernel/perf_event.c | 4 +- kernel/tracepoint.c | 23 +- 15 files changed, 356 insertions(+), 486 deletions(-)
arch/mips/include/asm/jump_label.h +12 -10
@@ -20,16 +20,18 @@#define WORD_INSN ".word"#endif -#define JUMP_LABEL (key, label) \ - do { \ - asm goto("1:\tnop\n\t" \ - "nop\n\t" \ - ".pushsection __jump_table, \"a\"\n\t" \ - WORD_INSN " 1b, %l[" #label "], %0\n\t" \ - ".popsection\n\t" \ - : : "i" (key) : : label); \ - } while (0) - +static __always_inline bool arch_static_branch(struct jump_label_key *key) +{ + asm goto("1:\tnop\n\t" +"nop\n\t" +".pushsection __jump_table, \"aw\"\n\t" +WORD_INSN " 1b, %l[l_yes], %0\n\t" +".popsection\n\t" + : :"i" (key) : : l_yes); +return false; +l_yes: +return true; +}#endif /* __KERNEL__ */
arch/sparc/include/asm/jump_label.h +14 -11
@@ -7,17 +7,20 @@#define JUMP_LABEL_NOP_SIZE 4 -#define JUMP_LABEL (key, label) \ - do { \ - asm goto("1:\n\t" \ - "nop\n\t" \ - "nop\n\t" \ - ".pushsection __jump_table, \"a\"\n\t"\ - ".align 4\n\t" \ - ".word 1b, %l[" #label "], %c0\n\t" \ - ".popsection \n\t" \ - : : "i" (key) : : label);\ - } while (0) +static __always_inline bool arch_static_branch(struct jump_label_key *key) +{ + asm goto("1:\n\t" +"nop\n\t" +"nop\n\t" +".pushsection __jump_table, \"aw\"\n\t" +".align 4\n\t" +".word 1b, %l[l_yes], %c0\n\t" +".popsection \n\t" + : :"i" (key) : : l_yes); +return false; +l_yes: +return true; +}#endif /* __KERNEL__ */
arch/x86/include/asm/alternative.h +1 -2
@@ -4,7 +4,6 @@#include <linux/types.h> #include <linux/stddef.h> #include <linux/stringify.h> -#include <linux/jump_label.h> #include <asm/asm.h> /*
@@ -191,7 +190,7 @@ extern void *text_poke(void *addr, const void *opcode, size_t len);extern void *text_poke_smp (void *addr,const void *opcode,size_t len);extern void text_poke_smp_batch (struct text_poke_param *params,int n); -#if defined(CONFIG_DYNAMIC_FTRACE ) || defined(HAVE_JUMP_LABEL ) +#if defined(CONFIG_DYNAMIC_FTRACE ) || defined(CONFIG_JUMP_LABEL )#define IDEAL_NOP_SIZE_5 5extern unsigned char ideal_nop5[IDEAL_NOP_SIZE_5 ];extern void arch_init_ideal_nop5 (void );
arch/x86/include/asm/jump_label.h +15 -11
@@ -5,20 +5,24 @@#include <linux/types.h> #include <asm/nops.h> +#include <asm/asm.h> #define JUMP_LABEL_NOP_SIZE 5 -# define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t" - -# define JUMP_LABEL (key, label) \ - do { \ - asm goto("1:" \ - JUMP_LABEL_INITIAL_NOP \ - ".pushsection __jump_table, \"aw\" \n\t"\ - _ASM_PTR "1b, %l[" #label "], %c0 \n\t" \ - ".popsection \n\t" \ - : : "i" (key) : : label); \ - } while (0) +#define JUMP_LABEL_INITIAL_NOP ".byte 0xe9 \n\t .long 0\n\t" + +static __always_inline bool arch_static_branch(struct jump_label_key *key) +{ + asm goto("1:" +JUMP_LABEL_INITIAL_NOP +".pushsection __jump_table, \"aw\" \n\t" + _ASM_PTR"1b, %l[l_yes], %c0 \n\t" +".popsection \n\t" + : :"i" (key) : : l_yes); +return false; +l_yes: +return true; +}#endif /* __KERNEL__ */
arch/x86/kernel/alternative.c +1 -1
@@ -679,7 +679,7 @@ void __kprobes text_poke_smp_batch(struct text_poke_param *params, int n)__stop_machine (stop_machine_text_poke, (void *)&tpp,NULL ); } -#if defined(CONFIG_DYNAMIC_FTRACE ) || defined(HAVE_JUMP_LABEL ) +#if defined(CONFIG_DYNAMIC_FTRACE ) || defined(CONFIG_JUMP_LABEL )#ifdef CONFIG_X86_64 unsigned char ideal_nop5[5 ] = {0x66 ,0x66 ,0x66 ,0x66 ,0x90 };
arch/x86/kernel/module.c +1 -0
@@ -24,6 +24,7 @@#include <linux/bug.h> #include <linux/mm.h> #include <linux/gfp.h> +#include <linux/jump_label.h> #include <asm/system.h> #include <asm/page.h>
include/asm-generic/vmlinux.lds.h +4 -10
@@ -170,6 +170,10 @@STRUCT_ALIGN (); \ *(__tracepoints) \/* implement dynamic printk debug */ \ + . = ALIGN(8); \ + VMLINUX_SYMBOL(__start___jump_table) = .; \ + *(__jump_table ) \ + VMLINUX_SYMBOL(__stop___jump_table) = .; \ . = ALIGN(8); \ VMLINUX_SYMBOL(__start___verbose) = .; \ *(__verbose) \
@@ -228,8 +232,6 @@ \ BUG_TABLE \ \ - JUMP_TABLE \ - \ /* PCI quirks */ \ .pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \ VMLINUX_SYMBOL(__start_pci_fixups_early) = .; \
@@ -589,14 +591,6 @@#define BUG_TABLE #endif -#define JUMP_TABLE \ - . = ALIGN(8); \ - __jump_table : AT(ADDR(__jump_table) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___jump_table) = .; \ - *(__jump_table) \ - VMLINUX_SYMBOL(__stop___jump_table) = .; \ - } -#ifdef CONFIG_PM_TRACE #define TRACEDATA \ . = ALIGN(4); \
include/linux/dynamic_debug.h +0 -2
@@ -1,8 +1,6 @@#ifndef _DYNAMIC_DEBUG_H#define _DYNAMIC_DEBUG_H -#include <linux/jump_label.h> -/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They * use independent hash functions, to reduce the chance of false positives.
include/linux/jump_label.h +56 -33
129 lines not on this page · raw message
include/linux/jump_label_ref.h deleted +0 -44
44 lines not on this page · raw message
include/linux/perf_event.h +13 -13
@@ -505,7 +505,7 @@ struct perf_guest_info_callbacks {#include <linux/ftrace.h> #include <linux/cpu.h> #include <linux/irq_work.h> -#include <linux/jump_label_ref.h> +#include <linux/jump_label.h> #include <asm/atomic.h> #include <asm/local.h>
@@ -1034,7 +1034,7 @@ static inline int is_software_event(struct perf_event *event)return event->pmu->task_ctx_nr == perf_sw_context; } -extern atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX ]; +extern struct jump_label_key perf_swevent_enabled[PERF_COUNT_SW_MAX ];extern void __perf_sw_event (u32 ,u64 ,int ,struct pt_regs *,u64 );
@@ -1063,22 +1063,21 @@ perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr) {struct pt_regs hot_regs; -JUMP_LABEL (&perf_swevent_enabled[event_id], have_event); -return ; - -have_event: -if (!regs) { -perf_fetch_caller_regs (&hot_regs); - regs = &hot_regs; +if (static_branch (&perf_swevent_enabled[event_id])) { +if (!regs) { +perf_fetch_caller_regs (&hot_regs); + regs = &hot_regs; + } +__perf_sw_event (event_id, nr, nmi, regs, addr); } -__perf_sw_event (event_id, nr, nmi, regs, addr); } -extern atomic_t perf_sched_events; +extern struct jump_label_key perf_sched_events;static inline void perf_event_task_sched_in (struct task_struct *task) { -COND_STMT (&perf_sched_events,__perf_event_task_sched_in (task)); +if (static_branch (&perf_sched_events)) +__perf_event_task_sched_in (task); } static inline
@@ -1086,7 +1085,8 @@ void perf_event_task_sched_out(struct task_struct *task, struct task_struct *nex {perf_sw_event (PERF_COUNT_SW_CONTEXT_SWITCHES ,1 ,1 ,NULL ,0 ); -COND_STMT (&perf_sched_events,__perf_event_task_sched_out (task, next)); +if (static_branch (&perf_sched_events)) +__perf_event_task_sched_out (task, next); }extern void perf_event_mmap (struct vm_area_struct *vma);
include/linux/tracepoint.h +10 -12
@@ -29,7 +29,7 @@ struct tracepoint_func {struct tracepoint {const char *name;/* Tracepoint name */ -int state;/* State. */ +struct jump_label_key key;void (*regfunc)(void );void (*unregfunc)(void );struct tracepoint_func __rcu *funcs;
@@ -146,9 +146,7 @@ void tracepoint_update_probe_range(struct tracepoint * const *begin, extern struct tracepoint __tracepoint_##name; \ static inline void trace_##name(proto) \ { \ - JUMP_LABEL(&__tracepoint_##name.state, do_trace); \ - return; \ -do_trace: \ + if (static_branch(&__tracepoint_##name.key)) \ __DO_TRACE(&__tracepoint_##name, \ TP_PROTO(data_proto), \ TP_ARGS(data_args), \
@@ -176,14 +174,14 @@ do_trace: \* structures, so we create an array of pointers that will be used for iteration * on the tracepoints. */ -#define DEFINE_TRACE_FN (name, reg, unreg) \ - static const char __tpstrtab_##name[] \ - __attribute__((section("__tracepoints_strings"))) = #name; \ - struct tracepoint __tracepoint_##name \ - __attribute__((section("__tracepoints"))) = \ - { __tpstrtab_##name, 0, reg, unreg, NULL }; \ - static struct tracepoint * const __tracepoint_ptr_##name __used \ - __attribute__((section("__tracepoints_ptrs"))) = \ +#define DEFINE_TRACE_FN (name, reg, unreg) \ + static const char __tpstrtab_##name[] \ + __attribute__((section("__tracepoints_strings"))) = #name; \ + struct tracepoint __tracepoint_##name \ + __attribute__((section("__tracepoints"))) = \ + { __tpstrtab_##name, JUMP_LABEL_INIT, reg, unreg, NULL };\ + static struct tracepoint * const __tracepoint_ptr_##name __used \ + __attribute__((section("__tracepoints_ptrs"))) = \ &__tracepoint_##name;#define DEFINE_TRACE (name) \
kernel/jump_label.c +218 -321
670 lines not on this page · raw message
kernel/perf_event.c +2 -2
@@ -125,7 +125,7 @@ enum event_type_t {* perf_sched_events : >0 events exist * perf_cgroup_events: >0 per-cpu cgroup events exist on this cpu */ -atomic_t perf_sched_events__read_mostly ; +struct jump_label_key perf_sched_events__read_mostly ; static DEFINE_PER_CPU(atomic_t, perf_cgroup_events);static atomic_t nr_mmap_events__read_mostly ;
@@ -5417,7 +5417,7 @@ fail:return err; } -atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX ]; +struct jump_label_key perf_swevent_enabled[PERF_COUNT_SW_MAX ];static void sw_perf_event_destroy (struct perf_event *event) {
kernel/tracepoint.c +9 -14
@@ -251,9 +251,9 @@ static void set_tracepoint(struct tracepoint_entry **entry, {WARN_ON (strcmp ((*entry)->name, elem->name) !=0 ); -if (elem->regfunc && !elem->state && active) +if (elem->regfunc && !jump_label_enabled (&elem->key) && active) elem->regfunc (); -else if (elem->unregfunc && elem->state && !active) +else if (elem->unregfunc &&jump_label_enabled (&elem->key) && !active) elem->unregfunc ();/*
@@ -264,13 +264,10 @@ static void set_tracepoint(struct tracepoint_entry **entry,* is used. */ rcu_assign_pointer (elem->funcs, (*entry)->funcs); -if (!elem->state && active) { -jump_label_enable (&elem->state); - elem->state = active; - }else if (elem->state && !active) { -jump_label_disable (&elem->state); - elem->state = active; - } +if (active && !jump_label_enabled (&elem->key)) +jump_label_inc (&elem->key); +else if (!active &&jump_label_enabled (&elem->key)) +jump_label_dec (&elem->key); }/*
@@ -281,13 +278,11 @@ static void set_tracepoint(struct tracepoint_entry **entry,*/ static void disable_tracepoint (struct tracepoint *elem) { -if (elem->unregfunc && elem->state) +if (elem->unregfunc &&jump_label_enabled (&elem->key)) elem->unregfunc (); -if (elem->state) { -jump_label_disable (&elem->state); - elem->state =0 ; - } +if (jump_label_enabled (&elem->key)) +jump_label_dec (&elem->key);rcu_assign_pointer (elem->funcs,NULL ); }
PATCH v2 2/4 dynamic debug: add jump label support
In reply to Jason BaronSince jump labels make use of atomic_read(), and dynamic_debug.h gets included by kernel.h, the inclusion of atomic.h in dynamic_debug.h (to get atomic_read()), would cause a circular dependency since atomic.h requires kernel.h. Thus, for dynamic debug I am explicitly including jump_label.h when jump labels are configured, and making use of a regular reads (non-atomic), when jump labels are disabled.
--- include/linux/dynamic_debug.h | 46 ++++++++++++++++++++++++++++++++++------ lib/dynamic_debug.c | 4 +- 2 files changed, 41 insertions(+), 9 deletions(-)
include/linux/dynamic_debug.h +39 -7
@@ -1,6 +1,26 @@#ifndef _DYNAMIC_DEBUG_H#define _DYNAMIC_DEBUG_H +/* +* When jump labels are disabled, they make use of atomic_read(). Since +* dynamic_debug.h gets included by kernel.h, the inclusion of jump_label.h by +* dynamic_debug.h and thus atomic.h (to get atomic_read()), would cause a +* circular dependency since atomic.h requires kernel.h. Thus, for dynamic debug +* we are explicitly including jump_label.h when jump labels are configured, and +* making use of a regular reads (non-atomic), when jump labels are disabled. +*/ +#if defined(CC_HAVE_ASM_GOTO ) && defined(CONFIG_JUMP_LABEL ) +#include <linux/jump_label.h> +#endif + +#ifdef HAVE_JUMP_LABEL +#define dd_enable (dp) do { jump_label_inc(&dp->enabled); } while (0) +#define dd_disable (dp) do { jump_label_dec(&dp->enabled); } while (0) +#else +#define dd_enable (dp) do { dp->enabled = 1; } while (0) +#define dd_disable (dp) do { dp->enabled = 0; } while (0) +#endif +/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They * use independent hash functions, to reduce the chance of false positives.
@@ -31,7 +51,11 @@ struct _ddebug {#define _DPRINTK_FLAGS_PRINT (1<<0)/* printk() a message using the format */ #define _DPRINTK_FLAGS_DEFAULT 0 unsigned int flags:8; -char enabled; +#ifdef HAVE_JUMP_LABEL +struct jump_label_key enabled; +#else +int enabled; +#endif } __attribute__((aligned(8)));
@@ -41,14 +65,22 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,#if defined(CONFIG_DYNAMIC_DEBUG )extern int ddebug_remove_module (const char *mod_name); +#ifdef HAVE_JUMP_LABEL +# define DDEBUG_INIT JUMP_LABEL_INIT +# define DDEBUG_BRANCH (enabled) static_branch(&enabled) +#else +# define DDEBUG_INIT 0 +# define DDEBUG_BRANCH (enabled) unlikely(enabled) +#endif +#define dynamic_pr_debug (fmt, ...) do { \ static struct _ddebug descriptor \ __used \ __attribute__((section("__verbose"), aligned(8))) = \ { KBUILD_MODNAME, __func__, __FILE__, fmt, __LINE__, \ - _DPRINTK_FLAGS_DEFAULT }; \ - if (unlikely(descriptor.enabled)) \ - printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \ + _DPRINTK_FLAGS_DEFAULT, DDEBUG_INIT }; \ + if (DDEBUG_BRANCH(descriptor.enabled)) \ + printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \ } while (0)
@@ -57,9 +89,9 @@ extern int ddebug_remove_module(const char *mod_name);__used \ __attribute__((section("__verbose"), aligned(8))) = \ {KBUILD_MODNAME , __func__, __FILE__, fmt, __LINE__, \ - _DPRINTK_FLAGS_DEFAULT }; \ -if (unlikely (descriptor.enabled)) \ - dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); \ + _DPRINTK_FLAGS_DEFAULT,DDEBUG_INIT }; \ +if (DDEBUG_BRANCH (descriptor.enabled)) \ + dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); \ } while (0) #else
lib/dynamic_debug.c +2 -2
@@ -142,9 +142,9 @@ static void ddebug_change(const struct ddebug_query *query, dt->num_enabled++; dp->flags = newflags;if (newflags) - dp->enabled =1 ; +dd_enable (dp);else - dp->enabled =0 ; +dd_disable (dp);if (verbose) printk(KERN_INFO "ddebug: changed %s:%d [%s]%s %s\n",
Signature · 1 line
1.7.1
PATCH v2 3/4 jump label: add _ASM_ALIGN for x86 and x86_64
In reply to Jason BaronThe linker should not be adding holes to word size aligned pointers, but out of paranoia we are explicitly specifying that alignment. I have not seen any holes in the jump label section in practice.
--- arch/x86/include/asm/jump_label.h | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/x86/include/asm/jump_label.h +1 -0
@@ -16,6 +16,7 @@ static __always_inline bool arch_static_branch(struct jump_label_key *key) asm goto("1:" JUMP_LABEL_INITIAL_NOP ".pushsection __jump_table, \"aw\" \n\t" + _ASM_ALIGN"\n\t" _ASM_PTR"1b, %l[l_yes], %c0 \n\t" ".popsection \n\t" : :"i" (key) : : l_yes);
Signature · 1 line
1.7.1
[tip:perf/core] jump label: Add _ASM_ALIGN for x86 and x86_64
Commit-ID: ef64789413c73f32faa5e5f1bc393e5843b0aa51 Gitweb: http://git.kernel.org/tip/ef64789413c73f32faa5e5f1bc393e5843b0aa51 Author: Jason Baron <[email protected]> AuthorDate: Wed, 16 Mar 2011 15:58:27 -0400 Committer: Steven Rostedt <[email protected]> CommitDate: Mon, 4 Apr 2011 13:42:51 -0400
jump label: Add _ASM_ALIGN for x86 and x86_64
The linker should not be adding holes to word size aligned pointers, but out of paranoia we are explicitly specifying that alignment. I have not seen any holes in the jump label section in practice.
LKML-Reference: <e119fbd060c9452c56063ea6148ba1070e7434cc.1300299760.git.jbaron@redhat.com>
--- arch/x86/include/asm/jump_label.h | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/x86/include/asm/jump_label.h +1 -0
@@ -16,6 +16,7 @@ static __always_inline bool arch_static_branch(struct jump_label_key *key) asm goto("1:" JUMP_LABEL_INITIAL_NOP ".pushsection __jump_table, \"aw\" \n\t" + _ASM_ALIGN"\n\t" _ASM_PTR"1b, %l[l_yes], %c0 \n\t" ".popsection \n\t" : :"i" (key) : : l_yes);
PATCH v2 4/4 jump label: add s390 support
In reply to Jason BaronFrom: Jan Glauber <[email protected]>
Implement the architecture backend for jump label support on s390.
For a shared kernel booted from a NSS silently disable jump labels because the NSS is read-only. Therefore jump labels will be disabled in a shared kernel and can't be activated.
--- arch/s390/Kconfig | 1 + arch/s390/include/asm/jump_label.h | 37 ++++++++++++++++++++++ arch/s390/kernel/Makefile | 2 +- arch/s390/kernel/jump_label.c | 59 ++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+), 1 deletions(-) create mode 100644 arch/s390/include/asm/jump_label.h create mode 100644 arch/s390/kernel/jump_label.c
arch/s390/Kconfig +1 -0
@@ -87,6 +87,7 @@ config S390 select HAVE_KERNEL_LZO select HAVE_GET_USER_PAGES_FAST select HAVE_ARCH_MUTEX_CPU_RELAX + select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 select ARCH_INLINE_SPIN_TRYLOCK select ARCH_INLINE_SPIN_TRYLOCK_BH select ARCH_INLINE_SPIN_LOCK
arch/s390/include/asm/jump_label.h new file +37 -0
@@ -0,0 +1,37 @@ +#ifndef _ASM_S390_JUMP_LABEL_H +#define _ASM_S390_JUMP_LABEL_H + +#include <linux/types.h> + +#define JUMP_LABEL_NOP_SIZE 6 + +#ifdef CONFIG_64BIT +#define ASM_PTR ".quad" +#define ASM_ALIGN ".balign 8" +#else +#define ASM_PTR ".long" +#define ASM_ALIGN ".balign 4" +#endif + +static __always_inline bool arch_static_branch(struct jump_label_key *key) +{ + asm goto("0: brcl 0,0\n" +".pushsection __jump_table, \"aw\"\n" +ASM_ALIGN "\n" +ASM_PTR " 0b, %l[label], %0\n" +".popsection\n" + : :"X" (key) : : label); +return false; +label: +return true; +} + +typedef unsigned long jump_label_t ; + +struct jump_entry { +jump_label_t code; +jump_label_t target; +jump_label_t key; +}; + +#endif
arch/s390/kernel/Makefile +1 -1
@@ -23,7 +23,7 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o \ processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \ - vdso.o vtime.o sysinfo.o nmi.o sclp.o + vdso.o vtime.o sysinfo.o nmi.o sclp.o jump_label.o obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
arch/s390/kernel/jump_label.c new file +59 -0
59 lines not on this page · raw message
Signature · 1 line
1.7.1
[tip:perf/core] jump label: Add s390 support
Commit-ID: 5373db886b791b2bc7811e2c115377916c409a5d Gitweb: http://git.kernel.org/tip/5373db886b791b2bc7811e2c115377916c409a5d Author: Jan Glauber <[email protected]> AuthorDate: Wed, 16 Mar 2011 15:58:30 -0400 Committer: Steven Rostedt <[email protected]> CommitDate: Mon, 4 Apr 2011 13:43:16 -0400
jump label: Add s390 support
Implement the architecture backend for jump label support on s390.
For a shared kernel booted from a NSS silently disable jump labels because the NSS is read-only. Therefore jump labels will be disabled in a shared kernel and can't be activated.
LKML-Reference: <6935d2c41ce111e1719176ed4bbd3dbe4de80855.1300299760.git.jbaron@redhat.com>
--- arch/s390/Kconfig | 1 + arch/s390/include/asm/jump_label.h | 37 ++++++++++++++++++++++ arch/s390/kernel/Makefile | 2 +- arch/s390/kernel/jump_label.c | 59 ++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+), 1 deletions(-)
arch/s390/Kconfig +1 -0
@@ -88,6 +88,7 @@ config S390 select HAVE_KERNEL_XZ select HAVE_GET_USER_PAGES_FAST select HAVE_ARCH_MUTEX_CPU_RELAX + select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 select ARCH_INLINE_SPIN_TRYLOCK select ARCH_INLINE_SPIN_TRYLOCK_BH select ARCH_INLINE_SPIN_LOCK
arch/s390/include/asm/jump_label.h new file +37 -0
@@ -0,0 +1,37 @@ +#ifndef _ASM_S390_JUMP_LABEL_H +#define _ASM_S390_JUMP_LABEL_H + +#include <linux/types.h> + +#define JUMP_LABEL_NOP_SIZE 6 + +#ifdef CONFIG_64BIT +#define ASM_PTR ".quad" +#define ASM_ALIGN ".balign 8" +#else +#define ASM_PTR ".long" +#define ASM_ALIGN ".balign 4" +#endif + +static __always_inline bool arch_static_branch(struct jump_label_key *key) +{ + asm goto("0: brcl 0,0\n" +".pushsection __jump_table, \"aw\"\n" +ASM_ALIGN "\n" +ASM_PTR " 0b, %l[label], %0\n" +".popsection\n" + : :"X" (key) : : label); +return false; +label: +return true; +} + +typedef unsigned long jump_label_t ; + +struct jump_entry { +jump_label_t code; +jump_label_t target; +jump_label_t key; +}; + +#endif
arch/s390/kernel/Makefile +1 -1
@@ -23,7 +23,7 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o \ processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o \ - vdso.o vtime.o sysinfo.o nmi.o sclp.o + vdso.o vtime.o sysinfo.o nmi.o sclp.o jump_label.o obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
arch/s390/kernel/jump_label.c new file +59 -0
59 lines not on this page · raw message
Steven Rostedt
maintainerQuoted 5 lines · Jason Baron
Hi,
Update against tip/perf/urgent. I've incorporated feedback from the last round. Hopefully these can still be considered for .39.
Doesn't apply to tip/perf/urgent. Could you try again.
Thanks,
-- Steve
Quoted 7 lines · Steven Rostedt
Quoted 5 lines · Jason Baron
Hi,
Update against tip/perf/urgent. I've incorporated feedback from the last round. Hopefully these can still be considered for .39.
Quoted 5 lines
Doesn't apply to tip/perf/urgent. Could you try again.
Thanks,
-- Steve
Hi,
yes, applying would be nice :)
Looks like I forgot a 'git fetch' there. After doing that, only patch 1/4 is affected b/c 'perf_task_events' was renamed to 'perf_sched_events'. I've re-posed 1/4.
thanks,
-Jason
Mathieu Desnoyers
Acked-byQuoted 14 lines · * Jason Baron ([email protected]) wrote:
Quoted 7 lines · Steven Rostedt
Quoted 5 lines · Jason Baron
Hi,
Update against tip/perf/urgent. I've incorporated feedback from the last round. Hopefully these can still be considered for .39.
Quoted 5 lines
Doesn't apply to tip/perf/urgent. Could you try again.
Thanks,
-- Steve
Quoted 7 lines
Hi,
yes, applying would be nice :)
Looks like I forgot a 'git fetch' there. After doing that, only patch 1/4 is affected b/c '
perf_task_events' was renamed to 'perf_sched_events'. I've re-posed 1/4.
I'm getting more confident about the alignment story, as we're generating these structures directly from assembly. You can add my Acked-by to this patch series.
Thanks!
Mathieu
Quoted 4 lines
thanks,
-Jason
Signature · 4 lines
Mathieu Desnoyers Operating System Efficiency R&D Consultant EfficiOS Inc. http://www.efficios.com