tracing vs world
Subsystems (17)
Peter Zijlstra
maintainerv3 cover tracing vs world
Hi all,
These here patches are the result of Mathieu and Steve trying to get commit 865e63b04e9b2 ("tracing: Add back in rcu_irq_enter/exit_irqson() for rcuidle tracepoints") reverted again.
One of the things discovered is that tracing MUST NOT happen before nmi_enter() or after nmi_exit(). Audit results of the previous version are still valid.
This then snowballed into auditing other exceptions, notably #MC, and #BP. Lots of patches came out of that.
I would love for some tooling in this area. Dan, smatch has full callchains right? Would it be possible to have an __assert_no_tracing__() marker of sorts that validates that no possible callchain reaching that assertion has hit tracing before that point?
It would mean you have to handle the various means of 'notrace' annotation (both the function attribute as well as the Makefile rules), recognising tracepoints and ideally handling NOKPROBE annotations.
Changes since -v2:
- #MC / ist_enter() audit -- first 4 patches. After this in_nmi() should always be set 'correctly'.
- RCU IRQ enter/exit function simplification
- #BP / poke_int3_handler() audit -- last many patches.
- pulled in some locking/kcsan patches
Changes since -v1:
- Added tags
- Changed #4; changed nmi_enter() to use __preempt_count_add() vs marking preempt_count_add() notrace.
- Changed #5; confusion on which functions are notrace due to Makefile
- Added #9; remove limitation on the perf-function-trace coupling
Peter Zijlstra
maintainerPATCH v3 1/22 hardirq/nmi: Allow nested nmi_enter()
Since there are already a number of sites (ARM64, PowerPC) that effectively nest nmi_enter(), lets make the primitive support this before adding even more.
--- arch/arm64/include/asm/hardirq.h | 4 ++-- arch/arm64/kernel/sdei.c | 14 ++------------ arch/arm64/kernel/traps.c | 8 ++------ arch/powerpc/kernel/traps.c | 19 +++++-------------- include/linux/hardirq.h | 2 +- include/linux/preempt.h | 4 ++-- kernel/printk/printk_safe.c | 6 ++++-- 7 files changed, 18 insertions(+), 39 deletions(-)
arch/arm64/include/asm/hardirq.h +2 -2
@@ -38,7 +38,7 @@ DECLARE_PER_CPU(struct nmi_ctx, nmi_cont#define arch_nmi_enter () \ do { \ - if (is_kernel_in_hyp_mode()) { \ + if (is_kernel_in_hyp_mode() && !in_nmi()) { \ struct nmi_ctx *nmi_ctx = this_cpu_ptr(&nmi_contexts); \ nmi_ctx->hcr = read_sysreg(hcr_el2); \ if (!(nmi_ctx->hcr & HCR_TGE)) { \
@@ -50,7 +50,7 @@ DECLARE_PER_CPU(struct nmi_ctx, nmi_cont#define arch_nmi_exit () \ do { \ - if (is_kernel_in_hyp_mode()) { \ + if (is_kernel_in_hyp_mode() && !in_nmi()) { \ struct nmi_ctx *nmi_ctx = this_cpu_ptr(&nmi_contexts); \ if (!(nmi_ctx->hcr & HCR_TGE)) \ write_sysreg(nmi_ctx->hcr, hcr_el2); \
arch/arm64/kernel/sdei.c +2 -12
@@ -251,22 +251,12 @@ asmlinkage __kprobes notrace unsigned lo __sdei_handler(struct pt_regs *regs, struct sdei_registered_event *arg) { unsigned long ret; -bool do_nmi_exit = false; -/* -* nmi_enter() deals with printk() re-entrance and use of RCU when -* RCU believed this CPU was idle. Because critical events can -* interrupt normal events, we may already be in_nmi(). -*/ -if (!in_nmi ()) { -nmi_enter (); - do_nmi_exit = true; - } +nmi_enter (); ret =_sdei_handler (regs, arg); -if (do_nmi_exit) -nmi_exit (); +nmi_exit ();return ret; }
arch/arm64/kernel/traps.c +2 -6
@@ -906,17 +906,13 @@ bool arm64_is_fatal_ras_serror(struct pt asmlinkage void do_serror(struct pt_regs *regs, unsigned int esr) { -const bool was_in_nmi =in_nmi (); - -if (!was_in_nmi) -nmi_enter (); +nmi_enter ();/* non-RAS errors are not containable */ if (!arm64_is_ras_serror (esr) ||arm64_is_fatal_ras_serror (regs, esr))arm64_serror_panic (regs, esr); -if (!was_in_nmi) -nmi_exit (); +nmi_exit (); } asmlinkage void enter_from_user_mode(void)
arch/powerpc/kernel/traps.c +5 -14
@@ -441,15 +441,9 @@ void hv_nmi_check_nonrecoverable(structvoid system_reset_exception (struct pt_regs *regs) {unsigned long hsrr0, hsrr1; -bool nested =in_nmi ();bool saved_hsrrs = false; -/* -* Avoid crashes in case of nested NMI exceptions. Recoverability -* is determined by RI and in_nmi -*/ -if (!nested) -nmi_enter (); +nmi_enter ();/* * System reset can interrupt code where HSRRs are live and MSR[RI]=1.
@@ -521,8 +515,7 @@ void system_reset_exception(struct pt_remtspr (SPRN_HSRR1 , hsrr1); } -if (!nested) -nmi_exit (); +nmi_exit ();/* What should we do here? We could issue a shutdown or hard reset. */ }
@@ -823,9 +816,8 @@ int machine_check_generic(struct pt_regsvoid machine_check_exception (struct pt_regs *regs) {int recover =0 ; -bool nested =in_nmi (); -if (!nested) -nmi_enter (); + +nmi_enter ();__this_cpu_inc (irq_stat.mce_exceptions);
@@ -863,8 +855,7 @@ void machine_check_exception(struct pt_rreturn ; bail: -if (!nested) -nmi_exit (); +nmi_exit (); }void SMIException (struct pt_regs *regs)
include/linux/hardirq.h +1 -1
@@ -71,7 +71,7 @@ extern void irq_exit(void);printk_nmi_enter (); \lockdep_off (); \ftrace_nmi_enter (); \ -BUG_ON (in_nmi ()); \ +BUG_ON (in_nmi () ==NMI_MASK ); \preempt_count_add (NMI_OFFSET +HARDIRQ_OFFSET ); \rcu_nmi_enter (); \trace_hardirq_enter (); \
include/linux/preempt.h +2 -2
@@ -26,13 +26,13 @@* PREEMPT_MASK: 0x000000ff * SOFTIRQ_MASK: 0x0000ff00 * HARDIRQ_MASK: 0x000f0000 -* NMI_MASK: 0x00100000 +* NMI_MASK: 0x00f00000 * PREEMPT_NEED_RESCHED: 0x80000000 */ #define PREEMPT_BITS 8#define SOFTIRQ_BITS 8#define HARDIRQ_BITS 4 -#define NMI_BITS 1 +#define NMI_BITS 4#define PREEMPT_SHIFT 0#define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS)
kernel/printk/printk_safe.c +4 -2
@@ -296,12 +296,14 @@ static __printf(1, 0) int vprintk_nmi(co void notrace printk_nmi_enter(void) { -this_cpu_or (printk_context,PRINTK_NMI_CONTEXT_MASK ); +if (!in_nmi ()) +this_cpu_or (printk_context,PRINTK_NMI_CONTEXT_MASK ); } void notrace printk_nmi_exit(void) { -this_cpu_and (printk_context, ~PRINTK_NMI_CONTEXT_MASK ); +if (!in_nmi ()) +this_cpu_and (printk_context, ~PRINTK_NMI_CONTEXT_MASK ); }/*
Steven Rostedt
maintainerRe: [PATCH v3 01/22] hardirq/nmi: Allow nested nmi_enter()
Quoted 24 lines · On Wed, 19 Feb 2020 15:47:25 +0100 Peter Zijlstra <[email protected]> wrote:
Since there are already a number of sites (ARM64, PowerPC) that effectively nest
nmi_enter(), lets make the primitive support this before adding even more.void
SMIException(struct pt_regs *regs)include/linux/hardirq.h +1
-1@@ -71,7 +71,7 @@ extern void irq_exit(void);printk_nmi_enter (); \lockdep_off (); \ftrace_nmi_enter (); \ -BUG_ON (in_nmi ()); \ +BUG_ON (in_nmi () ==NMI_MASK ); \preempt_count_add (NMI_OFFSET +HARDIRQ_OFFSET ); \rcu_nmi_enter (); \trace_hardirq_enter (); \include/linux/preempt.h +0
-0@@ -26,13 +26,13 @@* PREEMPT_MASK: 0x000000ff * SOFTIRQ_MASK: 0x0000ff00 * HARDIRQ_MASK: 0x000f0000
include/linux/preempt.h line 36
Quoted 10 lines
include/linux/preempt.h +2
-2-* NMI_MASK: 0x00100000 +* NMI_MASK: 0x00f00000 * PREEMPT_NEED_RESCHED: 0x80000000 */ #define PREEMPT_BITS 8#define SOFTIRQ_BITS 8#define HARDIRQ_BITS 4 -#define NMI_BITS 1 +#define NMI_BITS 4
Probably should document somewhere (in a comment above nmi_enter()?) that we allow nmi_enter() to nest up to 15 times.
-- Steve
Borislav Petkov
maintainerRe: [PATCH v3 01/22] hardirq/nmi: Allow nested nmi_enter()
Quoted 2 lines · Steven Rostedt
Probably should document somewhere (in a comment above
nmi_enter()?) that we allownmi_enter()to nest up to 15 times.
Yah, and can we make the BUG_ON() WARN_ON or so instead, so that there's at least a chance to be able to catch it for debugging. Or is the box going to be irreparably wedged after the 4 bits overflow?
Signature · 4 lines
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquettePeter Zijlstra
maintainerRe: [PATCH v3 01/22] hardirq/nmi: Allow nested nmi_enter()
Quoted 7 lines · Borislav Petkov
Quoted 2 lines · Steven Rostedt
Probably should document somewhere (in a comment above
nmi_enter()?) that we allownmi_enter()to nest up to 15 times.Yah, and can we make the
BUG_ON()WARN_ONor so instead, so that there's at least a chance to be able to catch it for debugging. Or is the box going to be irreparably wedged after the 4 bits overflow?
It's going to be fairly buggered, because at that point in_nmi() is going to be false again. It might survive for a little, it might not.
Re: [PATCH v3 01/22] hardirq/nmi: Allow nested nmi_enter()
In reply to Peter ZijlstraQuoted 9 lines · Peter Zijlstra
Since there are already a number of sites (ARM64, PowerPC) that effectively nest
nmi_enter(), lets make the primitive support this before adding even more.Cc Will Deacon <[email protected]>Cc Marc Zyngier <[email protected]>Cc Michael Ellerman <[email protected]>Cc Petr Mladek <[email protected]>Signed-off-by Peter Zijlstra (Intel) <[email protected]>
Quoted 4 lines
--- arch/arm64/include/asm/hardirq.h | 4 ++-- arch/arm64/kernel/sdei.c | 14 ++------------ arch/arm64/kernel/traps.c | 8 ++------
For these arm64 bits:
Will
Re: [PATCH v3 01/22] hardirq/nmi: Allow nested nmi_enter()
In reply to Peter ZijlstraQuoted 9 lines · Peter Zijlstra
Since there are already a number of sites (ARM64, PowerPC) that effectively nest
nmi_enter(), lets make the primitive support this before adding even more.Cc Will Deacon <[email protected]>Cc Marc Zyngier <[email protected]>Cc Michael Ellerman <[email protected]>Cc Petr Mladek <[email protected]>Signed-off-by Peter Zijlstra (Intel) <[email protected]>
Thanks for cleaning this up!
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
Re: [PATCH v3 01/22] hardirq/nmi: Allow nested nmi_enter()
In reply to Peter ZijlstraQuoted 3 lines · Peter Zijlstra
Since there are already a number of sites (ARM64, PowerPC) that effectively nest
nmi_enter(), lets make the primitive support this before adding even more.
The rest looks good as well.
Best Regards,
Petr
Peter Zijlstra
maintainerPATCH v3 2/22 x86,mce: Delete ist_begin_non_atomic()
In reply to Peter ZijlstraIt is an abomination; and in prepration of removing the whole ist_enter() thing, it needs to go.
Convert #MC over to using task_work_add() instead; it will run the same code slightly later, on the return to user path of the same exception.
--- arch/x86/include/asm/traps.h | 2 - arch/x86/kernel/cpu/mce/core.c | 53 +++++++++++++++++++++++------------------ arch/x86/kernel/traps.c | 37 ---------------------------- include/linux/sched.h | 6 ++++ 4 files changed, 36 insertions(+), 62 deletions(-)
arch/x86/include/asm/traps.h +0 -2
@@ -123,8 +123,6 @@ asmlinkage void smp_irq_move_cleanup_intextern void ist_enter (struct pt_regs *regs);extern void ist_exit (struct pt_regs *regs); -extern void ist_begin_non_atomic (struct pt_regs *regs); -extern void ist_end_non_atomic (void );#ifdef CONFIG_VMAP_STACK void __noreturn handle_stack_overflow(const char *message,
arch/x86/kernel/cpu/mce/core.c +30 -23
78 lines not on this page · raw message
arch/x86/kernel/traps.c +0 -37
@@ -117,43 +117,6 @@ void ist_exit(struct pt_regs *regs)rcu_nmi_exit (); } -/** -* ist_begin_non_atomic() - begin a non-atomic section in an IST exception -* @regs: regs passed to the IST exception handler -* -* IST exception handlers normally cannot schedule. As a special -* exception, if the exception interrupted userspace code (i.e. -* user_mode(regs) would return true) and the exception was not -* a double fault, it can be safe to schedule. ist_begin_non_atomic() -* begins a non-atomic section within an ist_enter()/ist_exit() region. -* Callers are responsible for enabling interrupts themselves inside -* the non-atomic section, and callers must call ist_end_non_atomic() -* before ist_exit(). -*/ -void ist_begin_non_atomic (struct pt_regs *regs) -{ -BUG_ON (!user_mode (regs)); - -/* -* Sanity check: we need to be on the normal thread stack. This -* will catch asm bugs and any attempt to use ist_preempt_enable -* from double_fault. -*/ -BUG_ON (!on_thread_stack ()); - -preempt_enable_no_resched (); -} - -/** -* ist_end_non_atomic() - begin a non-atomic section in an IST exception -* -* Ends a non-atomic section started with ist_begin_non_atomic(). -*/ -void ist_end_non_atomic (void ) -{ -preempt_disable (); -} -int is_valid_bugaddr (unsigned long addr) {unsigned short ud;
include/linux/sched.h +6 -0
@@ -1285,6 +1285,12 @@ struct task_struct {unsigned long prev_lowest_stack;#endif +#ifdef CONFIG_X86_MCE +u64 mce_addr; +u64 mce_status; +struct callback_head mce_kill_me; +#endif +/* * New fields for task_struct should be added above here, so that * they are included in the randomized portion of task_struct.
Borislav Petkov
maintainerRe: [PATCH v3 02/22] x86,mce: Delete ist_begin_non_atomic()
Quoted 1 line · Peter Zijlstra
Subject: Re: [PATCH v3 02/22] x86,mce: Delete
ist_begin_non_atomic()
x86/mce: ...
Quoted 6 lines
It is an abomination; and in prepration of removing the whole
ist_enter()thing, it needs to go.Convert #MC over to using
task_work_add()instead; it will run the same code slightly later, on the return to user path of the same exception.
That's fine because the error happened in userspace.
...
arch/x86/kernel/cpu/mce/core.c static void __mc_scan_banks(struct mce * · line 1194
Quoted 10 lines
arch/x86/kernel/cpu/mce/core.c +6
-0@@ -1202,6 +1186,29 @@ static void __mc_scan_banks(struct mce * *m = *final; } +static void mce_kill_me_now (struct callback_head *ch) +{ +force_sig (SIGBUS ); +} + +static void mce_kill_me_maybe (struct callback_head *cb)
You don't even need the "mce_" prefixes - those are static functions and in mce-land.
Change looks good otherwise.
Signature · 4 lines
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquetteAndy Lutomirski
maintainerRe: [PATCH v3 02/22] x86,mce: Delete ist_begin_non_atomic()
Quoted 6 lines · Borislav Petkov
Quoted 1 line · Peter Zijlstra
Subject: Re: [PATCH v3 02/22] x86,mce: Delete
ist_begin_non_atomic()x86/mce: ...
Quoted 8 lines
Quoted 6 lines
It is an abomination; and in prepration of removing the whole
ist_enter()thing, it needs to go.Convert #MC over to using
task_work_add()instead; it will run the same code slightly later, on the return to user path of the same exception.That's fine because the error happened in userspace.
Unless there is a signal pending and the signal setup code is about to hit the same failed memory. I suppose we can just treat cases like this as "oh well, time to kill the whole system".
But we should genuinely agree that we're okay with deferring this handling.
Peter Zijlstra
maintainerRe: [PATCH v3 02/22] x86,mce: Delete ist_begin_non_atomic()
Quoted 14 lines · Andy Lutomirski
Quoted 13 lines · Borislav Petkov
Quoted 1 line · Peter Zijlstra
Subject: Re: [PATCH v3 02/22] x86,mce: Delete
ist_begin_non_atomic()x86/mce: ...
Quoted 6 lines
It is an abomination; and in prepration of removing the whole
ist_enter()thing, it needs to go.Convert #MC over to using
task_work_add()instead; it will run the same code slightly later, on the return to user path of the same exception.
Quoted 7 lines
Quoted 1 line
That's fine because the error happened in userspace.
Unless there is a signal pending and the signal setup code is about to hit the same failed memory. I suppose we can just treat cases like this as "oh well, time to kill the whole system".
But we should genuinely agree that we're okay with deferring this handling.
It doesn't delay much. The moment it does that local_irq_enable() it's subject to preemption, just like it is on the return to user path.
Do you really want to create code that unwinds enough of nmi_enter() to get you to a preemptible context? *shudder*
Andy Lutomirski
maintainerRe: [PATCH v3 02/22] x86,mce: Delete ist_begin_non_atomic()
Quoted 22 lines · Peter Zijlstra
Quoted 20 lines · Andy Lutomirski
Quoted 6 lines · Borislav Petkov
Quoted 1 line · Peter Zijlstra
Subject: Re: [PATCH v3 02/22] x86,mce: Delete
ist_begin_non_atomic()x86/mce: ...
Quoted 8 lines
Quoted 6 lines
It is an abomination; and in prepration of removing the whole
ist_enter()thing, it needs to go.Convert #MC over to using
task_work_add()instead; it will run the same code slightly later, on the return to user path of the same exception.That's fine because the error happened in userspace.
Unless there is a signal pending and the signal setup code is about to hit the same failed memory. I suppose we can just treat cases like this as "oh well, time to kill the whole system".
Quoted 7 lines
Quoted 1 line
But we should genuinely agree that we're okay with deferring this handling.
It doesn't delay much. The moment it does that
local_irq_enable()it's subject to preemption, just like it is on the return to user path.Do you really want to create code that unwinds enough of
nmi_enter()to get you to a preemptible context? *shudder*
Well, there's another way to approach this:
void notrace nonothing do_machine_check(struct pt_regs *regs) {
if (user_mode(regs))
do_sane_machine_check(regs);
else
do_awful_machine_check(regs);
}void do_sane_machine_check(regs)
{
nothing special here. just a regular exception, more or less.
}
void do_awful_macine_check(regs)
{
basically an NMI. No funny business, no recovery possible.task_work_add() not allowed.
}
Or, even better, depending on how tglx's series shakes out, we could build on this patch:
and actually have two separate do_machine_check entry points. So we'd do, roughly:
idtentry_ist ... normal_stack_entry=do_sane_machine_check ist_stack_entry=do_awful_machine_check
and now there's no chance for confusion.
All of the above has some issues when Tony decides that he wants to recover from specially annotated recoverable kernel memory accesses. Then task_word_add() is a nonstarter, but the current stack-switch-from-usermode *also* doesn't work. I floated the idea of also doing the stack switch if we come from an IF=1 context, but that's starting to get nasty.
One big question here: are memory failure #MC exceptions synchronous
or can they be delayed? If we get a memory failure, is it possible
that the #MC hits some random context and not the actual context where the error occurred?
I suppose the general consideration I'm trying to get at is: is task_work_add() actually useful at all here? For the case when a kernel thread does memcpy_mcsafe() or similar, task work registered using task_work_add() will never run.
--Andy
Luck, Tony
maintainerRE: [PATCH v3 02/22] x86,mce: Delete ist_begin_non_atomic()
Quoted 4 lines
One big question here: are memory failure #MC exceptions synchronous
or can they be delayed? If we get a memory failure, is it possible
that the #MC hits some random context and not the actual context where the error occurred?
There are a few cases:
1) SRAO (Software recoverable action optional) [Patrol scrub or L3 cache eviction] These aren't synchronous with any core execution. Using machine check to signal was probably a mistake - compounded by it being broadcast :-( Could pick any CPU to handle (actually choose the first to arrive in do_machine_check()). That guy should arrange to soft offline the affected page. Every CPU can return to what they were doing before.
2) SRAR (Software recoverable action required)
These are synchronous. Starting with Skylake they may be signaled just to the thread
that hit the poison. Earlier generations broadcast.
2a) Hit in ring3 code ... we want to offline the page and SIGBUS the task(s)
2b) Memcpy_mcsafe() ... kernel has a recovery path. "Return" to the recovery code instead of to the original RIP. 2c) copy_from_user ... not implemented yet. We are in kernel, but would like to treat this like case 2a
3) Fatal
Always broadcast. Some bank has MCi_STATUS.PCC==1. System must be shutdown.
-Tony
Re: [PATCH v3 02/22] x86,mce: Delete ist_begin_non_atomic()
Quoted 10 lines · Tony
Quoted 5 lines
One big question here: are memory failure #MC exceptions synchronous
or can they be delayed? If we get a memory failure, is it possible
that the #MC hits some random context and not the actual context where the error occurred?
Quoted 7 lines
There are a few cases:
1) SRAO (Software recoverable action optional) [Patrol scrub or L3 cache eviction] These aren't synchronous with any core execution. Using machine check to signal was probably a mistake - compounded by it being broadcast :-( Could pick any CPU to handle (actually choose the first to arrive indo_machine_check()). That guy should arrange to soft offline the affected page. Every CPU can return to what they were doing before.
You could handle this by sending IPI-to-self and dealing with it in the interrupt handler. Or even wake a high-priority kthread or workqueue. irq_work may help. Relying on task_work or the non_atomic stuff seems silly - you can’t rely on anything about the interrupted context, and the context is more or less irrelevant anyway.
Quoted 4 lines
2) SRAR (Software recoverable action required)
These are synchronous. Starting with Skylake they may be signaled just to the thread that hit the poison. Earlier generations broadcast.
Here’s where dealing with one that came from kernel code is just nasty, right?
I would argue that, if IF=0, killing the machine is reasonable. If IF=1, we should be okay. Actually making this work sanely is gross, and arguably the goal should be minimizing grossness.
Perhaps, if we came from kernel mode, we should IPI-to-self and use a special vector that is idtentry, not apicinterrupt. Or maybe even do this for entries from usermode just to keep everything consistent.
Quoted 6 lines
2a) Hit in ring3 code ... we want to offline the page and SIGBUS the task(s)
2b)Memcpy_mcsafe()... kernel has a recovery path. "Return" to the recovery code instead of to the original RIP. 2c)copy_from_user... not implemented yet. We are in kernel, but would like to treat this like case 2a3) Fatal
Always broadcast. Some bank has MCi_STATUS.PCC==1. System must be shutdown.
Easy :)
It would be really, really nice if NMI was masked in MCE context.
Quoted 2 lines
-Tony
Peter Zijlstra
maintainerRe: [PATCH v3 02/22] x86,mce: Delete ist_begin_non_atomic()
In reply to Andy LutomirskiQuoted 20 lines · Andy Lutomirski
Quoted 2 lines · Peter Zijlstra
Do you really want to create code that unwinds enough of
nmi_enter()to get you to a preemptible context? *shudder*Well, there's another way to approach this:
void notrace nonothing
do_machine_check(struct pt_regs *regs){
if (user_mode(regs))do_sane_machine_check(regs); else do_awful_machine_check(regs); }void
do_sane_machine_check(regs)
{
nothing special here. just a regular exception, more or less.
}
Quoted 5 lines
void
do_awful_macine_check(regs)
{
basically an NMI. No funny business, no recovery possible.task_work_add()not allowed.
}
Right, that looks like major surgery to the current code though; I'd much prefer someone that knows that code do that.
Quoted 4 lines
I suppose the general consideration I'm trying to get at is: is
task_work_add()actually useful at all here? For the case when a kernel thread doesmemcpy_mcsafe()or similar, task work registered usingtask_work_add()will never run.
task_work isn't at all useful when we didn't come from userspace. In that case irq_work is the best option, but that doesn't provide a preemptible context.
Borislav Petkov
maintainerRe: [PATCH v3 02/22] x86,mce: Delete ist_begin_non_atomic()
In reply to Andy LutomirskiQuoted 5 lines · Andy Lutomirski
Unless there is a signal pending and the signal setup code is about to hit the same failed memory. I suppose we can just treat cases like this as "oh well, time to kill the whole system".
But we should genuinely agree that we're okay with deferring this handling.
Good catch!
static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags) {
...
/* deal with pending signal delivery */
if (cached_flags & _TIF_SIGPENDING)
do_signal(regs);
if (cached_flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(regs);
rseq_handle_notify_resume(NULL, regs);
}Err, can we make task_work run before we handle signals? Or there's a reason it is run in this order?
Comment over task_work_add() says:
* This is like the signal handler which runs in kernel mode, but it doesn't
* try to wake up the @task.
which sounds to me like this should really run before the signal handlers...
Signature · 4 lines
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquettePeter Zijlstra
maintainerRe: [PATCH v3 02/22] x86,mce: Delete ist_begin_non_atomic()
Quoted 28 lines · Borislav Petkov
Quoted 5 lines · Andy Lutomirski
Unless there is a signal pending and the signal setup code is about to hit the same failed memory. I suppose we can just treat cases like this as "oh well, time to kill the whole system".
But we should genuinely agree that we're okay with deferring this handling.
Good catch!
static void
exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags){... /* deal with pending signal delivery */ if (cached_flags & _TIF_SIGPENDING) do_signal(regs); if (cached_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); rseq_handle_notify_resume(NULL, regs); }Err, can we make
task_workrun before we handle signals? Or there's a reason it is run in this order?
Quoted 7 lines
Comment over
task_work_add()says:* This is like the signal handler which runs in kernel mode, but it doesn't
* try to wake up the @task.which sounds to me like this should really run before the signal handlers...
here goes...
arch/x86/entry/common.c +4 -4
@@ -155,16 +155,16 @@ static void exit_to_usermode_loop(structif (cached_flags & _TIF_PATCH_PENDING)klp_update_patch_state (current); -/* deal with pending signal delivery */ -if (cached_flags & _TIF_SIGPENDING) -do_signal (regs); -if (cached_flags & _TIF_NOTIFY_RESUME) {clear_thread_flag (TIF_NOTIFY_RESUME );tracehook_notify_resume (regs);rseq_handle_notify_resume (NULL , regs); } +/* deal with pending signal delivery */ +if (cached_flags & _TIF_SIGPENDING) +do_signal (regs); +if (cached_flags & _TIF_USER_RETURN_NOTIFY)fire_user_return_notifiers ();
Peter Zijlstra
maintainerPATCH v3 3/22 x86: Replace ist_enter() with nmi_enter()
In reply to Peter ZijlstraA few exceptions (like #DB and #BP) can happen at any location in the code, this then means that tracers should treat events from these exceptions as NMI-like. We could be holding locks with interrupts disabled for instance.
Similarly, #MC is an actual NMI-like exception.
All of them use ist_enter() which only concerns itself with RCU, but does not do any of the other setup that NMI's need. This means things like:
printk() raw_spin_lock(&logbuf_lock); <#DB/#BP/#MC> printk() raw_spin_lock(&logbuf_lock);
are entirely possible.
So replace ist_enter() with nmi_enter(). Also observe that any nmi_enter() caller must be both notrace and NOKPROBE.
--- arch/x86/include/asm/traps.h | 3 -- arch/x86/kernel/cpu/mce/core.c | 15 +++++----- arch/x86/kernel/cpu/mce/p5.c | 7 ++-- arch/x86/kernel/cpu/mce/winchip.c | 7 ++-- arch/x86/kernel/traps.c | 57 +++++--------------------------------- 5 files changed, 24 insertions(+), 65 deletions(-)
arch/x86/include/asm/traps.h +0 -3
@@ -121,9 +121,6 @@ void smp_spurious_interrupt(struct pt_revoid smp_error_interrupt (struct pt_regs *regs); asmlinkage void smp_irq_move_cleanup_interrupt(void); -extern void ist_enter (struct pt_regs *regs); -extern void ist_exit (struct pt_regs *regs); -#ifdef CONFIG_VMAP_STACK void __noreturn handle_stack_overflow(const char *message, struct pt_regs *regs,
arch/x86/kernel/cpu/mce/core.c +8 -7
@@ -1220,7 +1220,7 @@ static void mce_kill_me_maybe(struct cal* MCE broadcast. However some CPUs might be broken beyond repair, * so be always careful when synchronizing with others. */ -void do_machine_check (struct pt_regs *regs,long error_code) +notrace void do_machine_check(struct pt_regs *regs, long error_code) {DECLARE_BITMAP (valid_banks,MAX_NR_BANKS );DECLARE_BITMAP (toclear,MAX_NR_BANKS );
@@ -1254,10 +1254,10 @@ void do_machine_check(struct pt_regs *re*/ int lmce =1 ; -if (__mc_check_crashing_cpu (cpu)) -return ; +nmi_enter (); -ist_enter (regs); +if (__mc_check_crashing_cpu (cpu)) + goto out;this_cpu_inc (mce_exception_count);
@@ -1346,7 +1346,7 @@ void do_machine_check(struct pt_regs *resync_core ();if (worst !=MCE_AR_SEVERITY && !kill_it) - goto out_ist; + goto out;/* Fault was in user mode and we need to take some action */ if ((m.cs &3 ) ==3 ) {
@@ -1362,10 +1362,11 @@ void do_machine_check(struct pt_regs *remce_panic ("Failed kernel mode recovery" , &m, msg); } -out_ist: -ist_exit (regs); +out: +nmi_exit (); }EXPORT_SYMBOL_GPL (do_machine_check); +NOKPROBE_SYMBOL (do_machine_check);#ifndef CONFIG_MEMORY_FAILURE int memory_failure (unsigned long pfn,int flags)
arch/x86/kernel/cpu/mce/p5.c +4 -3
@@ -20,11 +20,11 @@int mce_p5_enabled__read_mostly ;/* Machine check handler for Pentium class Intel CPUs: */ -static void pentium_machine_check (struct pt_regs *regs,long error_code) +static notrace void pentium_machine_check(struct pt_regs *regs, long error_code) {u32 loaddr, hi, lotype; -ist_enter (regs); +nmi_enter ();rdmsr (MSR_IA32_P5_MC_ADDR , loaddr, hi);rdmsr (MSR_IA32_P5_MC_TYPE , lotype, hi);
@@ -39,8 +39,9 @@ static void pentium_machine_check(structadd_taint (TAINT_MACHINE_CHECK ,LOCKDEP_NOW_UNRELIABLE ); -ist_exit (regs); +nmi_exit (); } +NOKPROBE_SYMBOL (pentium_machine_check);/* Set up machine check reporting for processors with Intel style MCE: */ void intel_p5_mcheck_init (struct cpuinfo_x86 *c)
arch/x86/kernel/cpu/mce/winchip.c +4 -3
@@ -16,15 +16,16 @@#include "internal.h" /* Machine check handler for WinChip C6: */ -static void winchip_machine_check (struct pt_regs *regs,long error_code) +static notrace void winchip_machine_check(struct pt_regs *regs, long error_code) { -ist_enter (regs); +nmi_enter ();pr_emerg ("CPU0: Machine Check Exception.\n" );add_taint (TAINT_MACHINE_CHECK ,LOCKDEP_NOW_UNRELIABLE ); -ist_exit (regs); +nmi_exit (); } +NOKPROBE_SYMBOL (winchip_machine_check);/* Set up machine check reporting on the Winchip C6 series */ void winchip_mcheck_init (struct cpuinfo_x86 *c)
arch/x86/kernel/traps.c +8 -49
111 lines not on this page · raw message
Borislav Petkov
maintainerRe: [PATCH v3 03/22] x86: Replace ist_enter() with nmi_enter()
arch/x86/kernel/cpu/mce/core.c static void mce_kill_me_maybe(struct cal · line 1223
Quoted 6 lines · Peter Zijlstra
arch/x86/kernel/cpu/mce/core.c +1
-1@@ -1220,7 +1220,7 @@ static void mce_kill_me_maybe(struct cal* MCE broadcast. However some CPUs might be broken beyond repair, * so be always careful when synchronizing with others. */ -void do_machine_check (struct pt_regs *regs,long error_code) +notrace void do_machine_check(struct pt_regs *regs, long error_code)
Is there a convention where the notrace marker should come in the function signature? I see all possible combinations while grepping...
Quoted 7 lines
arch/x86/kernel/cpu/mce/core.c +0
-0{DECLARE_BITMAP (valid_banks,MAX_NR_BANKS );DECLARE_BITMAP (toclear,MAX_NR_BANKS );@@ -1254,10 +1254,10 @@ void do_machine_check(struct pt_regs *re*/ int lmce =1 ;
arch/x86/kernel/cpu/mce/core.c void do_machine_check(struct pt_regs *re · line 1263
Quoted 10 lines
arch/x86/kernel/cpu/mce/core.c +3
-3-if (__mc_check_crashing_cpu (cpu)) -return ; +nmi_enter (); -ist_enter (regs); +if (__mc_check_crashing_cpu (cpu)) + goto out;this_cpu_inc (mce_exception_count);
Should that __mc_check_crashing_cpu() happen before nmi_enter? The function is doing only a bunch of checks and clearing MSRs for bystander CPUs...
Quoted 10 lines
arch/x86/kernel/cpu/mce/core.c +1
-1@@ -1346,7 +1346,7 @@ void do_machine_check(struct pt_regs *resync_core ();if (worst !=MCE_AR_SEVERITY && !kill_it) - goto out_ist; + goto out;/* Fault was in user mode and we need to take some action */ if ((m.cs &3 ) ==3 ) {
arch/x86/kernel/cpu/mce/core.c void do_machine_check(struct pt_regs *re · line 1369
Quoted 10 lines
arch/x86/kernel/cpu/mce/core.c +3
-2@@ -1362,10 +1362,11 @@ void do_machine_check(struct pt_regs *remce_panic ("Failed kernel mode recovery" , &m, msg); } -out_ist: -ist_exit (regs); +out: +nmi_exit (); }EXPORT_SYMBOL_GPL (do_machine_check); +NOKPROBE_SYMBOL (do_machine_check);
Yah, that's a good idea regardless.
Thx.
Signature · 4 lines
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquettePeter Zijlstra
maintainerRe: [PATCH v3 03/22] x86: Replace ist_enter() with nmi_enter()
Quoted 10 lines · Borislav Petkov
arch/x86/kernel/cpu/mce/core.c static void mce_kill_me_maybe(struct cal · line 1223
Quoted 6 lines · Peter Zijlstra
arch/x86/kernel/cpu/mce/core.c +1
-1@@ -1220,7 +1220,7 @@ static void mce_kill_me_maybe(struct cal* MCE broadcast. However some CPUs might be broken beyond repair, * so be always careful when synchronizing with others. */ -void do_machine_check (struct pt_regs *regs,long error_code) +notrace void do_machine_check(struct pt_regs *regs, long error_code)Is there a convention where the notrace marker should come in the function signature? I see all possible combinations while grepping...
Same place as inline I think.
Quoted 15 lines
Quoted 15 lines
arch/x86/kernel/cpu/mce/core.c +3
-3{DECLARE_BITMAP (valid_banks,MAX_NR_BANKS );DECLARE_BITMAP (toclear,MAX_NR_BANKS );@@ -1254,10 +1254,10 @@ void do_machine_check(struct pt_regs *re*/ int lmce =1 ; -if (__mc_check_crashing_cpu (cpu)) -return ; +nmi_enter (); -ist_enter (regs); +if (__mc_check_crashing_cpu (cpu)) + goto out;
Quoted 6 lines
arch/x86/kernel/cpu/mce/core.c void do_machine_check(struct pt_regs *re · line 1263
Quoted 2 lines
arch/x86/kernel/cpu/mce/core.c +0
-0this_cpu_inc (mce_exception_count);Should that
__mc_check_crashing_cpu()happen beforenmi_enter? The function is doing only a bunch of checks and clearing MSRs for bystander CPUs...
You'll note the lack of notrace on that function, and we must not call into tracers before nmi_enter().
AFAICT there really is no benefit to trying to lift it before nmi_enter().
Peter Zijlstra
maintainerPATCH v3 4/22 x86/doublefault: Make memmove() notrace/NOKPROBE
In reply to Peter ZijlstraHitting the tracer or a kprobes from #DF is 'interesting', lets avoid that.
--- arch/x86/kernel/traps.c | 3 ++- arch/x86/lib/memcpy_32.c | 7 ++++++- arch/x86/lib/memmove_64.S | 5 +++++ 3 files changed, 13 insertions(+), 2 deletions(-)
arch/x86/kernel/traps.c +2 -1
@@ -271,7 +271,8 @@ dotraplinkage void do_double_fault(struc* The net result is that our #GP handler will think that we * entered from usermode with the bad user context. * -* No need for nmi_enter() here because we don't use RCU. +* No need for nmi_enter() here because we don't call out to anything +* except memmove() and that is notrace/NOKPROBE. */ if (((long)regs->sp >> P4D_SHIFT) == ESPFIX_PGD_ENTRY && regs->cs == __KERNEL_CS &&
arch/x86/lib/memcpy_32.c +6 -1
@@ -21,7 +21,7 @@ __visible void *memset(void *s, int c, s }EXPORT_SYMBOL (memset); -__visible void *memmove(void *dest, const void *src, size_t n) +__visible notrace void *memmove(void *dest, const void *src, size_t n) {int d0,d1,d2,d3,d4,d5;char *ret = dest;
@@ -207,3 +207,8 @@ __visible void *memmove(void *dest, cons }EXPORT_SYMBOL (memmove); +/* +* The double fault handler uses memmove(), do not mess with it or risk a +* tripple fault. +*/ +NOKPROBE_SYMBOL (memmove);
arch/x86/lib/memmove_64.S +5 -0
@@ -212,3 +212,8 @@ SYM_FUNC_END(__memmove) SYM_FUNC_END_ALIAS(memmove) EXPORT_SYMBOL(__memmove) EXPORT_SYMBOL(memmove) +/* + * The double fault handler uses memmove(), do not mess with it or risk a + * tripple fault. + */ +_ASM_NOKPROBE(__memmove)
Steven Rostedt
maintainerRe: [PATCH v3 04/22] x86/doublefault: Make memmove() notrace/NOKPROBE
Quoted 12 lines · On Wed, 19 Feb 2020 15:47:28 +0100 Peter Zijlstra <[email protected]> wrote:
arch/x86/lib/memcpy_32.c +1
-1@@ -21,7 +21,7 @@ __visible void *memset(void *s, int c, s }EXPORT_SYMBOL (memset); -__visible void *memmove(void *dest, const void *src, size_t n) +__visible notrace void *memmove(void *dest, const void *src, size_t n) {int d0,d1,d2,d3,d4,d5;char *ret = dest;
arch/x86/lib/memcpy_32.c __visible void *memmove(void *dest, cons · line 209
Quoted 3 lines
arch/x86/lib/memcpy_32.c +0
-0@@ -207,3 +207,8 @@ __visible void *memmove(void *dest, cons }EXPORT_SYMBOL (memmove);
Hmm, for things like this, which is adding notrace because of a single instance of it (although it is fine to trace in any other instance), it would be nice to have a gcc helper that could call "memmove+5" which would skip the tracing portion.
-- Steve
Peter Zijlstra
maintainerRe: [PATCH v3 04/22] x86/doublefault: Make memmove() notrace/NOKPROBE
Quoted 16 lines · Steven Rostedt
Quoted 13 lines · On Wed, 19 Feb 2020 15:47:28 +0100 Peter Zijlstra <[email protected]> wrote:
arch/x86/lib/memcpy_32.c +1
-1@@ -21,7 +21,7 @@ __visible void *memset(void *s, int c, s }EXPORT_SYMBOL (memset); -__visible void *memmove(void *dest, const void *src, size_t n) +__visible notrace void *memmove(void *dest, const void *src, size_t n) {int d0,d1,d2,d3,d4,d5;char *ret = dest;@@ -207,3 +207,8 @@ __visible void *memmove(void *dest, cons
Quoted 7 lines
arch/x86/lib/memcpy_32.c __visible void *memmove(void *dest, cons · line 209
Quoted 2 lines
arch/x86/lib/memcpy_32.c +0
-0}EXPORT_SYMBOL (memmove);Hmm, for things like this, which is adding notrace because of a single instance of it (although it is fine to trace in any other instance), it would be nice to have a gcc helper that could call "memmove+5" which would skip the tracing portion.
Or just open-code the memmove() in do_double_fault() I suppose. I don't think we care about super optimized code there. It's the bloody ESPFIX trainwreck.
Steven Rostedt
maintainerRe: [PATCH v3 04/22] x86/doublefault: Make memmove() notrace/NOKPROBE
Quoted 8 lines · On Wed, 19 Feb 2020 16:40:31 +0100 Peter Zijlstra <[email protected]> wrote:
Quoted 4 lines
Hmm, for things like this, which is adding notrace because of a single instance of it (although it is fine to trace in any other instance), it would be nice to have a gcc helper that could call "memmove+5" which would skip the tracing portion.
Or just open-code the
memmove()indo_double_fault()I suppose. I don't think we care about super optimized code there. It's the bloody ESPFIX trainwreck.
Or just create a memmove_notrace() version and use that.
-- Steve
Peter Zijlstra
maintainerRe: [PATCH v3 04/22] x86/doublefault: Make memmove() notrace/NOKPROBE
In reply to Peter ZijlstraQuoted 25 lines · Peter Zijlstra
Quoted 16 lines · Steven Rostedt
Quoted 13 lines · On Wed, 19 Feb 2020 15:47:28 +0100 Peter Zijlstra <[email protected]> wrote:
arch/x86/lib/memcpy_32.c +1
-1@@ -21,7 +21,7 @@ __visible void *memset(void *s, int c, s }EXPORT_SYMBOL (memset); -__visible void *memmove(void *dest, const void *src, size_t n) +__visible notrace void *memmove(void *dest, const void *src, size_t n) {int d0,d1,d2,d3,d4,d5;char *ret = dest;@@ -207,3 +207,8 @@ __visible void *memmove(void *dest, consQuoted 7 lines
arch/x86/lib/memcpy_32.c __visible void *memmove(void *dest, cons · line 209
Quoted 2 lines
arch/x86/lib/memcpy_32.c +0
-0}EXPORT_SYMBOL (memmove);Hmm, for things like this, which is adding notrace because of a single instance of it (although it is fine to trace in any other instance), it would be nice to have a gcc helper that could call "memmove+5" which would skip the tracing portion.
Quoted 3 lines
Or just open-code the
memmove()indo_double_fault()I suppose. I don't think we care about super optimized code there. It's the bloody ESPFIX trainwreck.
Something like so, I suppose...
arch/x86/kernel/traps.c +8 -2
@@ -350,14 +350,20 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsign regs->ip == (unsigned long)native_irq_return_iret) {struct pt_regs *gpregs = (struct pt_regs *)this_cpu_read (cpu_tss_rw.x86_tss.sp0) -1 ; +unsigned long *dst = &gpregs->ip; +unsigned long *src = (void *)regs->dp; +int i, count =5 ;/* * regs->sp points to the failing IRET frame on the * ESPFIX64 stack. Copy it to the entry stack. This fills * in gpregs->ss through gpregs->ip. -* */ -memmove (&gpregs->ip, (void *)regs->sp,5 *8 ); +for (i =0 ; i < count; i++) { +int idx = (dst <= src) ? i : count - i; + dst[idx] = src[idx]; + } + gpregs->orig_ax =0 ;/* Missing (lost) #GP error code */ /*
Peter Zijlstra
maintainerRe: [PATCH v3 04/22] x86/doublefault: Make memmove() notrace/NOKPROBE
Quoted 13 lines · Peter Zijlstra
Something like so, I suppose...
arch/x86/kernel/traps.c +3
-0@@ -350,14 +350,20 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsign regs->ip == (unsigned long)native_irq_return_iret) {struct pt_regs *gpregs = (struct pt_regs *)this_cpu_read (cpu_tss_rw.x86_tss.sp0) -1 ; +unsigned long *dst = &gpregs->ip; +unsigned long *src = (void *)regs->dp; +int i, count =5 ;
arch/x86/kernel/traps.c dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsign · line 363
Quoted 10 lines
arch/x86/kernel/traps.c +2
-2/* * regs->sp points to the failing IRET frame on the * ESPFIX64 stack. Copy it to the entry stack. This fills * in gpregs->ss through gpregs->ip. -* */ -memmove (&gpregs->ip, (void *)regs->sp,5 *8 ); +for (i =0 ; i < count; i++) { +int idx = (dst <= src) ? i : count - i;
That's an off-by-one for going backward; 'count - 1 - i' should work better, or I should just stop typing for today ;-)
Quoted 6 lines
arch/x86/kernel/traps.c +3
-0+ dst[idx] = src[idx]; + } + gpregs->orig_ax =0 ;/* Missing (lost) #GP error code */ /*
Steven Rostedt
maintainerRe: [PATCH v3 04/22] x86/doublefault: Make memmove() notrace/NOKPROBE
Quoted 6 lines · On Wed, 19 Feb 2020 17:04:42 +0100 Peter Zijlstra <[email protected]> wrote:
arch/x86/kernel/traps.c dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsign · line 363
Quoted 3 lines
arch/x86/kernel/traps.c +2
-1-memmove (&gpregs->ip, (void *)regs->sp,5 *8 ); +for (i =0 ; i < count; i++) { +int idx = (dst <= src) ? i : count - i;That's an off-by-one for going backward; 'count - 1 - i' should work better, or I should just stop typing for today ;-)
Or, we could just cut and paste the current memmove and make a notrace version too. Then we don't need to worry bout bugs like this.
-- Steve
Paul E. McKenney
maintainerRe: [PATCH v3 04/22] x86/doublefault: Make memmove() notrace/NOKPROBE
Quoted 10 lines · Steven Rostedt
Quoted 6 lines · On Wed, 19 Feb 2020 17:04:42 +0100 Peter Zijlstra <[email protected]> wrote:
arch/x86/kernel/traps.c dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsign · line 363
Quoted 3 lines
arch/x86/kernel/traps.c +2
-1-memmove (&gpregs->ip, (void *)regs->sp,5 *8 ); +for (i =0 ; i < count; i++) { +int idx = (dst <= src) ? i : count - i;That's an off-by-one for going backward; 'count - 1 - i' should work better, or I should just stop typing for today ;-)
Quoted 2 lines
Or, we could just cut and paste the current memmove and make a notrace version too. Then we don't need to worry bout bugs like this.
OK, I will bite...
Can we just make the core be an inline function and make a notrace and a trace caller? Possibly going one step further and having one call the other? (Presumably the traceable version invoking the notrace version, but it has been one good long time since I have looked at function preambles.)
Thanx, Paul
Peter Zijlstra
maintainerRe: [PATCH v3 04/22] x86/doublefault: Make memmove() notrace/NOKPROBE
Quoted 14 lines · Paul E. McKenney
Quoted 10 lines · Steven Rostedt
Quoted 6 lines · On Wed, 19 Feb 2020 17:04:42 +0100 Peter Zijlstra <[email protected]> wrote:
arch/x86/kernel/traps.c dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsign · line 363
Quoted 3 lines
arch/x86/kernel/traps.c +2
-1-memmove (&gpregs->ip, (void *)regs->sp,5 *8 ); +for (i =0 ; i < count; i++) { +int idx = (dst <= src) ? i : count - i;That's an off-by-one for going backward; 'count - 1 - i' should work better, or I should just stop typing for today ;-)
Quoted 2 lines
Or, we could just cut and paste the current memmove and make a notrace version too. Then we don't need to worry bout bugs like this.
Quoted 7 lines
OK, I will bite...
Can we just make the core be an inline function and make a notrace and a trace caller? Possibly going one step further and having one call the other? (Presumably the traceable version invoking the notrace version, but it has been one good long time since I have looked at function preambles.)
One complication is that GCC (and others) are prone to stick their own implementation of memmove() (and other string functions) in at 'random'. That is, it is up to the compiler's discretion wether or not to put a call to memmove() in or just emit some random giberish they feel has the same effect.
So if we go play silly games like that, we need be careful (or just call __memmove I suppose, which is supposed to avoid that IIRC).
Paul E. McKenney
maintainerRe: [PATCH v3 04/22] x86/doublefault: Make memmove() notrace/NOKPROBE
Quoted 23 lines · Peter Zijlstra
Quoted 14 lines · Paul E. McKenney
Quoted 10 lines · Steven Rostedt
Quoted 6 lines · On Wed, 19 Feb 2020 17:04:42 +0100 Peter Zijlstra <[email protected]> wrote:
arch/x86/kernel/traps.c dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsign · line 363
Quoted 3 lines
arch/x86/kernel/traps.c +2
-1-memmove (&gpregs->ip, (void *)regs->sp,5 *8 ); +for (i =0 ; i < count; i++) { +int idx = (dst <= src) ? i : count - i;That's an off-by-one for going backward; 'count - 1 - i' should work better, or I should just stop typing for today ;-)
Quoted 2 lines
Or, we could just cut and paste the current memmove and make a notrace version too. Then we don't need to worry bout bugs like this.
Quoted 7 lines
OK, I will bite...
Can we just make the core be an inline function and make a notrace and a trace caller? Possibly going one step further and having one call the other? (Presumably the traceable version invoking the notrace version, but it has been one good long time since I have looked at function preambles.)
Quoted 8 lines
One complication is that GCC (and others) are prone to stick their own implementation of
memmove()(and other string functions) in at 'random'. That is, it is up to the compiler's discretion wether or not to put a call tomemmove()in or just emit some random giberish they feel has the same effect.So if we go play silly games like that, we need be careful (or just call
__memmoveI suppose, which is supposed to avoid that IIRC).
Urgh, good point. :-/
Thanx, Paul
Steven Rostedt
maintainerRe: [PATCH v3 04/22] x86/doublefault: Make memmove() notrace/NOKPROBE
In reply to Paul E. McKenneyQuoted 10 lines · On Wed, 19 Feb 2020 08:27:47 -0800 "Paul E. McKenney" <[email protected]>…
Quoted 2 lines
Or, we could just cut and paste the current memmove and make a notrace version too. Then we don't need to worry bout bugs like this.
OK, I will bite...
Can we just make the core be an inline function and make a notrace and a trace caller? Possibly going one step further and having one call the other? (Presumably the traceable version invoking the notrace version, but it has been one good long time since I have looked at function preambles.)
Sure. Looking at the implementation (which is big and ugly), we could have a
static always_inline void __memmove(...)
{
[..]
}__visible void *memmove(...)
{
return __memmove(...);
}__visible notrace void *memmove_notrace(...)
{
return __memmove(...);
}-- Steve
Borislav Petkov
maintainerRe: [PATCH v3 04/22] x86/doublefault: Make memmove() notrace/NOKPROBE
In reply to Peter ZijlstraReview
Quoted 5 lines · Peter Zijlstra
(quoted diff) +4
-1- memmove(&gpregs->ip, (void *)regs->sp, 5*8); + for (i = 0; i < count; i++) { + int idx = (dst <= src) ? i : count - i; + dst[idx] = src[idx]; + }
Or, you can actually unroll it. This way it even documents clearly what it does:
arch/x86/kernel/traps.c +6 -1
@@ -298,6 +298,7 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsign regs->ip == (unsigned long)native_irq_return_iret) {struct pt_regs *gpregs = (struct pt_regs *)this_cpu_read (cpu_tss_rw.x86_tss.sp0) -1 ; +unsigned long *p = (unsigned long *)regs->sp;/* * regs->sp points to the failing IRET frame on the
@@ -305,7 +306,11 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsign* in gpregs->ss through gpregs->ip. * */ -memmove (&gpregs->ip, (void *)regs->sp,5 *8 ); + gpregs->ip = *p; + gpregs->cs = *(p +1 ); + gpregs->flags = *(p +2 ); + gpregs->sp = *(p +3 ); + gpregs->ss = *(p +4 ); gpregs->orig_ax =0 ;/* Missing (lost) #GP error code */ /*
Signature · 4 lines
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquettePeter Zijlstra
maintainerRe: [PATCH v3 04/22] x86/doublefault: Make memmove() notrace/NOKPROBE
Quoted 25 lines · Borislav Petkov
Review
Quoted 5 lines · Peter Zijlstra
(quoted diff) +4
-1- memmove(&gpregs->ip, (void *)regs->sp, 5*8); + for (i = 0; i < count; i++) { + int idx = (dst <= src) ? i : count - i; + dst[idx] = src[idx]; + }Or, you can actually unroll it. This way it even documents clearly what it does:
arch/x86/kernel/traps.c +1
-0@@ -298,6 +298,7 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsign regs->ip == (unsigned long)native_irq_return_iret) {struct pt_regs *gpregs = (struct pt_regs *)this_cpu_read (cpu_tss_rw.x86_tss.sp0) -1 ; +unsigned long *p = (unsigned long *)regs->sp;/* * regs->sp points to the failing IRET frame on the @@ -305,7 +306,11 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsign* in gpregs->ss through gpregs->ip. *
arch/x86/kernel/traps.c dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsign · line 316
Quoted 10 lines
arch/x86/kernel/traps.c +5
-1*/ -memmove (&gpregs->ip, (void *)regs->sp,5 *8 ); + gpregs->ip = *p; + gpregs->cs = *(p +1 ); + gpregs->flags = *(p +2 ); + gpregs->sp = *(p +3 ); + gpregs->ss = *(p +4 ); gpregs->orig_ax =0 ;/* Missing (lost) #GP error code */ /*
While I love that; is that actually correct? This is an unroll of memcpy() not memmove(). IFF the ranges overlap, the above is buggered.
Was the original memmove() really needed?
Re: [PATCH v3 04/22] x86/doublefault: Make memmove() notrace/NOKPROBE
In reply to Peter ZijlstraQuoted 5 lines · On Wed, 19 Feb 2020 15:47:28 +0100 Peter Zijlstra <[email protected]> wrote:
Hitting the tracer or a kprobes from #DF is 'interesting', lets avoid that.
Signed-off-by Peter Zijlstra (Intel) <[email protected]>---
-- Steve
Peter Zijlstra
maintainerPATCH v3 5/22 rcu: Make RCU IRQ enter/exit functions rely on in_nmi()
In reply to Peter ZijlstraFrom: Paul E. McKenney <[email protected]>
The rcu_nmi_enter_common() and rcu_nmi_exit_common() functions take an "irq" parameter that indicates whether these functions are invoked from an irq handler (irq==true) or an NMI handler (irq==false). However, recent changes have applied notrace to a few critical functions such that rcu_nmi_enter_common() and rcu_nmi_exit_common() many now rely on in_nmi(). Note that in_nmi() works no differently than before, but rather that tracing is now prohibited in code regions where in_nmi() would incorrectly report NMI state.
This commit therefore removes the "irq" parameter and inlines rcu_nmi_enter_common() and rcu_nmi_exit_common() into rcu_nmi_enter() and rcu_nmi_exit(), respectively.
--- kernel/rcu/tree.c | 45 ++++++++++++++------------------------------- 1 file changed, 14 insertions(+), 31 deletions(-)
kernel/rcu/tree.c +14 -31
@@ -614,16 +614,18 @@ void rcu_user_enter(void) }#endif /* CONFIG_NO_HZ_FULL */ -/* +/** +* rcu_nmi_exit - inform RCU of exit from NMI context +* * If we are returning from the outermost NMI handler that interrupted an * RCU-idle period, update rdp->dynticks and rdp->dynticks_nmi_nesting * to let the RCU grace-period handling know that the CPU is back to * being RCU-idle. * -* If you add or remove a call to rcu_nmi_exit_common(), be sure to test +* If you add or remove a call to rcu_nmi_exit(), be sure to test * with CONFIG_RCU_EQS_DEBUG=y. */ -static __always_inline void rcu_nmi_exit_common(bool irq) +void rcu_nmi_exit (void ) {struct rcu_data *rdp =this_cpu_ptr (&rcu_data);
@@ -651,27 +653,16 @@ static __always_inline void rcu_nmi_exittrace_rcu_dyntick (TPS ("Startirq" ), rdp->dynticks_nmi_nesting,0 ,atomic_read (&rdp->dynticks));WRITE_ONCE (rdp->dynticks_nmi_nesting,0 );/* Avoid store tearing. */ -if (irq) +if (!in_nmi ())rcu_prepare_for_idle ();rcu_dynticks_eqs_enter (); -if (irq) +if (!in_nmi ())rcu_dynticks_task_enter (); }/** -* rcu_nmi_exit - inform RCU of exit from NMI context -* -* If you add or remove a call to rcu_nmi_exit(), be sure to test -* with CONFIG_RCU_EQS_DEBUG=y. -*/ -void rcu_nmi_exit (void ) -{ -rcu_nmi_exit_common (false); -} - -/** * rcu_irq_exit - inform RCU that current CPU is exiting irq towards idle * * Exit from an interrupt handler, which might possibly result in entering
@@ -693,7 +684,7 @@ void rcu_nmi_exit(void)void rcu_irq_exit (void ) {lockdep_assert_irqs_disabled (); -rcu_nmi_exit_common (true); +rcu_nmi_exit (); }/*
@@ -777,7 +768,7 @@ void rcu_user_exit(void)#endif /* CONFIG_NO_HZ_FULL */ /** -* rcu_nmi_enter_common - inform RCU of entry to NMI context +* rcu_nmi_enter - inform RCU of entry to NMI context * @irq: Is this call from rcu_irq_enter? * * If the CPU was idle from RCU's viewpoint, update rdp->dynticks and
@@ -786,10 +777,10 @@ void rcu_user_exit(void)* long as the nesting level does not overflow an int. (You will probably * run out of stack space first.) * -* If you add or remove a call to rcu_nmi_enter_common(), be sure to test +* If you add or remove a call to rcu_nmi_enter(), be sure to test * with CONFIG_RCU_EQS_DEBUG=y. */ -static __always_inline void rcu_nmi_enter_common(bool irq) +void rcu_nmi_enter (void ) {long incby =2 ;struct rcu_data *rdp =this_cpu_ptr (&rcu_data);
@@ -807,12 +798,12 @@ static __always_inline void rcu_nmi_ente*/ if (rcu_dynticks_curr_cpu_in_eqs ()) { -if (irq) +if (!in_nmi ())rcu_dynticks_task_exit ();rcu_dynticks_eqs_exit (); -if (irq) +if (!in_nmi ())rcu_cleanup_after_idle (); incby =1 ;
@@ -834,14 +825,6 @@ static __always_inline void rcu_nmi_ente rdp->dynticks_nmi_nesting + incby);barrier (); } - -/** -* rcu_nmi_enter - inform RCU of entry to NMI context -*/ -void rcu_nmi_enter (void ) -{ -rcu_nmi_enter_common (false); -}NOKPROBE_SYMBOL (rcu_nmi_enter);/**
@@ -869,7 +852,7 @@ NOKPROBE_SYMBOL(rcu_nmi_enter);void rcu_irq_enter (void ) {lockdep_assert_irqs_disabled (); -rcu_nmi_enter_common (true); +rcu_nmi_enter (); }/*
Paul E. McKenney
maintainerRe: [PATCH v3 05/22] rcu: Make RCU IRQ enter/exit functions rely on in_nmi()
Quoted 11 lines · Peter Zijlstra
From: Paul E. McKenney <[email protected]>
The
rcu_nmi_enter_common()andrcu_nmi_exit_common()functions take an "irq" parameter that indicates whether these functions are invoked from an irq handler (irq==true) or an NMI handler (irq==false). However, recent changes have applied notrace to a few critical functions such thatrcu_nmi_enter_common()andrcu_nmi_exit_common()many now rely onin_nmi(). Note thatin_nmi()works no differently than before, but rather that tracing is now prohibited in code regions wherein_nmi()would incorrectly report NMI state.
Quoted 6 lines
This commit therefore removes the "irq" parameter and inlines
rcu_nmi_enter_common()andrcu_nmi_exit_common()intorcu_nmi_enter()andrcu_nmi_exit(), respectively.Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Peter Zijlstra (Intel) <[email protected]>
Again, thank you.
Would you like to also take the added comment for NOKPROBE_SYMBOL(), or would you prefer that I carry that separately? (I dropped it for now to avoid the conflict with the patch below.)
Here is the latest version of that comment, posted by Steve Rostedt.
Thanx, Paul
/*
* All functions called in the breakpoint trap handler (e.g. do_int3()
* on x86), must not allow kprobes until the kprobe breakpoint handler
* is called, otherwise it can cause an infinite recursion.
* On some archs, rcu_nmi_enter() is called in the breakpoint handler
* before the kprobe breakpoint handler is called, thus it must be
* marked as NOKPROBE.
*/
Quoted 130 lines
--- kernel/rcu/tree.c | 45 ++++++++++++++------------------------------- 1 file changed, 14 insertions(+), 31 deletions(-)kernel/rcu/tree.c +14
-31@@ -614,16 +614,18 @@ void rcu_user_enter(void) }#endif /* CONFIG_NO_HZ_FULL */ -/* +/** +* rcu_nmi_exit - inform RCU of exit from NMI context +* * If we are returning from the outermost NMI handler that interrupted an * RCU-idle period, update rdp->dynticks and rdp->dynticks_nmi_nesting * to let the RCU grace-period handling know that the CPU is back to * being RCU-idle. * -* If you add or remove a call to rcu_nmi_exit_common(), be sure to test +* If you add or remove a call to rcu_nmi_exit(), be sure to test * with CONFIG_RCU_EQS_DEBUG=y. */ -static __always_inline void rcu_nmi_exit_common(bool irq) +void rcu_nmi_exit (void ) {struct rcu_data *rdp =this_cpu_ptr (&rcu_data);@@ -651,27 +653,16 @@ static __always_inline void rcu_nmi_exittrace_rcu_dyntick (TPS ("Startirq" ), rdp->dynticks_nmi_nesting,0 ,atomic_read (&rdp->dynticks));WRITE_ONCE (rdp->dynticks_nmi_nesting,0 );/* Avoid store tearing. */ -if (irq) +if (!in_nmi ())rcu_prepare_for_idle ();rcu_dynticks_eqs_enter (); -if (irq) +if (!in_nmi ())rcu_dynticks_task_enter (); }/** -* rcu_nmi_exit - inform RCU of exit from NMI context -* -* If you add or remove a call to rcu_nmi_exit(), be sure to test -* with CONFIG_RCU_EQS_DEBUG=y. -*/ -void rcu_nmi_exit (void ) -{ -rcu_nmi_exit_common (false); -} - -/** * rcu_irq_exit - inform RCU that current CPU is exiting irq towards idle * * Exit from an interrupt handler, which might possibly result in entering @@ -693,7 +684,7 @@ void rcu_nmi_exit(void)void rcu_irq_exit (void ) {lockdep_assert_irqs_disabled (); -rcu_nmi_exit_common (true); +rcu_nmi_exit (); }/* @@ -777,7 +768,7 @@ void rcu_user_exit(void)#endif /* CONFIG_NO_HZ_FULL */ /** -* rcu_nmi_enter_common - inform RCU of entry to NMI context +* rcu_nmi_enter - inform RCU of entry to NMI context * @irq: Is this call from rcu_irq_enter? * * If the CPU was idle from RCU's viewpoint, update rdp->dynticks and @@ -786,10 +777,10 @@ void rcu_user_exit(void)* long as the nesting level does not overflow an int. (You will probably * run out of stack space first.) * -* If you add or remove a call to rcu_nmi_enter_common(), be sure to test +* If you add or remove a call to rcu_nmi_enter(), be sure to test * with CONFIG_RCU_EQS_DEBUG=y. */ -static __always_inline void rcu_nmi_enter_common(bool irq) +void rcu_nmi_enter (void ) {long incby =2 ;struct rcu_data *rdp =this_cpu_ptr (&rcu_data);@@ -807,12 +798,12 @@ static __always_inline void rcu_nmi_ente*/ if (rcu_dynticks_curr_cpu_in_eqs ()) { -if (irq) +if (!in_nmi ())rcu_dynticks_task_exit ();rcu_dynticks_eqs_exit (); -if (irq) +if (!in_nmi ())rcu_cleanup_after_idle (); incby =1 ;@@ -834,14 +825,6 @@ static __always_inline void rcu_nmi_ente rdp->dynticks_nmi_nesting + incby);barrier (); } - -/** -* rcu_nmi_enter - inform RCU of entry to NMI context -*/ -void rcu_nmi_enter (void ) -{ -rcu_nmi_enter_common (false); -}NOKPROBE_SYMBOL (rcu_nmi_enter);/** @@ -869,7 +852,7 @@ NOKPROBE_SYMBOL(rcu_nmi_enter);void rcu_irq_enter (void ) {lockdep_assert_irqs_disabled (); -rcu_nmi_enter_common (true); +rcu_nmi_enter (); }/*
Peter Zijlstra
maintainerRe: [PATCH v3 05/22] rcu: Make RCU IRQ enter/exit functions rely on in_nmi()
Quoted 29 lines · Paul E. McKenney
Quoted 11 lines · Peter Zijlstra
From: Paul E. McKenney <[email protected]>
The
rcu_nmi_enter_common()andrcu_nmi_exit_common()functions take an "irq" parameter that indicates whether these functions are invoked from an irq handler (irq==true) or an NMI handler (irq==false). However, recent changes have applied notrace to a few critical functions such thatrcu_nmi_enter_common()andrcu_nmi_exit_common()many now rely onin_nmi(). Note thatin_nmi()works no differently than before, but rather that tracing is now prohibited in code regions wherein_nmi()would incorrectly report NMI state.Quoted 6 lines
This commit therefore removes the "irq" parameter and inlines
rcu_nmi_enter_common()andrcu_nmi_exit_common()intorcu_nmi_enter()andrcu_nmi_exit(), respectively.Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Peter Zijlstra (Intel) <[email protected]>Again, thank you.
Would you like to also take the added comment for
NOKPROBE_SYMBOL(), or would you prefer that I carry that separately? (I dropped it for now to avoid the conflict with the patch below.)Here is the latest version of that comment, posted by Steve Rostedt.
Thanx, Paul
Quoted 8 lines
/*
* All functions called in the breakpoint trap handler (e.g.do_int3()
* on x86), must not allow kprobes until the kprobe breakpoint handler
* is called, otherwise it can cause an infinite recursion.
* On some archs,rcu_nmi_enter()is called in the breakpoint handler
* before the kprobe breakpoint handler is called, thus it must be
* marked as NOKPROBE.
*/
Oh right, let me stick that in a separate patch. Best we not loose that I suppose ;-)
Paul E. McKenney
maintainerRe: [PATCH v3 05/22] rcu: Make RCU IRQ enter/exit functions rely on in_nmi()
Quoted 39 lines · Peter Zijlstra
Quoted 29 lines · Paul E. McKenney
Quoted 11 lines · Peter Zijlstra
From: Paul E. McKenney <[email protected]>
The
rcu_nmi_enter_common()andrcu_nmi_exit_common()functions take an "irq" parameter that indicates whether these functions are invoked from an irq handler (irq==true) or an NMI handler (irq==false). However, recent changes have applied notrace to a few critical functions such thatrcu_nmi_enter_common()andrcu_nmi_exit_common()many now rely onin_nmi(). Note thatin_nmi()works no differently than before, but rather that tracing is now prohibited in code regions wherein_nmi()would incorrectly report NMI state.Quoted 6 lines
This commit therefore removes the "irq" parameter and inlines
rcu_nmi_enter_common()andrcu_nmi_exit_common()intorcu_nmi_enter()andrcu_nmi_exit(), respectively.Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Peter Zijlstra (Intel) <[email protected]>Again, thank you.
Would you like to also take the added comment for
NOKPROBE_SYMBOL(), or would you prefer that I carry that separately? (I dropped it for now to avoid the conflict with the patch below.)Here is the latest version of that comment, posted by Steve Rostedt.
Thanx, Paul
Quoted 8 lines
/*
* All functions called in the breakpoint trap handler (e.g.do_int3()
* on x86), must not allow kprobes until the kprobe breakpoint handler
* is called, otherwise it can cause an infinite recursion.
* On some archs,rcu_nmi_enter()is called in the breakpoint handler
* before the kprobe breakpoint handler is called, thus it must be
* marked as NOKPROBE.
*/
Quoted 2 lines
Oh right, let me stick that in a separate patch. Best we not loose that I suppose ;-)
There was a lot of effort spent on it, to be sure. ;-) ;-) ;-)
Thanx, Paul
Re: [PATCH v3 05/22] rcu: Make RCU IRQ enter/exit functions rely on in_nmi()
In reply to Peter ZijlstraQuoted 15 lines · Peter Zijlstra
Quoted 4 lines · Paul E. McKenney
Here is the latest version of that comment, posted by Steve Rostedt.
Thanx, Paul
Quoted 8 lines
/*
* All functions called in the breakpoint trap handler (e.g.do_int3()
* on x86), must not allow kprobes until the kprobe breakpoint handler
* is called, otherwise it can cause an infinite recursion.
* On some archs,rcu_nmi_enter()is called in the breakpoint handler
* before the kprobe breakpoint handler is called, thus it must be
* marked as NOKPROBE.
*/
Quoted 2 lines
Oh right, let me stick that in a separate patch. Best we not loose that I suppose ;-)
Having gone over the old thread, I ended up with the below. Anyone holler if I got it wrong somehow.
---
Subject: rcu: Provide comment for NOKPROBE() on rcu_nmi_enter()
From: Steven Rostedt <[email protected]>
From: Steven Rostedt <[email protected]>
The rcu_nmi_enter() function was marked NOKPROBE() by commit c13324a505c77 ("x86/kprobes: Prohibit probing on functions before kprobe_int3_handler()") because the do_int3() call kprobe code must not be invoked before kprobe_int3_handler() is called. It turns out that ist_enter() (in do_int3()) calls rcu_nmi_enter(), hence the marking NOKPROBE() being added to rcu_nmi_enter().
This commit therefore adds a comment documenting this line of reasoning.
--- kernel/rcu/tree.c | 8 ++++++++ 1 file changed, 8 insertions(+)
kernel/rcu/tree.c +8 -0
@@ -842,6 +842,14 @@ void rcu_nmi_enter(void) {rcu_nmi_enter_common (false); } +/* +* All functions called in the breakpoint trap handler (e.g. do_int3() +* on x86), must not allow kprobes until the kprobe breakpoint handler +* is called, otherwise it can cause an infinite recursion. +* On some archs, rcu_nmi_enter() is called in the breakpoint handler +* before the kprobe breakpoint handler is called, thus it must be +* marked as NOKPROBE. +*/ NOKPROBE_SYMBOL (rcu_nmi_enter);/**
Paul E. McKenney
maintainerRe: [PATCH v3 05/22] rcu: Make RCU IRQ enter/exit functions rely on in_nmi()
Quoted 16 lines · Peter Zijlstra
Quoted 15 lines · Peter Zijlstra
Quoted 12 lines · Paul E. McKenney
Here is the latest version of that comment, posted by Steve Rostedt.
Thanx, Paul
/*
* All functions called in the breakpoint trap handler (e.g.do_int3()
* on x86), must not allow kprobes until the kprobe breakpoint handler
* is called, otherwise it can cause an infinite recursion.
* On some archs,rcu_nmi_enter()is called in the breakpoint handler
* before the kprobe breakpoint handler is called, thus it must be
* marked as NOKPROBE.
*/
Quoted 5 lines
Quoted 2 lines
Oh right, let me stick that in a separate patch. Best we not loose that I suppose ;-)
Having gone over the old thread, I ended up with the below. Anyone holler if I got it wrong somehow.
Looks good to me!
Thanx, Paul
Quoted 41 lines
---
Subject: rcu: Provide comment forNOKPROBE()onrcu_nmi_enter()
From: Steven Rostedt <[email protected]>From: Steven Rostedt <[email protected]>
The
rcu_nmi_enter()function was markedNOKPROBE()by commitc13324a505c77("x86/kprobes: Prohibit probing on functions beforekprobe_int3_handler()") because thedo_int3()call kprobe code must not be invoked beforekprobe_int3_handler()is called. It turns out thatist_enter()(indo_int3()) callsrcu_nmi_enter(), hence the markingNOKPROBE()being added torcu_nmi_enter().This commit therefore adds a comment documenting this line of reasoning.
Signed-off-by Steven Rostedt <[email protected]>Reviewed-by Masami Hiramatsu <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Peter Zijlstra (Intel) <[email protected]>--- kernel/rcu/tree.c | 8 ++++++++ 1 file changed, 8 insertions(+)kernel/rcu/tree.c +8
-0@@ -842,6 +842,14 @@ void rcu_nmi_enter(void) {rcu_nmi_enter_common (false); } +/* +* All functions called in the breakpoint trap handler (e.g. do_int3() +* on x86), must not allow kprobes until the kprobe breakpoint handler +* is called, otherwise it can cause an infinite recursion. +* On some archs, rcu_nmi_enter() is called in the breakpoint handler +* before the kprobe breakpoint handler is called, thus it must be +* marked as NOKPROBE. +*/ NOKPROBE_SYMBOL (rcu_nmi_enter);/**
Steven Rostedt
maintainerPATCH 1/1 rcu/kprobes: Comment why rcu_nmi_enter() is marked NOKPROBE
In reply to Paul E. McKenneyFrom: Steven Rostedt (VMware) <[email protected]>
It's confusing that rcu_nmi_enter() is marked NOKPROBE and rcu_nmi_exit() is not. One may think that the exit needs to be marked for the same reason the enter is, as rcu_nmi_exit() reverts the RCU state back to what it was before rcu_nmi_enter(). But the reason has nothing to do with the state of RCU.
The breakpoint handler (int3 on x86) must not have any kprobe on it until the kprobe handler is called. Otherwise, it can cause an infinite recursion and crash the machine. It just so happens that rcu_nmi_enter() is called by the int3 handler before the kprobe handler can run, and therefore needs to be marked as NOKPROBE.
Comment this to remove the confusion to why rcu_nmi_enter() is marked NOKPROBE but rcu_nmi_exit() is not.
---
kernel/rcu/tree.c +8 -0
@@ -846,6 +846,14 @@ void rcu_nmi_enter(void) {rcu_nmi_enter_common (false); } +/* +* All functions called in the breakpoint trap handler (e.g. do_int3() +* on x86), must not allow kprobes until the kprobe breakpoint handler +* is called, otherwise it can cause an infinite recursion. +* On some archs, rcu_nmi_enter() is called in the breakpoint handler +* before the kprobe breakpoint handler is called, thus it must be +* marked as NOKPROBE. +*/ NOKPROBE_SYMBOL (rcu_nmi_enter);/**
Re: [PATCH] rcu/kprobes: Comment why rcu_nmi_enter() is marked NOKPROBE
Quoted 15 lines · Steven Rostedt
From: Steven Rostedt (VMware) <[email protected]>
It's confusing that
rcu_nmi_enter()is marked NOKPROBE andrcu_nmi_exit()is not. One may think that the exit needs to be marked for the same reason the enter is, asrcu_nmi_exit()reverts the RCU state back to what it was beforercu_nmi_enter(). But the reason has nothing to do with the state of RCU.The breakpoint handler (int3 on x86) must not have any kprobe on it until the kprobe handler is called. Otherwise, it can cause an infinite recursion and crash the machine. It just so happens that
rcu_nmi_enter()is called by the int3 handler before the kprobe handler can run, and therefore needs to be marked as NOKPROBE.
Quoted 5 lines
Comment this to remove the confusion to why
rcu_nmi_enter()is marked NOKPROBE butrcu_nmi_exit()is not.
thanks,
- Joel
Quoted 20 lines
---
kernel/rcu/tree.c +8
-0@@ -846,6 +846,14 @@ void rcu_nmi_enter(void) {rcu_nmi_enter_common (false); } +/* +* All functions called in the breakpoint trap handler (e.g. do_int3() +* on x86), must not allow kprobes until the kprobe breakpoint handler +* is called, otherwise it can cause an infinite recursion. +* On some archs, rcu_nmi_enter() is called in the breakpoint handler +* before the kprobe breakpoint handler is called, thus it must be +* marked as NOKPROBE. +*/ NOKPROBE_SYMBOL (rcu_nmi_enter);/**
Re: [PATCH] rcu/kprobes: Comment why rcu_nmi_enter() is marked NOKPROBE
In reply to Steven RostedtQuoted 14 lines · Steven Rostedt
From: Steven Rostedt (VMware) <[email protected]>
It's confusing that
rcu_nmi_enter()is marked NOKPROBE andrcu_nmi_exit()is not. One may think that the exit needs to be marked for the same reason the enter is, asrcu_nmi_exit()reverts the RCU state back to what it was beforercu_nmi_enter(). But the reason has nothing to do with the state of RCU.The breakpoint handler (int3 on x86) must not have any kprobe on it until the kprobe handler is called. Otherwise, it can cause an infinite recursion and crash the machine. It just so happens that
rcu_nmi_enter()is called by the int3 handler before the kprobe handler can run, and therefore needs to be marked as NOKPROBE.
Quoted 5 lines
Comment this to remove the confusion to why
rcu_nmi_enter()is marked NOKPROBE butrcu_nmi_exit()is not.
Quoted 20 lines
---
kernel/rcu/tree.c +8
-0@@ -846,6 +846,14 @@ void rcu_nmi_enter(void) {rcu_nmi_enter_common (false); } +/* +* All functions called in the breakpoint trap handler (e.g. do_int3() +* on x86), must not allow kprobes until the kprobe breakpoint handler +* is called, otherwise it can cause an infinite recursion. +* On some archs, rcu_nmi_enter() is called in the breakpoint handler +* before the kprobe breakpoint handler is called, thus it must be +* marked as NOKPROBE. +*/ NOKPROBE_SYMBOL (rcu_nmi_enter);/**
Re: [PATCH] rcu/kprobes: Comment why rcu_nmi_enter() is marked NOKPROBE
In reply to Steven RostedtQuoted 8 lines · On Wed, 19 Feb 2020 12:16:09 -0500 Steven Rostedt <[email protected]> wrote:
From: Steven Rostedt (VMware) <[email protected]>
It's confusing that
rcu_nmi_enter()is marked NOKPROBE andrcu_nmi_exit()is not. One may think that the exit needs to be marked for the same reason the enter is, asrcu_nmi_exit()reverts the RCU state back to what it was beforercu_nmi_enter(). But the reason has nothing to do with the state of RCU.
Quoted 8 lines
The breakpoint handler (int3 on x86) must not have any kprobe on it until the kprobe handler is called. Otherwise, it can cause an infinite recursion and crash the machine. It just so happens that
rcu_nmi_enter()is called by the int3 handler before the kprobe handler can run, and therefore needs to be marked as NOKPROBE.Comment this to remove the confusion to why
rcu_nmi_enter()is marked NOKPROBE butrcu_nmi_exit()is not.
Looks good to me.
Thanks,
Quoted 23 lines
Signed-off-by Steven Rostedt (VMware) <[email protected]>---
kernel/rcu/tree.c +8
-0@@ -846,6 +846,14 @@ void rcu_nmi_enter(void) {rcu_nmi_enter_common (false); } +/* +* All functions called in the breakpoint trap handler (e.g. do_int3() +* on x86), must not allow kprobes until the kprobe breakpoint handler +* is called, otherwise it can cause an infinite recursion. +* On some archs, rcu_nmi_enter() is called in the breakpoint handler +* before the kprobe breakpoint handler is called, thus it must be +* marked as NOKPROBE. +*/ NOKPROBE_SYMBOL (rcu_nmi_enter);/**
Signature · 1 line
Masami Hiramatsu <[email protected]>
Peter Zijlstra
maintainerPATCH v3 6/22 rcu: Rename rcu_irq_{enter,exit}_irqson()
In reply to Peter ZijlstraThe functions do in fact use local_irq_{save,restore}() and can therefore be used when IRQs are in fact disabled. Worse, they are already used in places where IRQs are disabled, leading to great confusion when reading the code.
Rename them to fix this confusion.
--- include/linux/rcupdate.h | 4 ++-- include/linux/rcutiny.h | 4 ++-- include/linux/rcutree.h | 4 ++-- include/linux/tracepoint.h | 4 ++-- kernel/cpu_pm.c | 4 ++-- kernel/rcu/tree.c | 8 ++++---- kernel/trace/trace.c | 4 ++-- 7 files changed, 16 insertions(+), 16 deletions(-)
include/linux/rcupdate.h +2 -2
@@ -120,9 +120,9 @@ static inline void rcu_init_nohz(void) {*/ #define RCU_NONIDLE (a) \ do { \ - rcu_irq_enter_irqson(); \ + rcu_irq_enter_irqsave(); \ do { a; } while (0); \ - rcu_irq_exit_irqson(); \ + rcu_irq_exit_irqsave(); \ } while (0)/*
include/linux/rcutiny.h +2 -2
@@ -68,8 +68,8 @@ static inline int rcu_jiffies_till_stallstatic inline void rcu_idle_enter (void ) { }static inline void rcu_idle_exit (void ) { }static inline void rcu_irq_enter (void ) { } -static inline void rcu_irq_exit_irqson (void ) { } -static inline void rcu_irq_enter_irqson (void ) { } +static inline void rcu_irq_exit_irqsave (void ) { } +static inline void rcu_irq_enter_irqsave (void ) { }static inline void rcu_irq_exit (void ) { }static inline void exit_rcu (void ) { }static inline bool rcu_preempt_need_deferred_qs (struct task_struct *t)
include/linux/rcutree.h +2 -2
@@ -46,8 +46,8 @@ void rcu_idle_enter(void);void rcu_idle_exit (void );void rcu_irq_enter (void );void rcu_irq_exit (void ); -void rcu_irq_enter_irqson (void ); -void rcu_irq_exit_irqson (void ); +void rcu_irq_enter_irqsave (void ); +void rcu_irq_exit_irqsave (void );void exit_rcu (void );
include/linux/tracepoint.h +2 -2
@@ -181,7 +181,7 @@ static inline struct tracepoint *tracepo*/ \if (rcuidle) { \ __idx =srcu_read_lock_notrace (&tracepoint_srcu);\ -rcu_irq_enter_irqson (); \ +rcu_irq_enter_irqsave (); \ } \ \ it_func_ptr =rcu_dereference_raw ((tp)->funcs); \
@@ -195,7 +195,7 @@ static inline struct tracepoint *tracepo } \ \if (rcuidle) { \ -rcu_irq_exit_irqson (); \ +rcu_irq_exit_irqsave (); \srcu_read_unlock_notrace (&tracepoint_srcu, __idx);\ } \ \
kernel/cpu_pm.c +2 -2
@@ -24,10 +24,10 @@ static int cpu_pm_notify(enum cpu_pm_eve* could be disfunctional in cpu idle. Copy RCU_NONIDLE code to let * RCU know this. */ -rcu_irq_enter_irqson (); +rcu_irq_enter_irqsave (); ret =__atomic_notifier_call_chain (&cpu_pm_notifier_chain, event,NULL , nr_to_call, nr_calls); -rcu_irq_exit_irqson (); +rcu_irq_exit_irqsave ();return notifier_to_errno (ret); }
kernel/rcu/tree.c +4 -4
@@ -699,10 +699,10 @@ void rcu_irq_exit(void)/* * Wrapper for rcu_irq_exit() where interrupts are enabled. * -* If you add or remove a call to rcu_irq_exit_irqson(), be sure to test +* If you add or remove a call to rcu_irq_exit_irqsave(), be sure to test * with CONFIG_RCU_EQS_DEBUG=y. */ -void rcu_irq_exit_irqson (void ) +void rcu_irq_exit_irqsave (void ) {unsigned long flags;
@@ -875,10 +875,10 @@ void rcu_irq_enter(void)/* * Wrapper for rcu_irq_enter() where interrupts are enabled. * -* If you add or remove a call to rcu_irq_enter_irqson(), be sure to test +* If you add or remove a call to rcu_irq_enter_irqsave(), be sure to test * with CONFIG_RCU_EQS_DEBUG=y. */ -void rcu_irq_enter_irqson (void ) +void rcu_irq_enter_irqsave (void ) {unsigned long flags;
kernel/trace/trace.c +2 -2
@@ -3004,9 +3004,9 @@ void __trace_stack(struct trace_array *tif (unlikely (in_nmi ()))return ; -rcu_irq_enter_irqson (); +rcu_irq_enter_irqsave ();__ftrace_trace_stack (buffer, flags, skip, pc,NULL ); -rcu_irq_exit_irqson (); +rcu_irq_exit_irqsave (); }/**
Re: [PATCH v3 06/22] rcu: Rename rcu_irq_{enter,exit}_irqson()
Quoted 8 lines · Peter Zijlstra
The functions do in fact use local_irq_{save,restore}() and can therefore be used when IRQs are in fact disabled. Worse, they are already used in places where IRQs are disabled, leading to great confusion when reading the code.
Rename them to fix this confusion.
Signed-off-by Peter Zijlstra (Intel) <[email protected]>
My first reaction was "Hey, wait, where is the _irqrestore()?"
Nevertheless, especially since these are the only _irqson() functions:
Quoted 129 lines
--- include/linux/rcupdate.h | 4 ++-- include/linux/rcutiny.h | 4 ++-- include/linux/rcutree.h | 4 ++-- include/linux/tracepoint.h | 4 ++-- kernel/cpu_pm.c | 4 ++-- kernel/rcu/tree.c | 8 ++++---- kernel/trace/trace.c | 4 ++-- 7 files changed, 16 insertions(+), 16 deletions(-)include/linux/rcupdate.h +2
-2@@ -120,9 +120,9 @@ static inline void rcu_init_nohz(void) {*/ #define RCU_NONIDLE (a) \ do { \ - rcu_irq_enter_irqson(); \ + rcu_irq_enter_irqsave(); \ do { a; } while (0); \ - rcu_irq_exit_irqson(); \ + rcu_irq_exit_irqsave(); \ } while (0)/* include/linux/rcutiny.h +2
-2@@ -68,8 +68,8 @@ static inline int rcu_jiffies_till_stallstatic inline void rcu_idle_enter (void ) { }static inline void rcu_idle_exit (void ) { }static inline void rcu_irq_enter (void ) { } -static inline void rcu_irq_exit_irqson (void ) { } -static inline void rcu_irq_enter_irqson (void ) { } +static inline void rcu_irq_exit_irqsave (void ) { } +static inline void rcu_irq_enter_irqsave (void ) { }static inline void rcu_irq_exit (void ) { }static inline void exit_rcu (void ) { }static inline bool rcu_preempt_need_deferred_qs (struct task_struct *t)include/linux/rcutree.h +2
-2@@ -46,8 +46,8 @@ void rcu_idle_enter(void);void rcu_idle_exit (void );void rcu_irq_enter (void );void rcu_irq_exit (void ); -void rcu_irq_enter_irqson (void ); -void rcu_irq_exit_irqson (void ); +void rcu_irq_enter_irqsave (void ); +void rcu_irq_exit_irqsave (void );void exit_rcu (void );include/linux/tracepoint.h +2
-2@@ -181,7 +181,7 @@ static inline struct tracepoint *tracepo*/ \if (rcuidle) { \ __idx =srcu_read_lock_notrace (&tracepoint_srcu);\ -rcu_irq_enter_irqson (); \ +rcu_irq_enter_irqsave (); \ } \ \ it_func_ptr =rcu_dereference_raw ((tp)->funcs); \@@ -195,7 +195,7 @@ static inline struct tracepoint *tracepo } \ \if (rcuidle) { \ -rcu_irq_exit_irqson (); \ +rcu_irq_exit_irqsave (); \srcu_read_unlock_notrace (&tracepoint_srcu, __idx);\ } \ \kernel/cpu_pm.c +2
-2@@ -24,10 +24,10 @@ static int cpu_pm_notify(enum cpu_pm_eve* could be disfunctional in cpu idle. Copy RCU_NONIDLE code to let * RCU know this. */ -rcu_irq_enter_irqson (); +rcu_irq_enter_irqsave (); ret =__atomic_notifier_call_chain (&cpu_pm_notifier_chain, event,NULL , nr_to_call, nr_calls); -rcu_irq_exit_irqson (); +rcu_irq_exit_irqsave ();return notifier_to_errno (ret); }kernel/rcu/tree.c +4
-4@@ -699,10 +699,10 @@ void rcu_irq_exit(void)/* * Wrapper for rcu_irq_exit() where interrupts are enabled. * -* If you add or remove a call to rcu_irq_exit_irqson(), be sure to test +* If you add or remove a call to rcu_irq_exit_irqsave(), be sure to test * with CONFIG_RCU_EQS_DEBUG=y. */ -void rcu_irq_exit_irqson (void ) +void rcu_irq_exit_irqsave (void ) {unsigned long flags;@@ -875,10 +875,10 @@ void rcu_irq_enter(void)/* * Wrapper for rcu_irq_enter() where interrupts are enabled. * -* If you add or remove a call to rcu_irq_enter_irqson(), be sure to test +* If you add or remove a call to rcu_irq_enter_irqsave(), be sure to test * with CONFIG_RCU_EQS_DEBUG=y. */ -void rcu_irq_enter_irqson (void ) +void rcu_irq_enter_irqsave (void ) {unsigned long flags;kernel/trace/trace.c +2
-2@@ -3004,9 +3004,9 @@ void __trace_stack(struct trace_array *tif (unlikely (in_nmi ()))return ; -rcu_irq_enter_irqson (); +rcu_irq_enter_irqsave ();__ftrace_trace_stack (buffer, flags, skip, pc,NULL ); -rcu_irq_exit_irqson (); +rcu_irq_exit_irqsave (); }/**
Peter Zijlstra
maintainerPATCH v3 7/22 rcu: Mark rcu_dynticks_curr_cpu_in_eqs() inline
In reply to Peter ZijlstraSince rcu_is_watching() is notrace (and needs to be, as it can be called from the tracers), make sure everything it in turn calls is notrace too.
To that effect, mark rcu_dynticks_curr_cpu_in_eqs() inline, which implies notrace, as the function is tiny.
--- kernel/rcu/tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/rcu/tree.c +1 -1
@@ -294,7 +294,7 @@ static void rcu_dynticks_eqs_online(void* * No ordering, as we are sampling CPU-local information. */ -static bool rcu_dynticks_curr_cpu_in_eqs (void ) +static inline bool rcu_dynticks_curr_cpu_in_eqs (void ) {struct rcu_data *rdp =this_cpu_ptr (&rcu_data);
Re: [PATCH v3 07/22] rcu: Mark rcu_dynticks_curr_cpu_in_eqs() inline
Quoted 8 lines · Peter Zijlstra
Since
rcu_is_watching()is notrace (and needs to be, as it can be called from the tracers), make sure everything it in turn calls is notrace too.To that effect, mark
rcu_dynticks_curr_cpu_in_eqs()inline, which implies notrace, as the function is tiny.Signed-off-by Peter Zijlstra (Intel) <[email protected]>
There was some controversy over inline vs. notrace, leading me to ask whether we should use both inline and notrace here. ;-)
Assuming that the usual tracing suspects are OK with it:
Quoted 17 lines
--- kernel/rcu/tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)kernel/rcu/tree.c +1
-1@@ -294,7 +294,7 @@ static void rcu_dynticks_eqs_online(void* * No ordering, as we are sampling CPU-local information. */ -static bool rcu_dynticks_curr_cpu_in_eqs (void ) +static inline bool rcu_dynticks_curr_cpu_in_eqs (void ) {struct rcu_data *rdp =this_cpu_ptr (&rcu_data);
Steven Rostedt
maintainerRe: [PATCH v3 07/22] rcu: Mark rcu_dynticks_curr_cpu_in_eqs() inline
Quoted 2 lines · On Wed, 19 Feb 2020 08:39:34 -0800 "Paul E. McKenney" <[email protected]>…
There was some controversy over inline vs. notrace, leading me to ask whether we should use both inline and notrace here. ;-)
"inline" implicitly suggests "notrace". The reason being is that there were "surprises" when gcc decided not to inline various functions marked as "inline" which caused ftrace to break. I figured, if someone marks something as "inline" that it should not be traced regardless if gcc decided to inline it or not.
-- Steve
Peter Zijlstra
maintainerPATCH v3 8/22 rcu,tracing: Create trace_rcu_{enter,exit}()
In reply to Peter ZijlstraTo facilitate tracers that need RCU, add some helpers to wrap the magic required.
The problem is that we can call into tracers (trace events and function tracing) while RCU isn't watching and this can happen from any context, including NMI.
It is this latter that is causing most of the trouble; we must make sure in_nmi() returns true before we land in anything tracing, otherwise we cannot recover.
These helpers are macros because of header-hell; they're placed here because of the proximity to nmi_{enter,exit{().
--- include/linux/hardirq.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+)
include/linux/hardirq.h +32 -0
@@ -89,4 +89,36 @@ extern void irq_exit(void);arch_nmi_exit (); \ } while (0) +/* +* Tracing vs RCU +* -------------- +* +* tracepoints and function-tracing can happen when RCU isn't watching (idle, +* or early IRQ/NMI entry). +* +* When it happens during idle or early during IRQ entry, tracing will have +* to inform RCU that it ought to pay attention, this is done by calling +* rcu_irq_enter_irqsave(). +* +* On NMI entry, we must be very careful that tracing only happens after we've +* incremented preempt_count(), otherwise we cannot tell we're in NMI and take +* the special path. + */ + +#define trace_rcu_enter () \ +({ \ + unsigned long state = 0; \ + if (!rcu_is_watching()) { \ + rcu_irq_enter_irqsave(); \ + state = 1; \ + } \ + state; \ +}) + +#define trace_rcu_exit (state) \ +do { \ + if (state) \ + rcu_irq_exit_irqsave(); \ +} while (0) +#endif /* LINUX_HARDIRQ_H */
Steven Rostedt
maintainerRe: [PATCH v3 08/22] rcu,tracing: Create trace_rcu_{enter,exit}()
Quoted 40 lines · On Wed, 19 Feb 2020 15:47:32 +0100 Peter Zijlstra <[email protected]> wrote:
To facilitate tracers that need RCU, add some helpers to wrap the magic required.
The problem is that we can call into tracers (trace events and function tracing) while RCU isn't watching and this can happen from any context, including NMI.
It is this latter that is causing most of the trouble; we must make sure
in_nmi()returns true before we land in anything tracing, otherwise we cannot recover.These helpers are macros because of header-hell; they're placed here because of the proximity to nmi_{enter,exit{().
Signed-off-by Peter Zijlstra (Intel) <[email protected]>--- include/linux/hardirq.h | 32 ++++++++++++++++++++++++++++++++include/linux/hardirq.h +22
-0+/* +* Tracing vs RCU +* -------------- +* +* tracepoints and function-tracing can happen when RCU isn't watching (idle, +* or early IRQ/NMI entry). +* +* When it happens during idle or early during IRQ entry, tracing will have +* to inform RCU that it ought to pay attention, this is done by calling +* rcu_irq_enter_irqsave(). +* +* On NMI entry, we must be very careful that tracing only happens after we've +* incremented preempt_count(), otherwise we cannot tell we're in NMI and take +* the special path. +*/ + +#define trace_rcu_enter () \ +({ \ + unsigned long state = 0; \ + if (!rcu_is_watching()) { \ + rcu_irq_enter_irqsave(); \ + state = 1; \
include/linux/hardirq.h extern void irq_exit(void); · line 123
Quoted 10 lines
include/linux/hardirq.h +10
-0+ } \ + state; \ +}) + +#define trace_rcu_exit (state) \ +do { \ + if (state) \ + rcu_irq_exit_irqsave(); \ +} while (0) +
Is there a reason that these can't be static __always_inline functions?
-- Steve
Quoted 2 lines
#endif /*
LINUX_HARDIRQ_H*/
Peter Zijlstra
maintainerRe: [PATCH v3 08/22] rcu,tracing: Create trace_rcu_{enter,exit}()
Quoted 5 lines · Steven Rostedt
Quoted 2 lines · On Wed, 19 Feb 2020 15:47:32 +0100 Peter Zijlstra <[email protected]> wrote:
These helpers are macros because of header-hell; they're placed here because of the proximity to nmi_{enter,exit{().
^^^^
Quoted 10 lines
Quoted 10 lines
include/linux/hardirq.h +10
-0+#define trace_rcu_enter () \ +({ \ + unsigned long state = 0; \ + if (!rcu_is_watching()) { \ + rcu_irq_enter_irqsave(); \ + state = 1; \ + } \ + state; \ +}) +
Quoted 8 lines
include/linux/hardirq.h extern void irq_exit(void); · line 123
Quoted 6 lines
include/linux/hardirq.h +6
-0+#define trace_rcu_exit (state) \ +do { \ + if (state) \ + rcu_irq_exit_irqsave(); \ +} while (0) +Is there a reason that these can't be static
__always_inlinefunctions?
It can be done, but then we need fwd declarations of those RCU functions somewhere outside of rcupdate.h. It's all a bit of a mess.
Steven Rostedt
maintainerRe: [PATCH v3 08/22] rcu,tracing: Create trace_rcu_{enter,exit}()
Quoted 8 lines · On Wed, 19 Feb 2020 16:58:28 +0100 Peter Zijlstra <[email protected]> wrote:
Quoted 5 lines · Steven Rostedt
Quoted 2 lines · On Wed, 19 Feb 2020 15:47:32 +0100 Peter Zijlstra <[email protected]> wrote:
These helpers are macros because of header-hell; they're placed here because of the proximity to nmi_{enter,exit{().
^^^^
Bah I can't read, because I even went looking for this!
Quoted 20 lines
Quoted 11 lines
Quoted 11 lines
include/linux/hardirq.h +10
-0+#define trace_rcu_enter () \ +({ \ + unsigned long state = 0; \ + if (!rcu_is_watching()) { \ + rcu_irq_enter_irqsave(); \ + state = 1; \ + } \ + state; \ +}) +Quoted 8 lines
include/linux/hardirq.h extern void irq_exit(void); · line 123
Quoted 6 lines
include/linux/hardirq.h +6
-0+#define trace_rcu_exit (state) \ +do { \ + if (state) \ + rcu_irq_exit_irqsave(); \ +} while (0) +Is there a reason that these can't be static
__always_inlinefunctions?
Quoted 2 lines
It can be done, but then we need fwd declarations of those RCU functions somewhere outside of
rcupdate.h. It's all a bit of a mess.
Maybe this belongs in the rcupdate.h file then?
-- Steve
Peter Zijlstra
maintainerRe: [PATCH v3 08/22] rcu,tracing: Create trace_rcu_{enter,exit}()
Quoted 34 lines · Steven Rostedt
Quoted 8 lines · On Wed, 19 Feb 2020 16:58:28 +0100 Peter Zijlstra <[email protected]> wrote:
Quoted 5 lines · Steven Rostedt
Quoted 2 lines · On Wed, 19 Feb 2020 15:47:32 +0100 Peter Zijlstra <[email protected]> wrote:
These helpers are macros because of header-hell; they're placed here because of the proximity to nmi_{enter,exit{().
^^^^
Bah I can't read, because I even went looking for this!
Quoted 20 lines
Quoted 19 lines
Quoted 7 lines
include/linux/hardirq.h +6
-0+#define trace_rcu_enter () \ +({ \ + unsigned long state = 0; \ + if (!rcu_is_watching()) { \ + rcu_irq_enter_irqsave(); \ + state = 1; \include/linux/hardirq.h extern void irq_exit(void); · line 123
Quoted 10 lines
include/linux/hardirq.h +10
-0+ } \ + state; \ +}) + +#define trace_rcu_exit (state) \ +do { \ + if (state) \ + rcu_irq_exit_irqsave(); \ +} while (0) +Is there a reason that these can't be static
__always_inlinefunctions?
Quoted 4 lines
Quoted 2 lines
It can be done, but then we need fwd declarations of those RCU functions somewhere outside of
rcupdate.h. It's all a bit of a mess.Maybe this belongs in the
rcupdate.hfile then?
Possibly, and I suppose the current version is less obviously dependent on the in_nmi() functionality as was the previous, seeing how Paul frobbed that all the way into the rcu_irq_enter*() implementation.
So sure, I can go move it I suppose.
Paul E. McKenney
maintainerRe: [PATCH v3 08/22] rcu,tracing: Create trace_rcu_{enter,exit}()
Quoted 38 lines · Peter Zijlstra
Quoted 37 lines · Steven Rostedt
Quoted 8 lines · On Wed, 19 Feb 2020 16:58:28 +0100 Peter Zijlstra <[email protected]> wrote:
Quoted 5 lines · Steven Rostedt
Quoted 2 lines · On Wed, 19 Feb 2020 15:47:32 +0100 Peter Zijlstra <[email protected]> wrote:
These helpers are macros because of header-hell; they're placed here because of the proximity to nmi_{enter,exit{().
^^^^
Bah I can't read, because I even went looking for this!
Quoted 22 lines
Quoted 11 lines
Quoted 11 lines
include/linux/hardirq.h +10
-0+#define trace_rcu_enter () \ +({ \ + unsigned long state = 0; \ + if (!rcu_is_watching()) { \ + rcu_irq_enter_irqsave(); \ + state = 1; \ + } \ + state; \ +}) +Quoted 8 lines
include/linux/hardirq.h extern void irq_exit(void); · line 123
Quoted 6 lines
include/linux/hardirq.h +6
-0+#define trace_rcu_exit (state) \ +do { \ + if (state) \ + rcu_irq_exit_irqsave(); \ +} while (0) +Is there a reason that these can't be static
__always_inlinefunctions?It can be done, but then we need fwd declarations of those RCU functions somewhere outside of
rcupdate.h. It's all a bit of a mess.
Quoted 7 lines
Quoted 1 line
Maybe this belongs in the
rcupdate.hfile then?Possibly, and I suppose the current version is less obviously dependent on the
in_nmi()functionality as was the previous, seeing how Paul frobbed that all the way into the rcu_irq_enter*() implementation.So sure, I can go move it I suppose.
No objections here.
Thanx, Paul
Peter Zijlstra
maintainerRe: [PATCH v3 08/22] rcu,tracing: Create trace_rcu_{enter,exit}()
Quoted 9 lines · Paul E. McKenney
Quoted 5 lines · Peter Zijlstra
Possibly, and I suppose the current version is less obviously dependent on the
in_nmi()functionality as was the previous, seeing how Paul frobbed that all the way into the rcu_irq_enter*() implementation.So sure, I can go move it I suppose.
No objections here.
It now looks like so:
---
Subject: rcu,tracing: Create trace_rcu_{enter,exit}()
From: Peter Zijlstra <[email protected]>
Date: Wed Feb 12 09:18:57 CET 2020
To facilitate tracers that need RCU, add some helpers to wrap the magic required.
The problem is that we can call into tracers (trace events and function tracing) while RCU isn't watching and this can happen from any context, including NMI.
--- include/linux/rcupdate.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
include/linux/rcupdate.h +29 -0
@@ -175,6 +175,35 @@ do { \#error "Unknown RCU implementation specified to kernel configuration"#endif +/** +* trace_rcu_enter - Force RCU to be active, for code that needs RCU readers +* +* Very similar to RCU_NONIDLE() above. +* +* Tracing can happen while RCU isn't active yet, for instance in the idle loop +* between rcu_idle_enter() and rcu_idle_exit(), or early in exception entry. +* RCU will happily ignore any read-side critical sections in this case. +* +* This function ensures that RCU is aware hereafter and the code can readily +* rely on RCU read-side critical sections working as expected. +* +* This function is NMI safe -- provided in_nmi() is correct and will nest up-to +* INT_MAX/2 times. +*/ +static inline int trace_rcu_enter (void ) +{ +int state = !rcu_is_watching (); +if (state) +rcu_irq_enter_irqsave (); +return state; +} + +static inline void trace_rcu_exit (int state) +{ +if (state) +rcu_irq_exit_irqsave (); +} +/* * The init_rcu_head_on_stack() and destroy_rcu_head_on_stack() calls * are needed for dynamic initialization and destruction of rcu_head
Re: [PATCH v3 08/22] rcu,tracing: Create trace_rcu_{enter,exit}()
Quoted 18 lines · Peter Zijlstra
Quoted 9 lines · Paul E. McKenney
Quoted 5 lines · Peter Zijlstra
Possibly, and I suppose the current version is less obviously dependent on the
in_nmi()functionality as was the previous, seeing how Paul frobbed that all the way into the rcu_irq_enter*() implementation.So sure, I can go move it I suppose.
No objections here.
It now looks like so:
---
Subject: rcu,tracing: Create trace_rcu_{enter,exit}()
From: Peter Zijlstra <[email protected]>
Date: Wed Feb 12 09:18:57 CET 2020
Quoted 8 lines
To facilitate tracers that need RCU, add some helpers to wrap the magic required.
The problem is that we can call into tracers (trace events and function tracing) while RCU isn't watching and this can happen from any context, including NMI.
Signed-off-by Peter Zijlstra (Intel) <[email protected]>
Quoted 42 lines
--- include/linux/rcupdate.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)include/linux/rcupdate.h +29
-0@@ -175,6 +175,35 @@ do { \#error "Unknown RCU implementation specified to kernel configuration"#endif +/** +* trace_rcu_enter - Force RCU to be active, for code that needs RCU readers +* +* Very similar to RCU_NONIDLE() above. +* +* Tracing can happen while RCU isn't active yet, for instance in the idle loop +* between rcu_idle_enter() and rcu_idle_exit(), or early in exception entry. +* RCU will happily ignore any read-side critical sections in this case. +* +* This function ensures that RCU is aware hereafter and the code can readily +* rely on RCU read-side critical sections working as expected. +* +* This function is NMI safe -- provided in_nmi() is correct and will nest up-to +* INT_MAX/2 times. +*/ +static inline int trace_rcu_enter (void ) +{ +int state = !rcu_is_watching (); +if (state) +rcu_irq_enter_irqsave (); +return state; +} + +static inline void trace_rcu_exit (int state) +{ +if (state) +rcu_irq_exit_irqsave (); +} +/* * The init_rcu_head_on_stack() and destroy_rcu_head_on_stack() calls * are needed for dynamic initialization and destruction of rcu_head
Peter Zijlstra
maintainerPATCH v3 9/22 sched,rcu,tracing: Avoid tracing before in_nmi() is correct
In reply to Peter ZijlstraIf we call into a tracer before in_nmi() becomes true, the tracer can no longer detect it is called from NMI context and behave correctly.
Therefore change nmi_{enter,exit}() to use __preempt_count_{add,sub}() as the normal preempt_count_{add,sub}() have a (desired) function trace entry.
This fixes a potential issue with current code; AFAICT when the function-tracer has stack-tracing enabled __trace_stack() will malfunction when it hits the preempt_count_add() function entry from NMI context.
--- include/linux/hardirq.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
include/linux/hardirq.h +11 -2
@@ -65,6 +65,15 @@ extern void irq_exit(void);#define arch_nmi_exit () do { } while (0)#endif +/* +* NMI vs Tracing +* -------------- +* +* We must not land in a tracer until (or after) we've changed preempt_count +* such that in_nmi() becomes true. To that effect all NMI C entry points must +* be marked 'notrace' and call nmi_enter() as soon as possible. +*/ +#define nmi_enter () \ do { \ arch_nmi_enter(); \
@@ -72,7 +81,7 @@ extern void irq_exit(void);lockdep_off (); \ftrace_nmi_enter (); \BUG_ON (in_nmi () ==NMI_MASK ); \ -preempt_count_add (NMI_OFFSET +HARDIRQ_OFFSET ); \ +__preempt_count_add (NMI_OFFSET +HARDIRQ_OFFSET ); \rcu_nmi_enter (); \trace_hardirq_enter (); \ }while (0 )
@@ -82,7 +91,7 @@ extern void irq_exit(void);trace_hardirq_exit (); \rcu_nmi_exit (); \BUG_ON (!in_nmi ()); \ -preempt_count_sub (NMI_OFFSET +HARDIRQ_OFFSET ); \ +__preempt_count_sub (NMI_OFFSET +HARDIRQ_OFFSET ); \ftrace_nmi_exit (); \lockdep_on (); \printk_nmi_exit (); \
Re: [PATCH v3 09/22] sched,rcu,tracing: Avoid tracing before in_nmi() is correct
Quoted 7 lines · On Wed, 19 Feb 2020 15:47:33 +0100 Peter Zijlstra <[email protected]> wrote:
If we call into a tracer before
in_nmi()becomes true, the tracer can no longer detect it is called from NMI context and behave correctly.Therefore change nmi_{enter,exit}() to use __preempt_count_{add,sub}() as the normal preempt_count_{add,sub}() have a (desired) function trace entry.
Quoted 9 lines
This fixes a potential issue with current code; AFAICT when the function-tracer has stack-tracing enabled
__trace_stack()will malfunction when it hits thepreempt_count_add()function entry from NMI context.Suggested-by Steven Rostedt (VMware) <[email protected]>Signed-off-by Peter Zijlstra (Intel) <[email protected]>---
-- Steve
Re: [PATCH v3 09/22] sched,rcu,tracing: Avoid tracing before in_nmi() is correct
In reply to Peter ZijlstraQuoted 7 lines · On Wed, 19 Feb 2020 15:47:33 +0100 Peter Zijlstra <[email protected]> wrote:
If we call into a tracer before
in_nmi()becomes true, the tracer can no longer detect it is called from NMI context and behave correctly.Therefore change nmi_{enter,exit}() to use __preempt_count_{add,sub}() as the normal preempt_count_{add,sub}() have a (desired) function trace entry.
Quoted 8 lines
This fixes a potential issue with current code; AFAICT when the function-tracer has stack-tracing enabled
__trace_stack()will malfunction when it hits thepreempt_count_add()function entry from NMI context.Suggested-by Steven Rostedt (VMware) <[email protected]>Signed-off-by Peter Zijlstra (Intel) <[email protected]>---
-- Steve
Peter Zijlstra
maintainerPATCH v3 10/22 x86,tracing: Add comments to do_nmi()
In reply to Peter ZijlstraAdd a few comments to do_nmi() as a result of the audit.
--- arch/x86/kernel/nmi.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
arch/x86/kernel/nmi.c +8 -2
@@ -529,11 +529,14 @@ do_nmi(struct pt_regs *regs, long error_* continue to use the NMI stack. */ if (unlikely (is_debug_stack (regs->sp))) { -debug_stack_set_zero (); +debug_stack_set_zero ();/* notrace due to Makefile */ this_cpu_write (update_debug_stack,1 ); }#endif +/* +* It is important that no tracing happens before nmi_enter()! +*/ nmi_enter ();inc_irq_stat (__nmi_count);
@@ -542,10 +545,13 @@ do_nmi(struct pt_regs *regs, long error_default_do_nmi (regs);nmi_exit (); +/* +* No tracing after nmi_exit()! +*/ #ifdef CONFIG_X86_64 if (unlikely (this_cpu_read (update_debug_stack))) { -debug_stack_reset (); +debug_stack_reset ();/* notrace due to Makefile */ this_cpu_write (update_debug_stack,0 ); }#endif
Re: [PATCH v3 10/22] x86,tracing: Add comments to do_nmi()
Quoted 4 lines · On Wed, 19 Feb 2020 15:47:34 +0100 Peter Zijlstra <[email protected]> wrote:
Add a few comments to
do_nmi()as a result of the audit.Signed-off-by Peter Zijlstra (Intel) <[email protected]>---
-- Steve
Peter Zijlstra
maintainerPATCH v3 11/22 perf,tracing: Prepare the perf-trace interface for RCU changes
In reply to Peter ZijlstraThe tracepoint interface will stop providing regular RCU context; make sure we do it ourselves, since perf makes use of regular RCU protected data.
--- kernel/events/core.c | 5 +++++ 1 file changed, 5 insertions(+)
kernel/events/core.c +5 -0
@@ -8950,6 +8950,7 @@ void perf_tp_event(u16 event_type, u64 c {struct perf_sample_data data;struct perf_event *event; +unsigned long rcu_flags;struct perf_raw_record raw = { .frag = {
@@ -8961,6 +8962,8 @@ void perf_tp_event(u16 event_type, u64 cperf_sample_data_init (&data,0 ,0 ); data.raw = &raw; + rcu_flags =trace_rcu_enter (); +perf_trace_buf_update (record, event_type);hlist_for_each_entry_rcu (event, head, hlist_entry) {
@@ -8996,6 +8999,8 @@ void perf_tp_event(u16 event_type, u64 c }perf_swevent_put_recursion_context (rctx); + +trace_rcu_exit (rcu_flags); }EXPORT_SYMBOL_GPL (perf_tp_event);
Peter Zijlstra
maintainerPATCH v3 12/22 tracing: Employ trace_rcu_{enter,exit}()
In reply to Peter ZijlstraReplace the opencoded (and incomplete) RCU manipulations with the new helpers to ensure a regular RCU context when calling into __ftrace_trace_stack().
--- kernel/trace/trace.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-)
kernel/trace/trace.c +3 -16
@@ -2989,24 +2989,11 @@ void __trace_stack(struct trace_array *t int pc) {struct trace_buffer *buffer = tr->array_buffer.buffer; +unsigned long rcu_flags; -if (rcu_is_watching ()) { -__ftrace_trace_stack (buffer, flags, skip, pc,NULL ); -return ; - } - -/* -* When an NMI triggers, RCU is enabled via rcu_nmi_enter(), -* but if the above rcu_is_watching() failed, then the NMI -* triggered someplace critical, and rcu_irq_enter() should -* not be called from NMI. -*/ -if (unlikely (in_nmi ())) -return ; - -rcu_irq_enter_irqsave (); + rcu_flags =trace_rcu_enter ();__ftrace_trace_stack (buffer, flags, skip, pc,NULL ); -rcu_irq_exit_irqsave (); +trace_rcu_exit (rcu_flags); }/**
Re: [PATCH v3 12/22] tracing: Employ trace_rcu_{enter,exit}()
Quoted 6 lines · On Wed, 19 Feb 2020 15:47:36 +0100 Peter Zijlstra <[email protected]> wrote:
Replace the opencoded (and incomplete) RCU manipulations with the new helpers to ensure a regular RCU context when calling into
__ftrace_trace_stack().Signed-off-by Peter Zijlstra (Intel) <[email protected]>---
-- Steve
Peter Zijlstra
maintainerPATCH v3 13/22 tracing: Remove regular RCU context for _rcuidle tracepoints (again)
In reply to Peter ZijlstraEffectively revert commit 865e63b04e9b2 ("tracing: Add back in rcu_irq_enter/exit_irqson() for rcuidle tracepoints") now that we've taught perf how to deal with not having an RCU context provided.
--- include/linux/tracepoint.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
include/linux/tracepoint.h +2 -6
@@ -179,10 +179,8 @@ static inline struct tracepoint *tracepo* For rcuidle callers, use srcu since sched-rcu \ * doesn't work from the idle path. \ */ \ -if (rcuidle) { \ +if (rcuidle) \ __idx =srcu_read_lock_notrace (&tracepoint_srcu);\ -rcu_irq_enter_irqsave (); \ - } \ \ it_func_ptr =rcu_dereference_raw ((tp)->funcs); \ \
@@ -194,10 +192,8 @@ static inline struct tracepoint *tracepo }while ((++it_func_ptr)->func); \ } \ \ -if (rcuidle) { \ -rcu_irq_exit_irqsave (); \ +if (rcuidle) \srcu_read_unlock_notrace (&tracepoint_srcu, __idx);\ - } \ \preempt_enable_notrace (); \ }while (0 )
Re: [PATCH v3 13/22] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 6 lines · On Wed, 19 Feb 2020 15:47:37 +0100 Peter Zijlstra <[email protected]> wrote:
Effectively revert commit
865e63b04e9b2("tracing: Add back in rcu_irq_enter/exit_irqson() for rcuidle tracepoints") now that we've taught perf how to deal with not having an RCU context provided.Signed-off-by Peter Zijlstra (Intel) <[email protected]>---
-- Steve
Paul E. McKenney
maintainerRe: [PATCH v3 13/22] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
In reply to Peter Zijlstrainclude/linux/tracepoint.h static inline struct tracepoint *tracepo
Quoted 12 lines · Peter Zijlstra
Effectively revert commit
865e63b04e9b2("tracing: Add back in rcu_irq_enter/exit_irqson() for rcuidle tracepoints") now that we've taught perf how to deal with not having an RCU context provided.Signed-off-by Peter Zijlstra (Intel) <[email protected]>--- include/linux/tracepoint.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)include/linux/tracepoint.h +0
-0@@ -179,10 +179,8 @@ static inline struct tracepoint *tracepo
Shouldn't we also get rid of this line above?
int __maybe_unused __idx = 0; \ Thanx, Paul
Quoted 25 lines
include/linux/tracepoint.h +2
-6* For rcuidle callers, use srcu since sched-rcu \ * doesn't work from the idle path. \ */ \ -if (rcuidle) { \ +if (rcuidle) \ __idx =srcu_read_lock_notrace (&tracepoint_srcu);\ -rcu_irq_enter_irqsave (); \ - } \ \ it_func_ptr =rcu_dereference_raw ((tp)->funcs); \ \@@ -194,10 +192,8 @@ static inline struct tracepoint *tracepo }while ((++it_func_ptr)->func); \ } \ \ -if (rcuidle) { \ -rcu_irq_exit_irqsave (); \ +if (rcuidle) \srcu_read_unlock_notrace (&tracepoint_srcu, __idx);\ - } \ \preempt_enable_notrace (); \ }while (0 )
Peter Zijlstra
maintainerRe: [PATCH v3 13/22] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 10 lines · Paul E. McKenney
Quoted 9 lines · Peter Zijlstra
Effectively revert commit
865e63b04e9b2("tracing: Add back in rcu_irq_enter/exit_irqson() for rcuidle tracepoints") now that we've taught perf how to deal with not having an RCU context provided.Signed-off-by Peter Zijlstra (Intel) <[email protected]>--- include/linux/tracepoint.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
Quoted 8 lines
include/linux/tracepoint.h static inline struct tracepoint *tracepo
Quoted 3 lines
include/linux/tracepoint.h +0
-0@@ -179,10 +179,8 @@ static inline struct tracepoint *tracepoShouldn't we also get rid of this line above?
int __maybe_unused __idx = 0; \
Probably makes a lot of sense, lemme fix that!
Peter Zijlstra
maintainerRe: [PATCH v3 13/22] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 17 lines · Peter Zijlstra
Quoted 16 lines · Paul E. McKenney
include/linux/tracepoint.h static inline struct tracepoint *tracepo
Quoted 12 lines · Peter Zijlstra
Effectively revert commit
865e63b04e9b2("tracing: Add back in rcu_irq_enter/exit_irqson() for rcuidle tracepoints") now that we've taught perf how to deal with not having an RCU context provided.Signed-off-by Peter Zijlstra (Intel) <[email protected]>--- include/linux/tracepoint.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)include/linux/tracepoint.h +0
-0@@ -179,10 +179,8 @@ static inline struct tracepoint *tracepoShouldn't we also get rid of this line above?
Quoted 4 lines
Quoted 2 lines
int __maybe_unused __idx = 0; \Probably makes a lot of sense, lemme fix that!
Oh wait, no! SRCU is the one that remains !
Steven Rostedt
maintainerRe: [PATCH v3 13/22] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 18 lines · On Wed, 19 Feb 2020 18:05:07 +0100 Peter Zijlstra <[email protected]> wrote:
Quoted 17 lines · Peter Zijlstra
Quoted 16 lines · Paul E. McKenney
include/linux/tracepoint.h static inline struct tracepoint *tracepo
Quoted 12 lines · Peter Zijlstra
Effectively revert commit
865e63b04e9b2("tracing: Add back in rcu_irq_enter/exit_irqson() for rcuidle tracepoints") now that we've taught perf how to deal with not having an RCU context provided.Signed-off-by Peter Zijlstra (Intel) <[email protected]>--- include/linux/tracepoint.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)include/linux/tracepoint.h +0
-0@@ -179,10 +179,8 @@ static inline struct tracepoint *tracepoShouldn't we also get rid of this line above?
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
int __maybe_unused __idx = 0; \Probably makes a lot of sense, lemme fix that!
Oh wait, no! SRCU is the one that remains !
Correct, and if rcuidle is not set, and this is a macro, the SRCU portion is compiled out.
-- Steve
Paul E. McKenney
maintainerRe: [PATCH v3 13/22] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 24 lines · Steven Rostedt
Quoted 21 lines · On Wed, 19 Feb 2020 18:05:07 +0100 Peter Zijlstra <[email protected]> wrote:
Quoted 20 lines · Peter Zijlstra
Quoted 18 lines · Paul E. McKenney
include/linux/tracepoint.h static inline struct tracepoint *tracepo
Quoted 12 lines · Peter Zijlstra
Effectively revert commit
865e63b04e9b2("tracing: Add back in rcu_irq_enter/exit_irqson() for rcuidle tracepoints") now that we've taught perf how to deal with not having an RCU context provided.Signed-off-by Peter Zijlstra (Intel) <[email protected]>--- include/linux/tracepoint.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)include/linux/tracepoint.h +0
-0@@ -179,10 +179,8 @@ static inline struct tracepoint *tracepoShouldn't we also get rid of this line above?
int __maybe_unused __idx = 0; \
Quoted 6 lines
Quoted 3 lines
Quoted 1 line
Probably makes a lot of sense, lemme fix that!
Oh wait, no! SRCU is the one that remains !
Correct, and if rcuidle is not set, and this is a macro, the SRCU portion is compiled out.
Sigh! Apologies for the noise!
If we are using SRCU, we don't care whether or not RCU is watching. OK, maybe finally catching up -- the whole point was use of RCU in other tracing code, wasn't it?
Thanx, Paul
Steven Rostedt
maintainerRe: [PATCH v3 13/22] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 8 lines · On Wed, 19 Feb 2020 09:40:25 -0800 "Paul E. McKenney" <[email protected]>…
Quoted 2 lines
Correct, and if rcuidle is not set, and this is a macro, the SRCU portion is compiled out.
Sigh! Apologies for the noise!
If we are using SRCU, we don't care whether or not RCU is watching. OK, maybe finally catching up -- the whole point was use of RCU in other tracing code, wasn't it?
Some callbacks (namely perf) might use RCU, but then the callbacks need to make sure rcu is watching.
-- Steve
Paul E. McKenney
maintainerRe: [PATCH v3 13/22] tracing: Remove regular RCU context for _rcuidle tracepoints (again)
Quoted 6 lines · Steven Rostedt
Quoted 3 lines · On Wed, 19 Feb 2020 09:40:25 -0800 "Paul E. McKenney" <[email protected]>…
Quoted 2 lines
Correct, and if rcuidle is not set, and this is a macro, the SRCU portion is compiled out.
Quoted 8 lines
Quoted 5 lines
Sigh! Apologies for the noise!
If we are using SRCU, we don't care whether or not RCU is watching. OK, maybe finally catching up -- the whole point was use of RCU in other tracing code, wasn't it?
Some callbacks (namely perf) might use RCU, but then the callbacks need to make sure rcu is watching.
Got it, thank you!
Thanx, Paul
Peter Zijlstra
maintainerPATCH v3 14/22 perf,tracing: Allow function tracing when !RCU
In reply to Peter ZijlstraSince perf is now able to deal with !rcu_is_watching() contexts, remove the restraint.
--- kernel/trace/trace_event_perf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/trace/trace_event_perf.c +1 -1
@@ -477,7 +477,7 @@ static int perf_ftrace_function_register {struct ftrace_ops *ops = &event->ftrace_ops; - ops->flags =FTRACE_OPS_FL_RCU ; + ops->flags =0 ; ops->func = perf_ftrace_function_call; ops->private = (void *)(unsigned long )nr_cpu_ids;
Peter Zijlstra
maintainerPATCH v3 15/22 x86/int3: Ensure that poke_int3_handler() is not traced
In reply to Peter ZijlstraFrom: Thomas Gleixner <[email protected]>
In order to ensure poke_int3_handler() is completely self contained -- we call this while we're modifying other text, imagine the fun of hitting another INT3 -- ensure that everything it uses is not traced.
The primary means here is to force inlining; bsearch() is notrace because all of lib/ is.
--- arch/x86/include/asm/ptrace.h | 2 +- arch/x86/include/asm/text-patching.h | 11 +++++++---- arch/x86/kernel/alternative.c | 11 +++++++---- 3 files changed, 15 insertions(+), 9 deletions(-)
arch/x86/include/asm/ptrace.h +1 -1
@@ -123,7 +123,7 @@ static inline void regs_set_return_value* On x86_64, vm86 mode is mercifully nonexistent, and we don't need * the extra check. */ -static inline int user_mode (struct pt_regs *regs) +static __always_inline int user_mode(struct pt_regs *regs) {#ifdef CONFIG_X86_32 return ((regs->cs &SEGMENT_RPL_MASK ) | (regs->flags &X86_VM_MASK )) >=USER_RPL ;
arch/x86/include/asm/text-patching.h +7 -4
@@ -64,7 +64,7 @@ extern void text_poke_finish(void);#define DISP32_SIZE 4 -static inline int text_opcode_size (u8 opcode) +static __always_inline int text_opcode_size(u8 opcode) {int size =0 ;
@@ -118,12 +118,14 @@ extern __ro_after_init struct mm_structextern __ro_after_init unsigned long poking_addr;#ifndef CONFIG_UML_X86 -static inline void int3_emulate_jmp (struct pt_regs *regs,unsigned long ip) +static __always_inline +void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip) { regs->ip = ip; } -static inline void int3_emulate_push (struct pt_regs *regs,unsigned long val) +static __always_inline +void int3_emulate_push(struct pt_regs *regs, unsigned long val) {/* * The int3 handler in entry_64.S adds a gap between the
@@ -138,7 +140,8 @@ static inline void int3_emulate_push(str *(unsigned long *)regs->sp = val; } -static inline void int3_emulate_call (struct pt_regs *regs,unsigned long func) +static __always_inline +void int3_emulate_call(struct pt_regs *regs, unsigned long func) {int3_emulate_push (regs, regs->ip -INT3_INSN_SIZE +CALL_INSN_SIZE );int3_emulate_jmp (regs, func);
arch/x86/kernel/alternative.c +4 -3
@@ -956,7 +956,8 @@ struct bp_patching_desc {static struct bp_patching_desc *bp_desc; -static inline struct bp_patching_desc *try_get_desc (struct bp_patching_desc **descp) +static __always_inline +struct bp_patching_desc *try_get_desc(struct bp_patching_desc **descp) {struct bp_patching_desc *desc =READ_ONCE (*descp);/* rcu_dereference */
@@ -966,13 +967,13 @@ static inline struct bp_patching_desc *treturn desc; } -static inline void put_desc (struct bp_patching_desc *desc) +static __always_inline void put_desc(struct bp_patching_desc *desc) {smp_mb__before_atomic ();atomic_dec (&desc->refs); } -static inline void *text_poke_addr (struct text_poke_loc *tp) +static __always_inline void *text_poke_addr(struct text_poke_loc *tp) {return _stext + tp->rel_addr; }
Peter Zijlstra
maintainerPATCH v3 16/22 locking/atomics, kcsan: Add KCSAN instrumentation
In reply to Peter ZijlstraFrom: Marco Elver <[email protected]>
This adds KCSAN instrumentation to atomic-instrumented.h.
--- include/asm-generic/atomic-instrumented.h | 390 +++++++++++++++--------------- scripts/atomic/gen-atomic-instrumented.sh | 14 - 2 files changed, 212 insertions(+), 192 deletions(-)
include/asm-generic/atomic-instrumented.h +200 -190
@@ -20,10 +20,20 @@#include <linux/build_bug.h> #include <linux/kasan-checks.h> +static inline void __atomic_check_read (const volatile void *v,size_t size) +{ +kasan_check_read (v, size); +} + +static inline void __atomic_check_write (const volatile void *v,size_t size) +{ +kasan_check_write (v, size); +} +static inline int atomic_read (const atomic_t *v) { -kasan_check_read (v,sizeof (*v)); +__atomic_check_read (v,sizeof (*v));return arch_atomic_read (v); }#define atomic_read atomic_read
@@ -32,7 +42,7 @@ atomic_read(const atomic_t *v)static inline int atomic_read_acquire (const atomic_t *v) { -kasan_check_read (v,sizeof (*v)); +__atomic_check_read (v,sizeof (*v));return arch_atomic_read_acquire (v); }#define atomic_read_acquire atomic_read_acquire
@@ -41,7 +51,7 @@ atomic_read_acquire(const atomic_t *v)static inline void atomic_set (atomic_t *v,int i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_set (v, i); }#define atomic_set atomic_set
@@ -50,7 +60,7 @@ atomic_set(atomic_t *v, int i)static inline void atomic_set_release (atomic_t *v,int i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_set_release (v, i); }#define atomic_set_release atomic_set_release
@@ -59,7 +69,7 @@ atomic_set_release(atomic_t *v, int i)static inline void atomic_add (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_add (i, v); }#define atomic_add atomic_add
@@ -68,7 +78,7 @@ atomic_add(int i, atomic_t *v)static inline int atomic_add_return (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_add_return (i, v); }#define atomic_add_return atomic_add_return
@@ -78,7 +88,7 @@ atomic_add_return(int i, atomic_t *v)static inline int atomic_add_return_acquire (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_add_return_acquire (i, v); }#define atomic_add_return_acquire atomic_add_return_acquire
@@ -88,7 +98,7 @@ atomic_add_return_acquire(int i, atomic_static inline int atomic_add_return_release (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_add_return_release (i, v); }#define atomic_add_return_release atomic_add_return_release
@@ -98,7 +108,7 @@ atomic_add_return_release(int i, atomic_static inline int atomic_add_return_relaxed (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_add_return_relaxed (i, v); }#define atomic_add_return_relaxed atomic_add_return_relaxed
@@ -108,7 +118,7 @@ atomic_add_return_relaxed(int i, atomic_static inline int atomic_fetch_add (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_add (i, v); }#define atomic_fetch_add atomic_fetch_add
@@ -118,7 +128,7 @@ atomic_fetch_add(int i, atomic_t *v)static inline int atomic_fetch_add_acquire (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_add_acquire (i, v); }#define atomic_fetch_add_acquire atomic_fetch_add_acquire
@@ -128,7 +138,7 @@ atomic_fetch_add_acquire(int i, atomic_tstatic inline int atomic_fetch_add_release (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_add_release (i, v); }#define atomic_fetch_add_release atomic_fetch_add_release
@@ -138,7 +148,7 @@ atomic_fetch_add_release(int i, atomic_tstatic inline int atomic_fetch_add_relaxed (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_add_relaxed (i, v); }#define atomic_fetch_add_relaxed atomic_fetch_add_relaxed
@@ -147,7 +157,7 @@ atomic_fetch_add_relaxed(int i, atomic_tstatic inline void atomic_sub (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_sub (i, v); }#define atomic_sub atomic_sub
@@ -156,7 +166,7 @@ atomic_sub(int i, atomic_t *v)static inline int atomic_sub_return (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_sub_return (i, v); }#define atomic_sub_return atomic_sub_return
@@ -166,7 +176,7 @@ atomic_sub_return(int i, atomic_t *v)static inline int atomic_sub_return_acquire (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_sub_return_acquire (i, v); }#define atomic_sub_return_acquire atomic_sub_return_acquire
@@ -176,7 +186,7 @@ atomic_sub_return_acquire(int i, atomic_static inline int atomic_sub_return_release (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_sub_return_release (i, v); }#define atomic_sub_return_release atomic_sub_return_release
@@ -186,7 +196,7 @@ atomic_sub_return_release(int i, atomic_static inline int atomic_sub_return_relaxed (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_sub_return_relaxed (i, v); }#define atomic_sub_return_relaxed atomic_sub_return_relaxed
@@ -196,7 +206,7 @@ atomic_sub_return_relaxed(int i, atomic_static inline int atomic_fetch_sub (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_sub (i, v); }#define atomic_fetch_sub atomic_fetch_sub
@@ -206,7 +216,7 @@ atomic_fetch_sub(int i, atomic_t *v)static inline int atomic_fetch_sub_acquire (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_sub_acquire (i, v); }#define atomic_fetch_sub_acquire atomic_fetch_sub_acquire
@@ -216,7 +226,7 @@ atomic_fetch_sub_acquire(int i, atomic_tstatic inline int atomic_fetch_sub_release (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_sub_release (i, v); }#define atomic_fetch_sub_release atomic_fetch_sub_release
@@ -226,7 +236,7 @@ atomic_fetch_sub_release(int i, atomic_tstatic inline int atomic_fetch_sub_relaxed (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_sub_relaxed (i, v); }#define atomic_fetch_sub_relaxed atomic_fetch_sub_relaxed
@@ -236,7 +246,7 @@ atomic_fetch_sub_relaxed(int i, atomic_tstatic inline void atomic_inc (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_inc (v); }#define atomic_inc atomic_inc
@@ -246,7 +256,7 @@ atomic_inc(atomic_t *v)static inline int atomic_inc_return (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_inc_return (v); }#define atomic_inc_return atomic_inc_return
@@ -256,7 +266,7 @@ atomic_inc_return(atomic_t *v)static inline int atomic_inc_return_acquire (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_inc_return_acquire (v); }#define atomic_inc_return_acquire atomic_inc_return_acquire
@@ -266,7 +276,7 @@ atomic_inc_return_acquire(atomic_t *v)static inline int atomic_inc_return_release (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_inc_return_release (v); }#define atomic_inc_return_release atomic_inc_return_release
@@ -276,7 +286,7 @@ atomic_inc_return_release(atomic_t *v)static inline int atomic_inc_return_relaxed (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_inc_return_relaxed (v); }#define atomic_inc_return_relaxed atomic_inc_return_relaxed
@@ -286,7 +296,7 @@ atomic_inc_return_relaxed(atomic_t *v)static inline int atomic_fetch_inc (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_inc (v); }#define atomic_fetch_inc atomic_fetch_inc
@@ -296,7 +306,7 @@ atomic_fetch_inc(atomic_t *v)static inline int atomic_fetch_inc_acquire (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_inc_acquire (v); }#define atomic_fetch_inc_acquire atomic_fetch_inc_acquire
@@ -306,7 +316,7 @@ atomic_fetch_inc_acquire(atomic_t *v)static inline int atomic_fetch_inc_release (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_inc_release (v); }#define atomic_fetch_inc_release atomic_fetch_inc_release
@@ -316,7 +326,7 @@ atomic_fetch_inc_release(atomic_t *v)static inline int atomic_fetch_inc_relaxed (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_inc_relaxed (v); }#define atomic_fetch_inc_relaxed atomic_fetch_inc_relaxed
@@ -326,7 +336,7 @@ atomic_fetch_inc_relaxed(atomic_t *v)static inline void atomic_dec (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_dec (v); }#define atomic_dec atomic_dec
@@ -336,7 +346,7 @@ atomic_dec(atomic_t *v)static inline int atomic_dec_return (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_dec_return (v); }#define atomic_dec_return atomic_dec_return
@@ -346,7 +356,7 @@ atomic_dec_return(atomic_t *v)static inline int atomic_dec_return_acquire (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_dec_return_acquire (v); }#define atomic_dec_return_acquire atomic_dec_return_acquire
@@ -356,7 +366,7 @@ atomic_dec_return_acquire(atomic_t *v)static inline int atomic_dec_return_release (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_dec_return_release (v); }#define atomic_dec_return_release atomic_dec_return_release
@@ -366,7 +376,7 @@ atomic_dec_return_release(atomic_t *v)static inline int atomic_dec_return_relaxed (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_dec_return_relaxed (v); }#define atomic_dec_return_relaxed atomic_dec_return_relaxed
@@ -376,7 +386,7 @@ atomic_dec_return_relaxed(atomic_t *v)static inline int atomic_fetch_dec (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_dec (v); }#define atomic_fetch_dec atomic_fetch_dec
@@ -386,7 +396,7 @@ atomic_fetch_dec(atomic_t *v)static inline int atomic_fetch_dec_acquire (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_dec_acquire (v); }#define atomic_fetch_dec_acquire atomic_fetch_dec_acquire
@@ -396,7 +406,7 @@ atomic_fetch_dec_acquire(atomic_t *v)static inline int atomic_fetch_dec_release (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_dec_release (v); }#define atomic_fetch_dec_release atomic_fetch_dec_release
@@ -406,7 +416,7 @@ atomic_fetch_dec_release(atomic_t *v)static inline int atomic_fetch_dec_relaxed (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_dec_relaxed (v); }#define atomic_fetch_dec_relaxed atomic_fetch_dec_relaxed
@@ -415,7 +425,7 @@ atomic_fetch_dec_relaxed(atomic_t *v)static inline void atomic_and (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_and (i, v); }#define atomic_and atomic_and
@@ -424,7 +434,7 @@ atomic_and(int i, atomic_t *v)static inline int atomic_fetch_and (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_and (i, v); }#define atomic_fetch_and atomic_fetch_and
@@ -434,7 +444,7 @@ atomic_fetch_and(int i, atomic_t *v)static inline int atomic_fetch_and_acquire (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_and_acquire (i, v); }#define atomic_fetch_and_acquire atomic_fetch_and_acquire
@@ -444,7 +454,7 @@ atomic_fetch_and_acquire(int i, atomic_tstatic inline int atomic_fetch_and_release (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_and_release (i, v); }#define atomic_fetch_and_release atomic_fetch_and_release
@@ -454,7 +464,7 @@ atomic_fetch_and_release(int i, atomic_tstatic inline int atomic_fetch_and_relaxed (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_and_relaxed (i, v); }#define atomic_fetch_and_relaxed atomic_fetch_and_relaxed
@@ -464,7 +474,7 @@ atomic_fetch_and_relaxed(int i, atomic_tstatic inline void atomic_andnot (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_andnot (i, v); }#define atomic_andnot atomic_andnot
@@ -474,7 +484,7 @@ atomic_andnot(int i, atomic_t *v)static inline int atomic_fetch_andnot (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_andnot (i, v); }#define atomic_fetch_andnot atomic_fetch_andnot
@@ -484,7 +494,7 @@ atomic_fetch_andnot(int i, atomic_t *v)static inline int atomic_fetch_andnot_acquire (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_andnot_acquire (i, v); }#define atomic_fetch_andnot_acquire atomic_fetch_andnot_acquire
@@ -494,7 +504,7 @@ atomic_fetch_andnot_acquire(int i, atomistatic inline int atomic_fetch_andnot_release (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_andnot_release (i, v); }#define atomic_fetch_andnot_release atomic_fetch_andnot_release
@@ -504,7 +514,7 @@ atomic_fetch_andnot_release(int i, atomistatic inline int atomic_fetch_andnot_relaxed (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_andnot_relaxed (i, v); }#define atomic_fetch_andnot_relaxed atomic_fetch_andnot_relaxed
@@ -513,7 +523,7 @@ atomic_fetch_andnot_relaxed(int i, atomistatic inline void atomic_or (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_or (i, v); }#define atomic_or atomic_or
@@ -522,7 +532,7 @@ atomic_or(int i, atomic_t *v)static inline int atomic_fetch_or (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_or (i, v); }#define atomic_fetch_or atomic_fetch_or
@@ -532,7 +542,7 @@ atomic_fetch_or(int i, atomic_t *v)static inline int atomic_fetch_or_acquire (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_or_acquire (i, v); }#define atomic_fetch_or_acquire atomic_fetch_or_acquire
@@ -542,7 +552,7 @@ atomic_fetch_or_acquire(int i, atomic_tstatic inline int atomic_fetch_or_release (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_or_release (i, v); }#define atomic_fetch_or_release atomic_fetch_or_release
@@ -552,7 +562,7 @@ atomic_fetch_or_release(int i, atomic_tstatic inline int atomic_fetch_or_relaxed (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_or_relaxed (i, v); }#define atomic_fetch_or_relaxed atomic_fetch_or_relaxed
@@ -561,7 +571,7 @@ atomic_fetch_or_relaxed(int i, atomic_tstatic inline void atomic_xor (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic_xor (i, v); }#define atomic_xor atomic_xor
@@ -570,7 +580,7 @@ atomic_xor(int i, atomic_t *v)static inline int atomic_fetch_xor (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_xor (i, v); }#define atomic_fetch_xor atomic_fetch_xor
@@ -580,7 +590,7 @@ atomic_fetch_xor(int i, atomic_t *v)static inline int atomic_fetch_xor_acquire (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_xor_acquire (i, v); }#define atomic_fetch_xor_acquire atomic_fetch_xor_acquire
@@ -590,7 +600,7 @@ atomic_fetch_xor_acquire(int i, atomic_tstatic inline int atomic_fetch_xor_release (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_xor_release (i, v); }#define atomic_fetch_xor_release atomic_fetch_xor_release
@@ -600,7 +610,7 @@ atomic_fetch_xor_release(int i, atomic_tstatic inline int atomic_fetch_xor_relaxed (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_xor_relaxed (i, v); }#define atomic_fetch_xor_relaxed atomic_fetch_xor_relaxed
@@ -610,7 +620,7 @@ atomic_fetch_xor_relaxed(int i, atomic_tstatic inline int atomic_xchg (atomic_t *v,int i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_xchg (v, i); }#define atomic_xchg atomic_xchg
@@ -620,7 +630,7 @@ atomic_xchg(atomic_t *v, int i)static inline int atomic_xchg_acquire (atomic_t *v,int i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_xchg_acquire (v, i); }#define atomic_xchg_acquire atomic_xchg_acquire
@@ -630,7 +640,7 @@ atomic_xchg_acquire(atomic_t *v, int i)static inline int atomic_xchg_release (atomic_t *v,int i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_xchg_release (v, i); }#define atomic_xchg_release atomic_xchg_release
@@ -640,7 +650,7 @@ atomic_xchg_release(atomic_t *v, int i)static inline int atomic_xchg_relaxed (atomic_t *v,int i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_xchg_relaxed (v, i); }#define atomic_xchg_relaxed atomic_xchg_relaxed
@@ -650,7 +660,7 @@ atomic_xchg_relaxed(atomic_t *v, int i)static inline int atomic_cmpxchg (atomic_t *v,int old,int new) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_cmpxchg (v, old, new); }#define atomic_cmpxchg atomic_cmpxchg
@@ -660,7 +670,7 @@ atomic_cmpxchg(atomic_t *v, int old, intstatic inline int atomic_cmpxchg_acquire (atomic_t *v,int old,int new) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_cmpxchg_acquire (v, old, new); }#define atomic_cmpxchg_acquire atomic_cmpxchg_acquire
@@ -670,7 +680,7 @@ atomic_cmpxchg_acquire(atomic_t *v, intstatic inline int atomic_cmpxchg_release (atomic_t *v,int old,int new) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_cmpxchg_release (v, old, new); }#define atomic_cmpxchg_release atomic_cmpxchg_release
@@ -680,7 +690,7 @@ atomic_cmpxchg_release(atomic_t *v, intstatic inline int atomic_cmpxchg_relaxed (atomic_t *v,int old,int new) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_cmpxchg_relaxed (v, old, new); }#define atomic_cmpxchg_relaxed atomic_cmpxchg_relaxed
@@ -690,8 +700,8 @@ atomic_cmpxchg_relaxed(atomic_t *v, intstatic inline bool atomic_try_cmpxchg (atomic_t *v,int *old,int new) { -kasan_check_write (v,sizeof (*v)); -kasan_check_write (old,sizeof (*old)); +__atomic_check_write (v,sizeof (*v)); +__atomic_check_write (old,sizeof (*old));return arch_atomic_try_cmpxchg (v, old, new); }#define atomic_try_cmpxchg atomic_try_cmpxchg
@@ -701,8 +711,8 @@ atomic_try_cmpxchg(atomic_t *v, int *oldstatic inline bool atomic_try_cmpxchg_acquire (atomic_t *v,int *old,int new) { -kasan_check_write (v,sizeof (*v)); -kasan_check_write (old,sizeof (*old)); +__atomic_check_write (v,sizeof (*v)); +__atomic_check_write (old,sizeof (*old));return arch_atomic_try_cmpxchg_acquire (v, old, new); }#define atomic_try_cmpxchg_acquire atomic_try_cmpxchg_acquire
@@ -712,8 +722,8 @@ atomic_try_cmpxchg_acquire(atomic_t *v,static inline bool atomic_try_cmpxchg_release (atomic_t *v,int *old,int new) { -kasan_check_write (v,sizeof (*v)); -kasan_check_write (old,sizeof (*old)); +__atomic_check_write (v,sizeof (*v)); +__atomic_check_write (old,sizeof (*old));return arch_atomic_try_cmpxchg_release (v, old, new); }#define atomic_try_cmpxchg_release atomic_try_cmpxchg_release
@@ -723,8 +733,8 @@ atomic_try_cmpxchg_release(atomic_t *v,static inline bool atomic_try_cmpxchg_relaxed (atomic_t *v,int *old,int new) { -kasan_check_write (v,sizeof (*v)); -kasan_check_write (old,sizeof (*old)); +__atomic_check_write (v,sizeof (*v)); +__atomic_check_write (old,sizeof (*old));return arch_atomic_try_cmpxchg_relaxed (v, old, new); }#define atomic_try_cmpxchg_relaxed atomic_try_cmpxchg_relaxed
@@ -734,7 +744,7 @@ atomic_try_cmpxchg_relaxed(atomic_t *v,static inline bool atomic_sub_and_test (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_sub_and_test (i, v); }#define atomic_sub_and_test atomic_sub_and_test
@@ -744,7 +754,7 @@ atomic_sub_and_test(int i, atomic_t *v)static inline bool atomic_dec_and_test (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_dec_and_test (v); }#define atomic_dec_and_test atomic_dec_and_test
@@ -754,7 +764,7 @@ atomic_dec_and_test(atomic_t *v)static inline bool atomic_inc_and_test (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_inc_and_test (v); }#define atomic_inc_and_test atomic_inc_and_test
@@ -764,7 +774,7 @@ atomic_inc_and_test(atomic_t *v)static inline bool atomic_add_negative (int i,atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_add_negative (i, v); }#define atomic_add_negative atomic_add_negative
@@ -774,7 +784,7 @@ atomic_add_negative(int i, atomic_t *v)static inline int atomic_fetch_add_unless (atomic_t *v,int a,int u) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_fetch_add_unless (v, a, u); }#define atomic_fetch_add_unless atomic_fetch_add_unless
@@ -784,7 +794,7 @@ atomic_fetch_add_unless(atomic_t *v, intstatic inline bool atomic_add_unless (atomic_t *v,int a,int u) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_add_unless (v, a, u); }#define atomic_add_unless atomic_add_unless
@@ -794,7 +804,7 @@ atomic_add_unless(atomic_t *v, int a, instatic inline bool atomic_inc_not_zero (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_inc_not_zero (v); }#define atomic_inc_not_zero atomic_inc_not_zero
@@ -804,7 +814,7 @@ atomic_inc_not_zero(atomic_t *v)static inline bool atomic_inc_unless_negative (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_inc_unless_negative (v); }#define atomic_inc_unless_negative atomic_inc_unless_negative
@@ -814,7 +824,7 @@ atomic_inc_unless_negative(atomic_t *v)static inline bool atomic_dec_unless_positive (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_dec_unless_positive (v); }#define atomic_dec_unless_positive atomic_dec_unless_positive
@@ -824,7 +834,7 @@ atomic_dec_unless_positive(atomic_t *v)static inline int atomic_dec_if_positive (atomic_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic_dec_if_positive (v); }#define atomic_dec_if_positive atomic_dec_if_positive
@@ -833,7 +843,7 @@ atomic_dec_if_positive(atomic_t *v)static inline s64 atomic64_read (const atomic64_t *v) { -kasan_check_read (v,sizeof (*v)); +__atomic_check_read (v,sizeof (*v));return arch_atomic64_read (v); }#define atomic64_read atomic64_read
@@ -842,7 +852,7 @@ atomic64_read(const atomic64_t *v)static inline s64 atomic64_read_acquire (const atomic64_t *v) { -kasan_check_read (v,sizeof (*v)); +__atomic_check_read (v,sizeof (*v));return arch_atomic64_read_acquire (v); }#define atomic64_read_acquire atomic64_read_acquire
@@ -851,7 +861,7 @@ atomic64_read_acquire(const atomic64_t *static inline void atomic64_set (atomic64_t *v,s64 i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_set (v, i); }#define atomic64_set atomic64_set
@@ -860,7 +870,7 @@ atomic64_set(atomic64_t *v, s64 i)static inline void atomic64_set_release (atomic64_t *v,s64 i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_set_release (v, i); }#define atomic64_set_release atomic64_set_release
@@ -869,7 +879,7 @@ atomic64_set_release(atomic64_t *v, s64static inline void atomic64_add (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_add (i, v); }#define atomic64_add atomic64_add
@@ -878,7 +888,7 @@ atomic64_add(s64 i, atomic64_t *v)static inline s64 atomic64_add_return (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_add_return (i, v); }#define atomic64_add_return atomic64_add_return
@@ -888,7 +898,7 @@ atomic64_add_return(s64 i, atomic64_t *vstatic inline s64 atomic64_add_return_acquire (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_add_return_acquire (i, v); }#define atomic64_add_return_acquire atomic64_add_return_acquire
@@ -898,7 +908,7 @@ atomic64_add_return_acquire(s64 i, atomistatic inline s64 atomic64_add_return_release (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_add_return_release (i, v); }#define atomic64_add_return_release atomic64_add_return_release
@@ -908,7 +918,7 @@ atomic64_add_return_release(s64 i, atomistatic inline s64 atomic64_add_return_relaxed (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_add_return_relaxed (i, v); }#define atomic64_add_return_relaxed atomic64_add_return_relaxed
@@ -918,7 +928,7 @@ atomic64_add_return_relaxed(s64 i, atomistatic inline s64 atomic64_fetch_add (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_add (i, v); }#define atomic64_fetch_add atomic64_fetch_add
@@ -928,7 +938,7 @@ atomic64_fetch_add(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_add_acquire (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_add_acquire (i, v); }#define atomic64_fetch_add_acquire atomic64_fetch_add_acquire
@@ -938,7 +948,7 @@ atomic64_fetch_add_acquire(s64 i, atomicstatic inline s64 atomic64_fetch_add_release (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_add_release (i, v); }#define atomic64_fetch_add_release atomic64_fetch_add_release
@@ -948,7 +958,7 @@ atomic64_fetch_add_release(s64 i, atomicstatic inline s64 atomic64_fetch_add_relaxed (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_add_relaxed (i, v); }#define atomic64_fetch_add_relaxed atomic64_fetch_add_relaxed
@@ -957,7 +967,7 @@ atomic64_fetch_add_relaxed(s64 i, atomicstatic inline void atomic64_sub (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_sub (i, v); }#define atomic64_sub atomic64_sub
@@ -966,7 +976,7 @@ atomic64_sub(s64 i, atomic64_t *v)static inline s64 atomic64_sub_return (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_sub_return (i, v); }#define atomic64_sub_return atomic64_sub_return
@@ -976,7 +986,7 @@ atomic64_sub_return(s64 i, atomic64_t *vstatic inline s64 atomic64_sub_return_acquire (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_sub_return_acquire (i, v); }#define atomic64_sub_return_acquire atomic64_sub_return_acquire
@@ -986,7 +996,7 @@ atomic64_sub_return_acquire(s64 i, atomistatic inline s64 atomic64_sub_return_release (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_sub_return_release (i, v); }#define atomic64_sub_return_release atomic64_sub_return_release
@@ -996,7 +1006,7 @@ atomic64_sub_return_release(s64 i, atomistatic inline s64 atomic64_sub_return_relaxed (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_sub_return_relaxed (i, v); }#define atomic64_sub_return_relaxed atomic64_sub_return_relaxed
@@ -1006,7 +1016,7 @@ atomic64_sub_return_relaxed(s64 i, atomistatic inline s64 atomic64_fetch_sub (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_sub (i, v); }#define atomic64_fetch_sub atomic64_fetch_sub
@@ -1016,7 +1026,7 @@ atomic64_fetch_sub(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_sub_acquire (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_sub_acquire (i, v); }#define atomic64_fetch_sub_acquire atomic64_fetch_sub_acquire
@@ -1026,7 +1036,7 @@ atomic64_fetch_sub_acquire(s64 i, atomicstatic inline s64 atomic64_fetch_sub_release (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_sub_release (i, v); }#define atomic64_fetch_sub_release atomic64_fetch_sub_release
@@ -1036,7 +1046,7 @@ atomic64_fetch_sub_release(s64 i, atomicstatic inline s64 atomic64_fetch_sub_relaxed (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_sub_relaxed (i, v); }#define atomic64_fetch_sub_relaxed atomic64_fetch_sub_relaxed
@@ -1046,7 +1056,7 @@ atomic64_fetch_sub_relaxed(s64 i, atomicstatic inline void atomic64_inc (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_inc (v); }#define atomic64_inc atomic64_inc
@@ -1056,7 +1066,7 @@ atomic64_inc(atomic64_t *v)static inline s64 atomic64_inc_return (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_inc_return (v); }#define atomic64_inc_return atomic64_inc_return
@@ -1066,7 +1076,7 @@ atomic64_inc_return(atomic64_t *v)static inline s64 atomic64_inc_return_acquire (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_inc_return_acquire (v); }#define atomic64_inc_return_acquire atomic64_inc_return_acquire
@@ -1076,7 +1086,7 @@ atomic64_inc_return_acquire(atomic64_t *static inline s64 atomic64_inc_return_release (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_inc_return_release (v); }#define atomic64_inc_return_release atomic64_inc_return_release
@@ -1086,7 +1096,7 @@ atomic64_inc_return_release(atomic64_t *static inline s64 atomic64_inc_return_relaxed (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_inc_return_relaxed (v); }#define atomic64_inc_return_relaxed atomic64_inc_return_relaxed
@@ -1096,7 +1106,7 @@ atomic64_inc_return_relaxed(atomic64_t *static inline s64 atomic64_fetch_inc (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_inc (v); }#define atomic64_fetch_inc atomic64_fetch_inc
@@ -1106,7 +1116,7 @@ atomic64_fetch_inc(atomic64_t *v)static inline s64 atomic64_fetch_inc_acquire (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_inc_acquire (v); }#define atomic64_fetch_inc_acquire atomic64_fetch_inc_acquire
@@ -1116,7 +1126,7 @@ atomic64_fetch_inc_acquire(atomic64_t *vstatic inline s64 atomic64_fetch_inc_release (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_inc_release (v); }#define atomic64_fetch_inc_release atomic64_fetch_inc_release
@@ -1126,7 +1136,7 @@ atomic64_fetch_inc_release(atomic64_t *vstatic inline s64 atomic64_fetch_inc_relaxed (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_inc_relaxed (v); }#define atomic64_fetch_inc_relaxed atomic64_fetch_inc_relaxed
@@ -1136,7 +1146,7 @@ atomic64_fetch_inc_relaxed(atomic64_t *vstatic inline void atomic64_dec (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_dec (v); }#define atomic64_dec atomic64_dec
@@ -1146,7 +1156,7 @@ atomic64_dec(atomic64_t *v)static inline s64 atomic64_dec_return (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_dec_return (v); }#define atomic64_dec_return atomic64_dec_return
@@ -1156,7 +1166,7 @@ atomic64_dec_return(atomic64_t *v)static inline s64 atomic64_dec_return_acquire (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_dec_return_acquire (v); }#define atomic64_dec_return_acquire atomic64_dec_return_acquire
@@ -1166,7 +1176,7 @@ atomic64_dec_return_acquire(atomic64_t *static inline s64 atomic64_dec_return_release (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_dec_return_release (v); }#define atomic64_dec_return_release atomic64_dec_return_release
@@ -1176,7 +1186,7 @@ atomic64_dec_return_release(atomic64_t *static inline s64 atomic64_dec_return_relaxed (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_dec_return_relaxed (v); }#define atomic64_dec_return_relaxed atomic64_dec_return_relaxed
@@ -1186,7 +1196,7 @@ atomic64_dec_return_relaxed(atomic64_t *static inline s64 atomic64_fetch_dec (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_dec (v); }#define atomic64_fetch_dec atomic64_fetch_dec
@@ -1196,7 +1206,7 @@ atomic64_fetch_dec(atomic64_t *v)static inline s64 atomic64_fetch_dec_acquire (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_dec_acquire (v); }#define atomic64_fetch_dec_acquire atomic64_fetch_dec_acquire
@@ -1206,7 +1216,7 @@ atomic64_fetch_dec_acquire(atomic64_t *vstatic inline s64 atomic64_fetch_dec_release (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_dec_release (v); }#define atomic64_fetch_dec_release atomic64_fetch_dec_release
@@ -1216,7 +1226,7 @@ atomic64_fetch_dec_release(atomic64_t *vstatic inline s64 atomic64_fetch_dec_relaxed (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_dec_relaxed (v); }#define atomic64_fetch_dec_relaxed atomic64_fetch_dec_relaxed
@@ -1225,7 +1235,7 @@ atomic64_fetch_dec_relaxed(atomic64_t *vstatic inline void atomic64_and (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_and (i, v); }#define atomic64_and atomic64_and
@@ -1234,7 +1244,7 @@ atomic64_and(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_and (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_and (i, v); }#define atomic64_fetch_and atomic64_fetch_and
@@ -1244,7 +1254,7 @@ atomic64_fetch_and(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_and_acquire (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_and_acquire (i, v); }#define atomic64_fetch_and_acquire atomic64_fetch_and_acquire
@@ -1254,7 +1264,7 @@ atomic64_fetch_and_acquire(s64 i, atomicstatic inline s64 atomic64_fetch_and_release (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_and_release (i, v); }#define atomic64_fetch_and_release atomic64_fetch_and_release
@@ -1264,7 +1274,7 @@ atomic64_fetch_and_release(s64 i, atomicstatic inline s64 atomic64_fetch_and_relaxed (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_and_relaxed (i, v); }#define atomic64_fetch_and_relaxed atomic64_fetch_and_relaxed
@@ -1274,7 +1284,7 @@ atomic64_fetch_and_relaxed(s64 i, atomicstatic inline void atomic64_andnot (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_andnot (i, v); }#define atomic64_andnot atomic64_andnot
@@ -1284,7 +1294,7 @@ atomic64_andnot(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_andnot (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_andnot (i, v); }#define atomic64_fetch_andnot atomic64_fetch_andnot
@@ -1294,7 +1304,7 @@ atomic64_fetch_andnot(s64 i, atomic64_tstatic inline s64 atomic64_fetch_andnot_acquire (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_andnot_acquire (i, v); }#define atomic64_fetch_andnot_acquire atomic64_fetch_andnot_acquire
@@ -1304,7 +1314,7 @@ atomic64_fetch_andnot_acquire(s64 i, atostatic inline s64 atomic64_fetch_andnot_release (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_andnot_release (i, v); }#define atomic64_fetch_andnot_release atomic64_fetch_andnot_release
@@ -1314,7 +1324,7 @@ atomic64_fetch_andnot_release(s64 i, atostatic inline s64 atomic64_fetch_andnot_relaxed (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_andnot_relaxed (i, v); }#define atomic64_fetch_andnot_relaxed atomic64_fetch_andnot_relaxed
@@ -1323,7 +1333,7 @@ atomic64_fetch_andnot_relaxed(s64 i, atostatic inline void atomic64_or (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_or (i, v); }#define atomic64_or atomic64_or
@@ -1332,7 +1342,7 @@ atomic64_or(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_or (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_or (i, v); }#define atomic64_fetch_or atomic64_fetch_or
@@ -1342,7 +1352,7 @@ atomic64_fetch_or(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_or_acquire (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_or_acquire (i, v); }#define atomic64_fetch_or_acquire atomic64_fetch_or_acquire
@@ -1352,7 +1362,7 @@ atomic64_fetch_or_acquire(s64 i, atomic6static inline s64 atomic64_fetch_or_release (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_or_release (i, v); }#define atomic64_fetch_or_release atomic64_fetch_or_release
@@ -1362,7 +1372,7 @@ atomic64_fetch_or_release(s64 i, atomic6static inline s64 atomic64_fetch_or_relaxed (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_or_relaxed (i, v); }#define atomic64_fetch_or_relaxed atomic64_fetch_or_relaxed
@@ -1371,7 +1381,7 @@ atomic64_fetch_or_relaxed(s64 i, atomic6static inline void atomic64_xor (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));arch_atomic64_xor (i, v); }#define atomic64_xor atomic64_xor
@@ -1380,7 +1390,7 @@ atomic64_xor(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_xor (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_xor (i, v); }#define atomic64_fetch_xor atomic64_fetch_xor
@@ -1390,7 +1400,7 @@ atomic64_fetch_xor(s64 i, atomic64_t *v)static inline s64 atomic64_fetch_xor_acquire (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_xor_acquire (i, v); }#define atomic64_fetch_xor_acquire atomic64_fetch_xor_acquire
@@ -1400,7 +1410,7 @@ atomic64_fetch_xor_acquire(s64 i, atomicstatic inline s64 atomic64_fetch_xor_release (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_xor_release (i, v); }#define atomic64_fetch_xor_release atomic64_fetch_xor_release
@@ -1410,7 +1420,7 @@ atomic64_fetch_xor_release(s64 i, atomicstatic inline s64 atomic64_fetch_xor_relaxed (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_xor_relaxed (i, v); }#define atomic64_fetch_xor_relaxed atomic64_fetch_xor_relaxed
@@ -1420,7 +1430,7 @@ atomic64_fetch_xor_relaxed(s64 i, atomicstatic inline s64 atomic64_xchg (atomic64_t *v,s64 i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_xchg (v, i); }#define atomic64_xchg atomic64_xchg
@@ -1430,7 +1440,7 @@ atomic64_xchg(atomic64_t *v, s64 i)static inline s64 atomic64_xchg_acquire (atomic64_t *v,s64 i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_xchg_acquire (v, i); }#define atomic64_xchg_acquire atomic64_xchg_acquire
@@ -1440,7 +1450,7 @@ atomic64_xchg_acquire(atomic64_t *v, s64static inline s64 atomic64_xchg_release (atomic64_t *v,s64 i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_xchg_release (v, i); }#define atomic64_xchg_release atomic64_xchg_release
@@ -1450,7 +1460,7 @@ atomic64_xchg_release(atomic64_t *v, s64static inline s64 atomic64_xchg_relaxed (atomic64_t *v,s64 i) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_xchg_relaxed (v, i); }#define atomic64_xchg_relaxed atomic64_xchg_relaxed
@@ -1460,7 +1470,7 @@ atomic64_xchg_relaxed(atomic64_t *v, s64static inline s64 atomic64_cmpxchg (atomic64_t *v,s64 old,s64 new) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_cmpxchg (v, old, new); }#define atomic64_cmpxchg atomic64_cmpxchg
@@ -1470,7 +1480,7 @@ atomic64_cmpxchg(atomic64_t *v, s64 old,static inline s64 atomic64_cmpxchg_acquire (atomic64_t *v,s64 old,s64 new) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_cmpxchg_acquire (v, old, new); }#define atomic64_cmpxchg_acquire atomic64_cmpxchg_acquire
@@ -1480,7 +1490,7 @@ atomic64_cmpxchg_acquire(atomic64_t *v,static inline s64 atomic64_cmpxchg_release (atomic64_t *v,s64 old,s64 new) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_cmpxchg_release (v, old, new); }#define atomic64_cmpxchg_release atomic64_cmpxchg_release
@@ -1490,7 +1500,7 @@ atomic64_cmpxchg_release(atomic64_t *v,static inline s64 atomic64_cmpxchg_relaxed (atomic64_t *v,s64 old,s64 new) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_cmpxchg_relaxed (v, old, new); }#define atomic64_cmpxchg_relaxed atomic64_cmpxchg_relaxed
@@ -1500,8 +1510,8 @@ atomic64_cmpxchg_relaxed(atomic64_t *v,static inline bool atomic64_try_cmpxchg (atomic64_t *v,s64 *old,s64 new) { -kasan_check_write (v,sizeof (*v)); -kasan_check_write (old,sizeof (*old)); +__atomic_check_write (v,sizeof (*v)); +__atomic_check_write (old,sizeof (*old));return arch_atomic64_try_cmpxchg (v, old, new); }#define atomic64_try_cmpxchg atomic64_try_cmpxchg
@@ -1511,8 +1521,8 @@ atomic64_try_cmpxchg(atomic64_t *v, s64static inline bool atomic64_try_cmpxchg_acquire (atomic64_t *v,s64 *old,s64 new) { -kasan_check_write (v,sizeof (*v)); -kasan_check_write (old,sizeof (*old)); +__atomic_check_write (v,sizeof (*v)); +__atomic_check_write (old,sizeof (*old));return arch_atomic64_try_cmpxchg_acquire (v, old, new); }#define atomic64_try_cmpxchg_acquire atomic64_try_cmpxchg_acquire
@@ -1522,8 +1532,8 @@ atomic64_try_cmpxchg_acquire(atomic64_tstatic inline bool atomic64_try_cmpxchg_release (atomic64_t *v,s64 *old,s64 new) { -kasan_check_write (v,sizeof (*v)); -kasan_check_write (old,sizeof (*old)); +__atomic_check_write (v,sizeof (*v)); +__atomic_check_write (old,sizeof (*old));return arch_atomic64_try_cmpxchg_release (v, old, new); }#define atomic64_try_cmpxchg_release atomic64_try_cmpxchg_release
@@ -1533,8 +1543,8 @@ atomic64_try_cmpxchg_release(atomic64_tstatic inline bool atomic64_try_cmpxchg_relaxed (atomic64_t *v,s64 *old,s64 new) { -kasan_check_write (v,sizeof (*v)); -kasan_check_write (old,sizeof (*old)); +__atomic_check_write (v,sizeof (*v)); +__atomic_check_write (old,sizeof (*old));return arch_atomic64_try_cmpxchg_relaxed (v, old, new); }#define atomic64_try_cmpxchg_relaxed atomic64_try_cmpxchg_relaxed
@@ -1544,7 +1554,7 @@ atomic64_try_cmpxchg_relaxed(atomic64_tstatic inline bool atomic64_sub_and_test (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_sub_and_test (i, v); }#define atomic64_sub_and_test atomic64_sub_and_test
@@ -1554,7 +1564,7 @@ atomic64_sub_and_test(s64 i, atomic64_tstatic inline bool atomic64_dec_and_test (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_dec_and_test (v); }#define atomic64_dec_and_test atomic64_dec_and_test
@@ -1564,7 +1574,7 @@ atomic64_dec_and_test(atomic64_t *v)static inline bool atomic64_inc_and_test (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_inc_and_test (v); }#define atomic64_inc_and_test atomic64_inc_and_test
@@ -1574,7 +1584,7 @@ atomic64_inc_and_test(atomic64_t *v)static inline bool atomic64_add_negative (s64 i,atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_add_negative (i, v); }#define atomic64_add_negative atomic64_add_negative
@@ -1584,7 +1594,7 @@ atomic64_add_negative(s64 i, atomic64_tstatic inline s64 atomic64_fetch_add_unless (atomic64_t *v,s64 a,s64 u) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_fetch_add_unless (v, a, u); }#define atomic64_fetch_add_unless atomic64_fetch_add_unless
@@ -1594,7 +1604,7 @@ atomic64_fetch_add_unless(atomic64_t *v,static inline bool atomic64_add_unless (atomic64_t *v,s64 a,s64 u) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_add_unless (v, a, u); }#define atomic64_add_unless atomic64_add_unless
@@ -1604,7 +1614,7 @@ atomic64_add_unless(atomic64_t *v, s64 astatic inline bool atomic64_inc_not_zero (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_inc_not_zero (v); }#define atomic64_inc_not_zero atomic64_inc_not_zero
@@ -1614,7 +1624,7 @@ atomic64_inc_not_zero(atomic64_t *v)static inline bool atomic64_inc_unless_negative (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_inc_unless_negative (v); }#define atomic64_inc_unless_negative atomic64_inc_unless_negative
@@ -1624,7 +1634,7 @@ atomic64_inc_unless_negative(atomic64_tstatic inline bool atomic64_dec_unless_positive (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_dec_unless_positive (v); }#define atomic64_dec_unless_positive atomic64_dec_unless_positive
@@ -1634,7 +1644,7 @@ atomic64_dec_unless_positive(atomic64_tstatic inline s64 atomic64_dec_if_positive (atomic64_t *v) { -kasan_check_write (v,sizeof (*v)); +__atomic_check_write (v,sizeof (*v));return arch_atomic64_dec_if_positive (v); }#define atomic64_dec_if_positive atomic64_dec_if_positive
@@ -1644,7 +1654,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define xchg (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_xchg(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1653,7 +1663,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define xchg_acquire (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_xchg_acquire(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1662,7 +1672,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define xchg_release (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_xchg_release(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1671,7 +1681,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define xchg_relaxed (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_xchg_relaxed(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1680,7 +1690,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1689,7 +1699,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg_acquire (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg_acquire(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1698,7 +1708,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg_release (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg_release(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1707,7 +1717,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg_relaxed (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg_relaxed(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1716,7 +1726,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg64 (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg64(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1725,7 +1735,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg64_acquire (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg64_acquire(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1734,7 +1744,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg64_release (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg64_release(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1743,7 +1753,7 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg64_relaxed (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg64_relaxed(__ai_ptr, __VA_ARGS__); \ })#endif
@@ -1751,28 +1761,28 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg_local (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg_local(__ai_ptr, __VA_ARGS__); \ })#define cmpxchg64_local (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_cmpxchg64_local(__ai_ptr, __VA_ARGS__); \ })#define sync_cmpxchg (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, sizeof(*__ai_ptr)); \ arch_sync_cmpxchg(__ai_ptr, __VA_ARGS__); \ })#define cmpxchg_double (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, 2 * sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, 2 * sizeof(*__ai_ptr)); \ arch_cmpxchg_double(__ai_ptr, __VA_ARGS__); \ })
@@ -1780,9 +1790,9 @@ atomic64_dec_if_positive(atomic64_t *v)#define cmpxchg_double_local (ptr, ...) \ ({ \ typeof(ptr) __ai_ptr = (ptr); \ - kasan_check_write(__ai_ptr, 2 * sizeof(*__ai_ptr)); \ + __atomic_check_write(__ai_ptr, 2 * sizeof(*__ai_ptr)); \ arch_cmpxchg_double_local(__ai_ptr, __VA_ARGS__); \ })#endif /* _ASM_GENERIC_ATOMIC_INSTRUMENTED_H */ -// b29b625d5de9280f680e42c7be859b55b15e5f6a +// aa929c117bdd954a0957b91fe509f118ca8b9707
scripts/atomic/gen-atomic-instrumented.sh +12 -2
@@ -20,7 +20,7 @@ gen_param_check() # We don't write to constant parameters [ ${type#c} != ${type} ] && rw="read" - printf "\tkasan_check_${rw}(${name}, sizeof(*${name}));\n" + printf "\t__atomic_check_${rw}(${name}, sizeof(*${name}));\n" } #gen_param_check(arg...)
@@ -107,7 +107,7 @@ cat <<EOF #define ${xchg}(ptr, ...) \\ ({ \\ typeof(ptr) __ai_ptr = (ptr); \\ - kasan_check_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\ + __atomic_check_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\ arch_${xchg}(__ai_ptr, __VA_ARGS__); \\ }) EOF
@@ -149,6 +149,16 @@ cat << EOF #include <linux/build_bug.h> #include <linux/kasan-checks.h> +static inline void __atomic_check_read(const volatile void *v, size_t size) +{ + kasan_check_read(v, size); +} + +static inline void __atomic_check_write(const volatile void *v, size_t size) +{ + kasan_check_write(v, size); +} + EOF grep '^[a-z]' "$1" | while read name meta args; do
Steven Rostedt
maintainerRe: [PATCH v3 16/22] locking/atomics, kcsan: Add KCSAN instrumentation
Quoted 9 lines · On Wed, 19 Feb 2020 15:47:40 +0100 Peter Zijlstra <[email protected]> wrote:
From: Marco Elver <[email protected]>
This adds KCSAN instrumentation to
atomic-instrumented.h.Signed-off-by Marco Elver <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>[peterz: removed the actual kcsan hooks]Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Mark Rutland <[email protected]>
Quoted 5 lines
--- include/asm-generic/atomic-instrumented.h | 390 +++++++++++++++--------------- scripts/atomic/gen-atomic-instrumented.sh | 14 - 2 files changed, 212 insertions(+), 192 deletions(-)
Does this and the rest of the series depend on the previous patches in the series? Or can this be a series on to itself (patches 16-22)?
-- Steve
Peter Zijlstra
maintainerRe: [PATCH v3 16/22] locking/atomics, kcsan: Add KCSAN instrumentation
Quoted 19 lines · Steven Rostedt
Quoted 9 lines · On Wed, 19 Feb 2020 15:47:40 +0100 Peter Zijlstra <[email protected]> wrote:
From: Marco Elver <[email protected]>
This adds KCSAN instrumentation to
atomic-instrumented.h.Signed-off-by Marco Elver <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>[peterz: removed the actual kcsan hooks]Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Mark Rutland <[email protected]>Quoted 5 lines
--- include/asm-generic/atomic-instrumented.h | 390 +++++++++++++++--------------- scripts/atomic/gen-atomic-instrumented.sh | 14 - 2 files changed, 212 insertions(+), 192 deletions(-)
Quoted 2 lines
Does this and the rest of the series depend on the previous patches in the series? Or can this be a series on to itself (patches 16-22)?
It can probably stand on its own, but it very much is related in so far that it's fallout from staring at all this nonsense.
Without these the do_int3() can actually have accidental tracing before reaching it's nmi_enter().
Paul E. McKenney
maintainerRe: [PATCH v3 16/22] locking/atomics, kcsan: Add KCSAN instrumentation
Quoted 20 lines · Peter Zijlstra
Quoted 19 lines · Steven Rostedt
Quoted 14 lines · On Wed, 19 Feb 2020 15:47:40 +0100 Peter Zijlstra <[email protected]> wrote:
From: Marco Elver <[email protected]>
This adds KCSAN instrumentation to
atomic-instrumented.h.Signed-off-by Marco Elver <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>[peterz: removed the actual kcsan hooks]Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Mark Rutland <[email protected]>--- include/asm-generic/atomic-instrumented.h | 390 +++++++++++++++--------------- scripts/atomic/gen-atomic-instrumented.sh | 14 - 2 files changed, 212 insertions(+), 192 deletions(-)
Quoted 8 lines
Quoted 2 lines
Does this and the rest of the series depend on the previous patches in the series? Or can this be a series on to itself (patches 16-22)?
It can probably stand on its own, but it very much is related in so far that it's fallout from staring at all this nonsense.
Without these the
do_int3()can actually have accidental tracing before reaching it'snmi_enter().
The original is already in -tip, so some merge magic will be required.
Thanx, Paul
Peter Zijlstra
maintainerRe: [PATCH v3 16/22] locking/atomics, kcsan: Add KCSAN instrumentation
Quoted 24 lines · Paul E. McKenney
Quoted 23 lines · Peter Zijlstra
Quoted 21 lines · Steven Rostedt
Quoted 9 lines · On Wed, 19 Feb 2020 15:47:40 +0100 Peter Zijlstra <[email protected]> wrote:
From: Marco Elver <[email protected]>
This adds KCSAN instrumentation to
atomic-instrumented.h.Signed-off-by Marco Elver <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>[peterz: removed the actual kcsan hooks]Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Mark Rutland <[email protected]>Quoted 5 lines
--- include/asm-generic/atomic-instrumented.h | 390 +++++++++++++++--------------- scripts/atomic/gen-atomic-instrumented.sh | 14 - 2 files changed, 212 insertions(+), 192 deletions(-)Does this and the rest of the series depend on the previous patches in the series? Or can this be a series on to itself (patches 16-22)?
Quoted 7 lines
Quoted 5 lines
It can probably stand on its own, but it very much is related in so far that it's fallout from staring at all this nonsense.
Without these the
do_int3()can actually have accidental tracing before reaching it'snmi_enter().The original is already in -tip, so some merge magic will be required.
Yes, So I don't strictly need this one, but I do need the two next patches adding __always_inline to everything. I figured it was easier to also pick this one (and butcher it) than to rebase everything.
I didn't want to depend on the locking/kcsan tree, and if this goes in, we do have to do something 'funny' there. Maybe rebase, maybe put in a few kcsan stubs so the original patch at least compiles. We'll see :/
Paul E. McKenney
maintainerRe: [PATCH v3 16/22] locking/atomics, kcsan: Add KCSAN instrumentation
Quoted 33 lines · Peter Zijlstra
Quoted 24 lines · Paul E. McKenney
Quoted 23 lines · Peter Zijlstra
Quoted 21 lines · Steven Rostedt
Quoted 9 lines · On Wed, 19 Feb 2020 15:47:40 +0100 Peter Zijlstra <[email protected]> wrote:
From: Marco Elver <[email protected]>
This adds KCSAN instrumentation to
atomic-instrumented.h.Signed-off-by Marco Elver <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>[peterz: removed the actual kcsan hooks]Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Mark Rutland <[email protected]>Quoted 5 lines
--- include/asm-generic/atomic-instrumented.h | 390 +++++++++++++++--------------- scripts/atomic/gen-atomic-instrumented.sh | 14 - 2 files changed, 212 insertions(+), 192 deletions(-)Does this and the rest of the series depend on the previous patches in the series? Or can this be a series on to itself (patches 16-22)?
Quoted 7 lines
Quoted 5 lines
It can probably stand on its own, but it very much is related in so far that it's fallout from staring at all this nonsense.
Without these the
do_int3()can actually have accidental tracing before reaching it'snmi_enter().The original is already in -tip, so some merge magic will be required.
Quoted 7 lines
Yes, So I don't strictly need this one, but I do need the two next patches adding
__always_inlineto everything. I figured it was easier to also pick this one (and butcher it) than to rebase everything.I didn't want to depend on the locking/kcsan tree, and if this goes in, we do have to do something 'funny' there. Maybe rebase, maybe put in a few kcsan stubs so the original patch at least compiles. We'll see :/
Fair enough!
Thanx, Paul
Peter Zijlstra
maintainerPATCH v3 17/22 asm-generic/atomic: Use __always_inline for pure wrappers
In reply to Peter ZijlstraFrom: Marco Elver <[email protected]>
Prefer __always_inline for atomic wrappers. When building for size (CC_OPTIMIZE_FOR_SIZE), some compilers appear to be less inclined to inline even relatively small static inline functions that are assumed to be inlinable such as atomic ops. This can cause problems, for example in UACCESS regions.
By using __always_inline, we let the real implementation and not the wrapper determine the final inlining preference.
For x86 tinyconfig we observe:
- vmlinux baseline: 1316204
- vmlinux with patch: 1315988 (-216 bytes)
This came up when addressing UACCESS warnings with CC_OPTIMIZE_FOR_SIZE in the KCSAN runtime:
http://lkml.kernel.org/r/[email protected]
--- include/asm-generic/atomic-instrumented.h | 335 +++++++++++++++--------------- include/asm-generic/atomic-long.h | 331 ++++++++++++++--------------- scripts/atomic/gen-atomic-instrumented.sh | 7 scripts/atomic/gen-atomic-long.sh | 3 4 files changed, 340 insertions(+), 336 deletions(-)
include/asm-generic/atomic-instrumented.h +168 -167
@@ -18,19 +18,20 @@#define _ASM_GENERIC_ATOMIC_INSTRUMENTED_H#include <linux/build_bug.h> +#include <linux/compiler.h> #include <linux/kasan-checks.h> -static inline void __atomic_check_read (const volatile void *v,size_t size) +static __always_inline void __atomic_check_read(const volatile void *v, size_t size) {kasan_check_read (v, size); } -static inline void __atomic_check_write (const volatile void *v,size_t size) +static __always_inline void __atomic_check_write(const volatile void *v, size_t size) {kasan_check_write (v, size); } -static inline int +static __always_inline intatomic_read (const atomic_t *v) {__atomic_check_read (v,sizeof (*v));
@@ -39,7 +40,7 @@ atomic_read(const atomic_t *v)#define atomic_read atomic_read#if defined(arch_atomic_read_acquire) -static inline int +static __always_inline intatomic_read_acquire (const atomic_t *v) {__atomic_check_read (v,sizeof (*v));
@@ -48,7 +49,7 @@ atomic_read_acquire(const atomic_t *v)#define atomic_read_acquire atomic_read_acquire#endif -static inline void +static __always_inline voidatomic_set (atomic_t *v,int i) {__atomic_check_write (v,sizeof (*v));
@@ -57,7 +58,7 @@ atomic_set(atomic_t *v, int i)#define atomic_set atomic_set#if defined(arch_atomic_set_release) -static inline void +static __always_inline voidatomic_set_release (atomic_t *v,int i) {__atomic_check_write (v,sizeof (*v));
@@ -66,7 +67,7 @@ atomic_set_release(atomic_t *v, int i)#define atomic_set_release atomic_set_release#endif -static inline void +static __always_inline voidatomic_add (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -75,7 +76,7 @@ atomic_add(int i, atomic_t *v)#define atomic_add atomic_add#if !defined(arch_atomic_add_return_relaxed) || defined(arch_atomic_add_return) -static inline int +static __always_inline intatomic_add_return (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -85,7 +86,7 @@ atomic_add_return(int i, atomic_t *v)#endif #if defined(arch_atomic_add_return_acquire) -static inline int +static __always_inline intatomic_add_return_acquire (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -95,7 +96,7 @@ atomic_add_return_acquire(int i, atomic_#endif #if defined(arch_atomic_add_return_release) -static inline int +static __always_inline intatomic_add_return_release (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -105,7 +106,7 @@ atomic_add_return_release(int i, atomic_#endif #if defined(arch_atomic_add_return_relaxed) -static inline int +static __always_inline intatomic_add_return_relaxed (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -115,7 +116,7 @@ atomic_add_return_relaxed(int i, atomic_#endif #if !defined(arch_atomic_fetch_add_relaxed) || defined(arch_atomic_fetch_add) -static inline int +static __always_inline intatomic_fetch_add (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -125,7 +126,7 @@ atomic_fetch_add(int i, atomic_t *v)#endif #if defined(arch_atomic_fetch_add_acquire) -static inline int +static __always_inline intatomic_fetch_add_acquire (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -135,7 +136,7 @@ atomic_fetch_add_acquire(int i, atomic_t#endif #if defined(arch_atomic_fetch_add_release) -static inline int +static __always_inline intatomic_fetch_add_release (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -145,7 +146,7 @@ atomic_fetch_add_release(int i, atomic_t#endif #if defined(arch_atomic_fetch_add_relaxed) -static inline int +static __always_inline intatomic_fetch_add_relaxed (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -154,7 +155,7 @@ atomic_fetch_add_relaxed(int i, atomic_t#define atomic_fetch_add_relaxed atomic_fetch_add_relaxed#endif -static inline void +static __always_inline voidatomic_sub (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -163,7 +164,7 @@ atomic_sub(int i, atomic_t *v)#define atomic_sub atomic_sub#if !defined(arch_atomic_sub_return_relaxed) || defined(arch_atomic_sub_return) -static inline int +static __always_inline intatomic_sub_return (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -173,7 +174,7 @@ atomic_sub_return(int i, atomic_t *v)#endif #if defined(arch_atomic_sub_return_acquire) -static inline int +static __always_inline intatomic_sub_return_acquire (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -183,7 +184,7 @@ atomic_sub_return_acquire(int i, atomic_#endif #if defined(arch_atomic_sub_return_release) -static inline int +static __always_inline intatomic_sub_return_release (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -193,7 +194,7 @@ atomic_sub_return_release(int i, atomic_#endif #if defined(arch_atomic_sub_return_relaxed) -static inline int +static __always_inline intatomic_sub_return_relaxed (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -203,7 +204,7 @@ atomic_sub_return_relaxed(int i, atomic_#endif #if !defined(arch_atomic_fetch_sub_relaxed) || defined(arch_atomic_fetch_sub) -static inline int +static __always_inline intatomic_fetch_sub (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -213,7 +214,7 @@ atomic_fetch_sub(int i, atomic_t *v)#endif #if defined(arch_atomic_fetch_sub_acquire) -static inline int +static __always_inline intatomic_fetch_sub_acquire (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -223,7 +224,7 @@ atomic_fetch_sub_acquire(int i, atomic_t#endif #if defined(arch_atomic_fetch_sub_release) -static inline int +static __always_inline intatomic_fetch_sub_release (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -233,7 +234,7 @@ atomic_fetch_sub_release(int i, atomic_t#endif #if defined(arch_atomic_fetch_sub_relaxed) -static inline int +static __always_inline intatomic_fetch_sub_relaxed (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -243,7 +244,7 @@ atomic_fetch_sub_relaxed(int i, atomic_t#endif #if defined(arch_atomic_inc) -static inline void +static __always_inline voidatomic_inc (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -253,7 +254,7 @@ atomic_inc(atomic_t *v)#endif #if defined(arch_atomic_inc_return) -static inline int +static __always_inline intatomic_inc_return (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -263,7 +264,7 @@ atomic_inc_return(atomic_t *v)#endif #if defined(arch_atomic_inc_return_acquire) -static inline int +static __always_inline intatomic_inc_return_acquire (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -273,7 +274,7 @@ atomic_inc_return_acquire(atomic_t *v)#endif #if defined(arch_atomic_inc_return_release) -static inline int +static __always_inline intatomic_inc_return_release (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -283,7 +284,7 @@ atomic_inc_return_release(atomic_t *v)#endif #if defined(arch_atomic_inc_return_relaxed) -static inline int +static __always_inline intatomic_inc_return_relaxed (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -293,7 +294,7 @@ atomic_inc_return_relaxed(atomic_t *v)#endif #if defined(arch_atomic_fetch_inc) -static inline int +static __always_inline intatomic_fetch_inc (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -303,7 +304,7 @@ atomic_fetch_inc(atomic_t *v)#endif #if defined(arch_atomic_fetch_inc_acquire) -static inline int +static __always_inline intatomic_fetch_inc_acquire (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -313,7 +314,7 @@ atomic_fetch_inc_acquire(atomic_t *v)#endif #if defined(arch_atomic_fetch_inc_release) -static inline int +static __always_inline intatomic_fetch_inc_release (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -323,7 +324,7 @@ atomic_fetch_inc_release(atomic_t *v)#endif #if defined(arch_atomic_fetch_inc_relaxed) -static inline int +static __always_inline intatomic_fetch_inc_relaxed (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -333,7 +334,7 @@ atomic_fetch_inc_relaxed(atomic_t *v)#endif #if defined(arch_atomic_dec) -static inline void +static __always_inline voidatomic_dec (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -343,7 +344,7 @@ atomic_dec(atomic_t *v)#endif #if defined(arch_atomic_dec_return) -static inline int +static __always_inline intatomic_dec_return (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -353,7 +354,7 @@ atomic_dec_return(atomic_t *v)#endif #if defined(arch_atomic_dec_return_acquire) -static inline int +static __always_inline intatomic_dec_return_acquire (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -363,7 +364,7 @@ atomic_dec_return_acquire(atomic_t *v)#endif #if defined(arch_atomic_dec_return_release) -static inline int +static __always_inline intatomic_dec_return_release (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -373,7 +374,7 @@ atomic_dec_return_release(atomic_t *v)#endif #if defined(arch_atomic_dec_return_relaxed) -static inline int +static __always_inline intatomic_dec_return_relaxed (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -383,7 +384,7 @@ atomic_dec_return_relaxed(atomic_t *v)#endif #if defined(arch_atomic_fetch_dec) -static inline int +static __always_inline intatomic_fetch_dec (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -393,7 +394,7 @@ atomic_fetch_dec(atomic_t *v)#endif #if defined(arch_atomic_fetch_dec_acquire) -static inline int +static __always_inline intatomic_fetch_dec_acquire (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -403,7 +404,7 @@ atomic_fetch_dec_acquire(atomic_t *v)#endif #if defined(arch_atomic_fetch_dec_release) -static inline int +static __always_inline intatomic_fetch_dec_release (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -413,7 +414,7 @@ atomic_fetch_dec_release(atomic_t *v)#endif #if defined(arch_atomic_fetch_dec_relaxed) -static inline int +static __always_inline intatomic_fetch_dec_relaxed (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -422,7 +423,7 @@ atomic_fetch_dec_relaxed(atomic_t *v)#define atomic_fetch_dec_relaxed atomic_fetch_dec_relaxed#endif -static inline void +static __always_inline voidatomic_and (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -431,7 +432,7 @@ atomic_and(int i, atomic_t *v)#define atomic_and atomic_and#if !defined(arch_atomic_fetch_and_relaxed) || defined(arch_atomic_fetch_and) -static inline int +static __always_inline intatomic_fetch_and (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -441,7 +442,7 @@ atomic_fetch_and(int i, atomic_t *v)#endif #if defined(arch_atomic_fetch_and_acquire) -static inline int +static __always_inline intatomic_fetch_and_acquire (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -451,7 +452,7 @@ atomic_fetch_and_acquire(int i, atomic_t#endif #if defined(arch_atomic_fetch_and_release) -static inline int +static __always_inline intatomic_fetch_and_release (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -461,7 +462,7 @@ atomic_fetch_and_release(int i, atomic_t#endif #if defined(arch_atomic_fetch_and_relaxed) -static inline int +static __always_inline intatomic_fetch_and_relaxed (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -471,7 +472,7 @@ atomic_fetch_and_relaxed(int i, atomic_t#endif #if defined(arch_atomic_andnot) -static inline void +static __always_inline voidatomic_andnot (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -481,7 +482,7 @@ atomic_andnot(int i, atomic_t *v)#endif #if defined(arch_atomic_fetch_andnot) -static inline int +static __always_inline intatomic_fetch_andnot (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -491,7 +492,7 @@ atomic_fetch_andnot(int i, atomic_t *v)#endif #if defined(arch_atomic_fetch_andnot_acquire) -static inline int +static __always_inline intatomic_fetch_andnot_acquire (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -501,7 +502,7 @@ atomic_fetch_andnot_acquire(int i, atomi#endif #if defined(arch_atomic_fetch_andnot_release) -static inline int +static __always_inline intatomic_fetch_andnot_release (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -511,7 +512,7 @@ atomic_fetch_andnot_release(int i, atomi#endif #if defined(arch_atomic_fetch_andnot_relaxed) -static inline int +static __always_inline intatomic_fetch_andnot_relaxed (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -520,7 +521,7 @@ atomic_fetch_andnot_relaxed(int i, atomi#define atomic_fetch_andnot_relaxed atomic_fetch_andnot_relaxed#endif -static inline void +static __always_inline voidatomic_or (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -529,7 +530,7 @@ atomic_or(int i, atomic_t *v)#define atomic_or atomic_or#if !defined(arch_atomic_fetch_or_relaxed) || defined(arch_atomic_fetch_or) -static inline int +static __always_inline intatomic_fetch_or (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -539,7 +540,7 @@ atomic_fetch_or(int i, atomic_t *v)#endif #if defined(arch_atomic_fetch_or_acquire) -static inline int +static __always_inline intatomic_fetch_or_acquire (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -549,7 +550,7 @@ atomic_fetch_or_acquire(int i, atomic_t#endif #if defined(arch_atomic_fetch_or_release) -static inline int +static __always_inline intatomic_fetch_or_release (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -559,7 +560,7 @@ atomic_fetch_or_release(int i, atomic_t#endif #if defined(arch_atomic_fetch_or_relaxed) -static inline int +static __always_inline intatomic_fetch_or_relaxed (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -568,7 +569,7 @@ atomic_fetch_or_relaxed(int i, atomic_t#define atomic_fetch_or_relaxed atomic_fetch_or_relaxed#endif -static inline void +static __always_inline voidatomic_xor (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -577,7 +578,7 @@ atomic_xor(int i, atomic_t *v)#define atomic_xor atomic_xor#if !defined(arch_atomic_fetch_xor_relaxed) || defined(arch_atomic_fetch_xor) -static inline int +static __always_inline intatomic_fetch_xor (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -587,7 +588,7 @@ atomic_fetch_xor(int i, atomic_t *v)#endif #if defined(arch_atomic_fetch_xor_acquire) -static inline int +static __always_inline intatomic_fetch_xor_acquire (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -597,7 +598,7 @@ atomic_fetch_xor_acquire(int i, atomic_t#endif #if defined(arch_atomic_fetch_xor_release) -static inline int +static __always_inline intatomic_fetch_xor_release (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -607,7 +608,7 @@ atomic_fetch_xor_release(int i, atomic_t#endif #if defined(arch_atomic_fetch_xor_relaxed) -static inline int +static __always_inline intatomic_fetch_xor_relaxed (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -617,7 +618,7 @@ atomic_fetch_xor_relaxed(int i, atomic_t#endif #if !defined(arch_atomic_xchg_relaxed) || defined(arch_atomic_xchg) -static inline int +static __always_inline intatomic_xchg (atomic_t *v,int i) {__atomic_check_write (v,sizeof (*v));
@@ -627,7 +628,7 @@ atomic_xchg(atomic_t *v, int i)#endif #if defined(arch_atomic_xchg_acquire) -static inline int +static __always_inline intatomic_xchg_acquire (atomic_t *v,int i) {__atomic_check_write (v,sizeof (*v));
@@ -637,7 +638,7 @@ atomic_xchg_acquire(atomic_t *v, int i)#endif #if defined(arch_atomic_xchg_release) -static inline int +static __always_inline intatomic_xchg_release (atomic_t *v,int i) {__atomic_check_write (v,sizeof (*v));
@@ -647,7 +648,7 @@ atomic_xchg_release(atomic_t *v, int i)#endif #if defined(arch_atomic_xchg_relaxed) -static inline int +static __always_inline intatomic_xchg_relaxed (atomic_t *v,int i) {__atomic_check_write (v,sizeof (*v));
@@ -657,7 +658,7 @@ atomic_xchg_relaxed(atomic_t *v, int i)#endif #if !defined(arch_atomic_cmpxchg_relaxed) || defined(arch_atomic_cmpxchg) -static inline int +static __always_inline intatomic_cmpxchg (atomic_t *v,int old,int new) {__atomic_check_write (v,sizeof (*v));
@@ -667,7 +668,7 @@ atomic_cmpxchg(atomic_t *v, int old, int#endif #if defined(arch_atomic_cmpxchg_acquire) -static inline int +static __always_inline intatomic_cmpxchg_acquire (atomic_t *v,int old,int new) {__atomic_check_write (v,sizeof (*v));
@@ -677,7 +678,7 @@ atomic_cmpxchg_acquire(atomic_t *v, int#endif #if defined(arch_atomic_cmpxchg_release) -static inline int +static __always_inline intatomic_cmpxchg_release (atomic_t *v,int old,int new) {__atomic_check_write (v,sizeof (*v));
@@ -687,7 +688,7 @@ atomic_cmpxchg_release(atomic_t *v, int#endif #if defined(arch_atomic_cmpxchg_relaxed) -static inline int +static __always_inline intatomic_cmpxchg_relaxed (atomic_t *v,int old,int new) {__atomic_check_write (v,sizeof (*v));
@@ -697,7 +698,7 @@ atomic_cmpxchg_relaxed(atomic_t *v, int#endif #if defined(arch_atomic_try_cmpxchg) -static inline bool +static __always_inline boolatomic_try_cmpxchg (atomic_t *v,int *old,int new) {__atomic_check_write (v,sizeof (*v));
@@ -708,7 +709,7 @@ atomic_try_cmpxchg(atomic_t *v, int *old#endif #if defined(arch_atomic_try_cmpxchg_acquire) -static inline bool +static __always_inline boolatomic_try_cmpxchg_acquire (atomic_t *v,int *old,int new) {__atomic_check_write (v,sizeof (*v));
@@ -719,7 +720,7 @@ atomic_try_cmpxchg_acquire(atomic_t *v,#endif #if defined(arch_atomic_try_cmpxchg_release) -static inline bool +static __always_inline boolatomic_try_cmpxchg_release (atomic_t *v,int *old,int new) {__atomic_check_write (v,sizeof (*v));
@@ -730,7 +731,7 @@ atomic_try_cmpxchg_release(atomic_t *v,#endif #if defined(arch_atomic_try_cmpxchg_relaxed) -static inline bool +static __always_inline boolatomic_try_cmpxchg_relaxed (atomic_t *v,int *old,int new) {__atomic_check_write (v,sizeof (*v));
@@ -741,7 +742,7 @@ atomic_try_cmpxchg_relaxed(atomic_t *v,#endif #if defined(arch_atomic_sub_and_test) -static inline bool +static __always_inline boolatomic_sub_and_test (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -751,7 +752,7 @@ atomic_sub_and_test(int i, atomic_t *v)#endif #if defined(arch_atomic_dec_and_test) -static inline bool +static __always_inline boolatomic_dec_and_test (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -761,7 +762,7 @@ atomic_dec_and_test(atomic_t *v)#endif #if defined(arch_atomic_inc_and_test) -static inline bool +static __always_inline boolatomic_inc_and_test (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -771,7 +772,7 @@ atomic_inc_and_test(atomic_t *v)#endif #if defined(arch_atomic_add_negative) -static inline bool +static __always_inline boolatomic_add_negative (int i,atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -781,7 +782,7 @@ atomic_add_negative(int i, atomic_t *v)#endif #if defined(arch_atomic_fetch_add_unless) -static inline int +static __always_inline intatomic_fetch_add_unless (atomic_t *v,int a,int u) {__atomic_check_write (v,sizeof (*v));
@@ -791,7 +792,7 @@ atomic_fetch_add_unless(atomic_t *v, int#endif #if defined(arch_atomic_add_unless) -static inline bool +static __always_inline boolatomic_add_unless (atomic_t *v,int a,int u) {__atomic_check_write (v,sizeof (*v));
@@ -801,7 +802,7 @@ atomic_add_unless(atomic_t *v, int a, in#endif #if defined(arch_atomic_inc_not_zero) -static inline bool +static __always_inline boolatomic_inc_not_zero (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -811,7 +812,7 @@ atomic_inc_not_zero(atomic_t *v)#endif #if defined(arch_atomic_inc_unless_negative) -static inline bool +static __always_inline boolatomic_inc_unless_negative (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -821,7 +822,7 @@ atomic_inc_unless_negative(atomic_t *v)#endif #if defined(arch_atomic_dec_unless_positive) -static inline bool +static __always_inline boolatomic_dec_unless_positive (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -831,7 +832,7 @@ atomic_dec_unless_positive(atomic_t *v)#endif #if defined(arch_atomic_dec_if_positive) -static inline int +static __always_inline intatomic_dec_if_positive (atomic_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -840,7 +841,7 @@ atomic_dec_if_positive(atomic_t *v)#define atomic_dec_if_positive atomic_dec_if_positive#endif -static inline s64 +static __always_inline s64atomic64_read (const atomic64_t *v) {__atomic_check_read (v,sizeof (*v));
@@ -849,7 +850,7 @@ atomic64_read(const atomic64_t *v)#define atomic64_read atomic64_read#if defined(arch_atomic64_read_acquire) -static inline s64 +static __always_inline s64atomic64_read_acquire (const atomic64_t *v) {__atomic_check_read (v,sizeof (*v));
@@ -858,7 +859,7 @@ atomic64_read_acquire(const atomic64_t *#define atomic64_read_acquire atomic64_read_acquire#endif -static inline void +static __always_inline voidatomic64_set (atomic64_t *v,s64 i) {__atomic_check_write (v,sizeof (*v));
@@ -867,7 +868,7 @@ atomic64_set(atomic64_t *v, s64 i)#define atomic64_set atomic64_set#if defined(arch_atomic64_set_release) -static inline void +static __always_inline voidatomic64_set_release (atomic64_t *v,s64 i) {__atomic_check_write (v,sizeof (*v));
@@ -876,7 +877,7 @@ atomic64_set_release(atomic64_t *v, s64#define atomic64_set_release atomic64_set_release#endif -static inline void +static __always_inline voidatomic64_add (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -885,7 +886,7 @@ atomic64_add(s64 i, atomic64_t *v)#define atomic64_add atomic64_add#if !defined(arch_atomic64_add_return_relaxed) || defined(arch_atomic64_add_return) -static inline s64 +static __always_inline s64atomic64_add_return (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -895,7 +896,7 @@ atomic64_add_return(s64 i, atomic64_t *v#endif #if defined(arch_atomic64_add_return_acquire) -static inline s64 +static __always_inline s64atomic64_add_return_acquire (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -905,7 +906,7 @@ atomic64_add_return_acquire(s64 i, atomi#endif #if defined(arch_atomic64_add_return_release) -static inline s64 +static __always_inline s64atomic64_add_return_release (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -915,7 +916,7 @@ atomic64_add_return_release(s64 i, atomi#endif #if defined(arch_atomic64_add_return_relaxed) -static inline s64 +static __always_inline s64atomic64_add_return_relaxed (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -925,7 +926,7 @@ atomic64_add_return_relaxed(s64 i, atomi#endif #if !defined(arch_atomic64_fetch_add_relaxed) || defined(arch_atomic64_fetch_add) -static inline s64 +static __always_inline s64atomic64_fetch_add (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -935,7 +936,7 @@ atomic64_fetch_add(s64 i, atomic64_t *v)#endif #if defined(arch_atomic64_fetch_add_acquire) -static inline s64 +static __always_inline s64atomic64_fetch_add_acquire (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -945,7 +946,7 @@ atomic64_fetch_add_acquire(s64 i, atomic#endif #if defined(arch_atomic64_fetch_add_release) -static inline s64 +static __always_inline s64atomic64_fetch_add_release (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -955,7 +956,7 @@ atomic64_fetch_add_release(s64 i, atomic#endif #if defined(arch_atomic64_fetch_add_relaxed) -static inline s64 +static __always_inline s64atomic64_fetch_add_relaxed (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -964,7 +965,7 @@ atomic64_fetch_add_relaxed(s64 i, atomic#define atomic64_fetch_add_relaxed atomic64_fetch_add_relaxed#endif -static inline void +static __always_inline voidatomic64_sub (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -973,7 +974,7 @@ atomic64_sub(s64 i, atomic64_t *v)#define atomic64_sub atomic64_sub#if !defined(arch_atomic64_sub_return_relaxed) || defined(arch_atomic64_sub_return) -static inline s64 +static __always_inline s64atomic64_sub_return (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -983,7 +984,7 @@ atomic64_sub_return(s64 i, atomic64_t *v#endif #if defined(arch_atomic64_sub_return_acquire) -static inline s64 +static __always_inline s64atomic64_sub_return_acquire (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -993,7 +994,7 @@ atomic64_sub_return_acquire(s64 i, atomi#endif #if defined(arch_atomic64_sub_return_release) -static inline s64 +static __always_inline s64atomic64_sub_return_release (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1003,7 +1004,7 @@ atomic64_sub_return_release(s64 i, atomi#endif #if defined(arch_atomic64_sub_return_relaxed) -static inline s64 +static __always_inline s64atomic64_sub_return_relaxed (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1013,7 +1014,7 @@ atomic64_sub_return_relaxed(s64 i, atomi#endif #if !defined(arch_atomic64_fetch_sub_relaxed) || defined(arch_atomic64_fetch_sub) -static inline s64 +static __always_inline s64atomic64_fetch_sub (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1023,7 +1024,7 @@ atomic64_fetch_sub(s64 i, atomic64_t *v)#endif #if defined(arch_atomic64_fetch_sub_acquire) -static inline s64 +static __always_inline s64atomic64_fetch_sub_acquire (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1033,7 +1034,7 @@ atomic64_fetch_sub_acquire(s64 i, atomic#endif #if defined(arch_atomic64_fetch_sub_release) -static inline s64 +static __always_inline s64atomic64_fetch_sub_release (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1043,7 +1044,7 @@ atomic64_fetch_sub_release(s64 i, atomic#endif #if defined(arch_atomic64_fetch_sub_relaxed) -static inline s64 +static __always_inline s64atomic64_fetch_sub_relaxed (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1053,7 +1054,7 @@ atomic64_fetch_sub_relaxed(s64 i, atomic#endif #if defined(arch_atomic64_inc) -static inline void +static __always_inline voidatomic64_inc (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1063,7 +1064,7 @@ atomic64_inc(atomic64_t *v)#endif #if defined(arch_atomic64_inc_return) -static inline s64 +static __always_inline s64atomic64_inc_return (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1073,7 +1074,7 @@ atomic64_inc_return(atomic64_t *v)#endif #if defined(arch_atomic64_inc_return_acquire) -static inline s64 +static __always_inline s64atomic64_inc_return_acquire (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1083,7 +1084,7 @@ atomic64_inc_return_acquire(atomic64_t *#endif #if defined(arch_atomic64_inc_return_release) -static inline s64 +static __always_inline s64atomic64_inc_return_release (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1093,7 +1094,7 @@ atomic64_inc_return_release(atomic64_t *#endif #if defined(arch_atomic64_inc_return_relaxed) -static inline s64 +static __always_inline s64atomic64_inc_return_relaxed (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1103,7 +1104,7 @@ atomic64_inc_return_relaxed(atomic64_t *#endif #if defined(arch_atomic64_fetch_inc) -static inline s64 +static __always_inline s64atomic64_fetch_inc (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1113,7 +1114,7 @@ atomic64_fetch_inc(atomic64_t *v)#endif #if defined(arch_atomic64_fetch_inc_acquire) -static inline s64 +static __always_inline s64atomic64_fetch_inc_acquire (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1123,7 +1124,7 @@ atomic64_fetch_inc_acquire(atomic64_t *v#endif #if defined(arch_atomic64_fetch_inc_release) -static inline s64 +static __always_inline s64atomic64_fetch_inc_release (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1133,7 +1134,7 @@ atomic64_fetch_inc_release(atomic64_t *v#endif #if defined(arch_atomic64_fetch_inc_relaxed) -static inline s64 +static __always_inline s64atomic64_fetch_inc_relaxed (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1143,7 +1144,7 @@ atomic64_fetch_inc_relaxed(atomic64_t *v#endif #if defined(arch_atomic64_dec) -static inline void +static __always_inline voidatomic64_dec (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1153,7 +1154,7 @@ atomic64_dec(atomic64_t *v)#endif #if defined(arch_atomic64_dec_return) -static inline s64 +static __always_inline s64atomic64_dec_return (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1163,7 +1164,7 @@ atomic64_dec_return(atomic64_t *v)#endif #if defined(arch_atomic64_dec_return_acquire) -static inline s64 +static __always_inline s64atomic64_dec_return_acquire (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1173,7 +1174,7 @@ atomic64_dec_return_acquire(atomic64_t *#endif #if defined(arch_atomic64_dec_return_release) -static inline s64 +static __always_inline s64atomic64_dec_return_release (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1183,7 +1184,7 @@ atomic64_dec_return_release(atomic64_t *#endif #if defined(arch_atomic64_dec_return_relaxed) -static inline s64 +static __always_inline s64atomic64_dec_return_relaxed (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1193,7 +1194,7 @@ atomic64_dec_return_relaxed(atomic64_t *#endif #if defined(arch_atomic64_fetch_dec) -static inline s64 +static __always_inline s64atomic64_fetch_dec (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1203,7 +1204,7 @@ atomic64_fetch_dec(atomic64_t *v)#endif #if defined(arch_atomic64_fetch_dec_acquire) -static inline s64 +static __always_inline s64atomic64_fetch_dec_acquire (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1213,7 +1214,7 @@ atomic64_fetch_dec_acquire(atomic64_t *v#endif #if defined(arch_atomic64_fetch_dec_release) -static inline s64 +static __always_inline s64atomic64_fetch_dec_release (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1223,7 +1224,7 @@ atomic64_fetch_dec_release(atomic64_t *v#endif #if defined(arch_atomic64_fetch_dec_relaxed) -static inline s64 +static __always_inline s64atomic64_fetch_dec_relaxed (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1232,7 +1233,7 @@ atomic64_fetch_dec_relaxed(atomic64_t *v#define atomic64_fetch_dec_relaxed atomic64_fetch_dec_relaxed#endif -static inline void +static __always_inline voidatomic64_and (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1241,7 +1242,7 @@ atomic64_and(s64 i, atomic64_t *v)#define atomic64_and atomic64_and#if !defined(arch_atomic64_fetch_and_relaxed) || defined(arch_atomic64_fetch_and) -static inline s64 +static __always_inline s64atomic64_fetch_and (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1251,7 +1252,7 @@ atomic64_fetch_and(s64 i, atomic64_t *v)#endif #if defined(arch_atomic64_fetch_and_acquire) -static inline s64 +static __always_inline s64atomic64_fetch_and_acquire (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1261,7 +1262,7 @@ atomic64_fetch_and_acquire(s64 i, atomic#endif #if defined(arch_atomic64_fetch_and_release) -static inline s64 +static __always_inline s64atomic64_fetch_and_release (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1271,7 +1272,7 @@ atomic64_fetch_and_release(s64 i, atomic#endif #if defined(arch_atomic64_fetch_and_relaxed) -static inline s64 +static __always_inline s64atomic64_fetch_and_relaxed (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1281,7 +1282,7 @@ atomic64_fetch_and_relaxed(s64 i, atomic#endif #if defined(arch_atomic64_andnot) -static inline void +static __always_inline voidatomic64_andnot (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1291,7 +1292,7 @@ atomic64_andnot(s64 i, atomic64_t *v)#endif #if defined(arch_atomic64_fetch_andnot) -static inline s64 +static __always_inline s64atomic64_fetch_andnot (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1301,7 +1302,7 @@ atomic64_fetch_andnot(s64 i, atomic64_t#endif #if defined(arch_atomic64_fetch_andnot_acquire) -static inline s64 +static __always_inline s64atomic64_fetch_andnot_acquire (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1311,7 +1312,7 @@ atomic64_fetch_andnot_acquire(s64 i, ato#endif #if defined(arch_atomic64_fetch_andnot_release) -static inline s64 +static __always_inline s64atomic64_fetch_andnot_release (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1321,7 +1322,7 @@ atomic64_fetch_andnot_release(s64 i, ato#endif #if defined(arch_atomic64_fetch_andnot_relaxed) -static inline s64 +static __always_inline s64atomic64_fetch_andnot_relaxed (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1330,7 +1331,7 @@ atomic64_fetch_andnot_relaxed(s64 i, ato#define atomic64_fetch_andnot_relaxed atomic64_fetch_andnot_relaxed#endif -static inline void +static __always_inline voidatomic64_or (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1339,7 +1340,7 @@ atomic64_or(s64 i, atomic64_t *v)#define atomic64_or atomic64_or#if !defined(arch_atomic64_fetch_or_relaxed) || defined(arch_atomic64_fetch_or) -static inline s64 +static __always_inline s64atomic64_fetch_or (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1349,7 +1350,7 @@ atomic64_fetch_or(s64 i, atomic64_t *v)#endif #if defined(arch_atomic64_fetch_or_acquire) -static inline s64 +static __always_inline s64atomic64_fetch_or_acquire (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1359,7 +1360,7 @@ atomic64_fetch_or_acquire(s64 i, atomic6#endif #if defined(arch_atomic64_fetch_or_release) -static inline s64 +static __always_inline s64atomic64_fetch_or_release (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1369,7 +1370,7 @@ atomic64_fetch_or_release(s64 i, atomic6#endif #if defined(arch_atomic64_fetch_or_relaxed) -static inline s64 +static __always_inline s64atomic64_fetch_or_relaxed (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1378,7 +1379,7 @@ atomic64_fetch_or_relaxed(s64 i, atomic6#define atomic64_fetch_or_relaxed atomic64_fetch_or_relaxed#endif -static inline void +static __always_inline voidatomic64_xor (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1387,7 +1388,7 @@ atomic64_xor(s64 i, atomic64_t *v)#define atomic64_xor atomic64_xor#if !defined(arch_atomic64_fetch_xor_relaxed) || defined(arch_atomic64_fetch_xor) -static inline s64 +static __always_inline s64atomic64_fetch_xor (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1397,7 +1398,7 @@ atomic64_fetch_xor(s64 i, atomic64_t *v)#endif #if defined(arch_atomic64_fetch_xor_acquire) -static inline s64 +static __always_inline s64atomic64_fetch_xor_acquire (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1407,7 +1408,7 @@ atomic64_fetch_xor_acquire(s64 i, atomic#endif #if defined(arch_atomic64_fetch_xor_release) -static inline s64 +static __always_inline s64atomic64_fetch_xor_release (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1417,7 +1418,7 @@ atomic64_fetch_xor_release(s64 i, atomic#endif #if defined(arch_atomic64_fetch_xor_relaxed) -static inline s64 +static __always_inline s64atomic64_fetch_xor_relaxed (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1427,7 +1428,7 @@ atomic64_fetch_xor_relaxed(s64 i, atomic#endif #if !defined(arch_atomic64_xchg_relaxed) || defined(arch_atomic64_xchg) -static inline s64 +static __always_inline s64atomic64_xchg (atomic64_t *v,s64 i) {__atomic_check_write (v,sizeof (*v));
@@ -1437,7 +1438,7 @@ atomic64_xchg(atomic64_t *v, s64 i)#endif #if defined(arch_atomic64_xchg_acquire) -static inline s64 +static __always_inline s64atomic64_xchg_acquire (atomic64_t *v,s64 i) {__atomic_check_write (v,sizeof (*v));
@@ -1447,7 +1448,7 @@ atomic64_xchg_acquire(atomic64_t *v, s64#endif #if defined(arch_atomic64_xchg_release) -static inline s64 +static __always_inline s64atomic64_xchg_release (atomic64_t *v,s64 i) {__atomic_check_write (v,sizeof (*v));
@@ -1457,7 +1458,7 @@ atomic64_xchg_release(atomic64_t *v, s64#endif #if defined(arch_atomic64_xchg_relaxed) -static inline s64 +static __always_inline s64atomic64_xchg_relaxed (atomic64_t *v,s64 i) {__atomic_check_write (v,sizeof (*v));
@@ -1467,7 +1468,7 @@ atomic64_xchg_relaxed(atomic64_t *v, s64#endif #if !defined(arch_atomic64_cmpxchg_relaxed) || defined(arch_atomic64_cmpxchg) -static inline s64 +static __always_inline s64atomic64_cmpxchg (atomic64_t *v,s64 old,s64 new) {__atomic_check_write (v,sizeof (*v));
@@ -1477,7 +1478,7 @@ atomic64_cmpxchg(atomic64_t *v, s64 old,#endif #if defined(arch_atomic64_cmpxchg_acquire) -static inline s64 +static __always_inline s64atomic64_cmpxchg_acquire (atomic64_t *v,s64 old,s64 new) {__atomic_check_write (v,sizeof (*v));
@@ -1487,7 +1488,7 @@ atomic64_cmpxchg_acquire(atomic64_t *v,#endif #if defined(arch_atomic64_cmpxchg_release) -static inline s64 +static __always_inline s64atomic64_cmpxchg_release (atomic64_t *v,s64 old,s64 new) {__atomic_check_write (v,sizeof (*v));
@@ -1497,7 +1498,7 @@ atomic64_cmpxchg_release(atomic64_t *v,#endif #if defined(arch_atomic64_cmpxchg_relaxed) -static inline s64 +static __always_inline s64atomic64_cmpxchg_relaxed (atomic64_t *v,s64 old,s64 new) {__atomic_check_write (v,sizeof (*v));
@@ -1507,7 +1508,7 @@ atomic64_cmpxchg_relaxed(atomic64_t *v,#endif #if defined(arch_atomic64_try_cmpxchg) -static inline bool +static __always_inline boolatomic64_try_cmpxchg (atomic64_t *v,s64 *old,s64 new) {__atomic_check_write (v,sizeof (*v));
@@ -1518,7 +1519,7 @@ atomic64_try_cmpxchg(atomic64_t *v, s64#endif #if defined(arch_atomic64_try_cmpxchg_acquire) -static inline bool +static __always_inline boolatomic64_try_cmpxchg_acquire (atomic64_t *v,s64 *old,s64 new) {__atomic_check_write (v,sizeof (*v));
@@ -1529,7 +1530,7 @@ atomic64_try_cmpxchg_acquire(atomic64_t#endif #if defined(arch_atomic64_try_cmpxchg_release) -static inline bool +static __always_inline boolatomic64_try_cmpxchg_release (atomic64_t *v,s64 *old,s64 new) {__atomic_check_write (v,sizeof (*v));
@@ -1540,7 +1541,7 @@ atomic64_try_cmpxchg_release(atomic64_t#endif #if defined(arch_atomic64_try_cmpxchg_relaxed) -static inline bool +static __always_inline boolatomic64_try_cmpxchg_relaxed (atomic64_t *v,s64 *old,s64 new) {__atomic_check_write (v,sizeof (*v));
@@ -1551,7 +1552,7 @@ atomic64_try_cmpxchg_relaxed(atomic64_t#endif #if defined(arch_atomic64_sub_and_test) -static inline bool +static __always_inline boolatomic64_sub_and_test (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1561,7 +1562,7 @@ atomic64_sub_and_test(s64 i, atomic64_t#endif #if defined(arch_atomic64_dec_and_test) -static inline bool +static __always_inline boolatomic64_dec_and_test (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1571,7 +1572,7 @@ atomic64_dec_and_test(atomic64_t *v)#endif #if defined(arch_atomic64_inc_and_test) -static inline bool +static __always_inline boolatomic64_inc_and_test (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1581,7 +1582,7 @@ atomic64_inc_and_test(atomic64_t *v)#endif #if defined(arch_atomic64_add_negative) -static inline bool +static __always_inline boolatomic64_add_negative (s64 i,atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1591,7 +1592,7 @@ atomic64_add_negative(s64 i, atomic64_t#endif #if defined(arch_atomic64_fetch_add_unless) -static inline s64 +static __always_inline s64atomic64_fetch_add_unless (atomic64_t *v,s64 a,s64 u) {__atomic_check_write (v,sizeof (*v));
@@ -1601,7 +1602,7 @@ atomic64_fetch_add_unless(atomic64_t *v,#endif #if defined(arch_atomic64_add_unless) -static inline bool +static __always_inline boolatomic64_add_unless (atomic64_t *v,s64 a,s64 u) {__atomic_check_write (v,sizeof (*v));
@@ -1611,7 +1612,7 @@ atomic64_add_unless(atomic64_t *v, s64 a#endif #if defined(arch_atomic64_inc_not_zero) -static inline bool +static __always_inline boolatomic64_inc_not_zero (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1621,7 +1622,7 @@ atomic64_inc_not_zero(atomic64_t *v)#endif #if defined(arch_atomic64_inc_unless_negative) -static inline bool +static __always_inline boolatomic64_inc_unless_negative (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1631,7 +1632,7 @@ atomic64_inc_unless_negative(atomic64_t#endif #if defined(arch_atomic64_dec_unless_positive) -static inline bool +static __always_inline boolatomic64_dec_unless_positive (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1641,7 +1642,7 @@ atomic64_dec_unless_positive(atomic64_t#endif #if defined(arch_atomic64_dec_if_positive) -static inline s64 +static __always_inline s64atomic64_dec_if_positive (atomic64_t *v) {__atomic_check_write (v,sizeof (*v));
@@ -1795,4 +1796,4 @@ atomic64_dec_if_positive(atomic64_t *v) })#endif /* _ASM_GENERIC_ATOMIC_INSTRUMENTED_H */ -// aa929c117bdd954a0957b91fe509f118ca8b9707 +// 6c1b0b614b55b76c258f89e205622e8f004871af
include/asm-generic/atomic-long.h +166 -165
1,162 lines not on this page · raw message
scripts/atomic/gen-atomic-instrumented.sh +4 -3
@@ -84,7 +84,7 @@ gen_proto_order_variant() [ ! -z "${guard}" ] && printf "#if ${guard}\n" cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomicname}(${params}) { ${checks}
@@ -147,14 +147,15 @@ cat << EOF #define _ASM_GENERIC_ATOMIC_INSTRUMENTED_H #include <linux/build_bug.h> +#include <linux/compiler.h> #include <linux/kasan-checks.h> -static inline void __atomic_check_read(const volatile void *v, size_t size) +static __always_inline void __atomic_check_read(const volatile void *v, size_t size) { kasan_check_read(v, size); } -static inline void __atomic_check_write(const volatile void *v, size_t size) +static __always_inline void __atomic_check_write(const volatile void *v, size_t size) { kasan_check_write(v, size); }
scripts/atomic/gen-atomic-long.sh +2 -1
@@ -46,7 +46,7 @@ gen_proto_order_variant() local retstmt="$(gen_ret_stmt "${meta}")" cat <<EOF -static inline ${ret} +static __always_inline ${ret} atomic_long_${name}(${params}) { ${retstmt}${atomic}_${name}(${argscast});
@@ -64,6 +64,7 @@ cat << EOF #ifndef _ASM_GENERIC_ATOMIC_LONG_H #define _ASM_GENERIC_ATOMIC_LONG_H +#include <linux/compiler.h> #include <asm/types.h> #ifdef CONFIG_64BIT
Peter Zijlstra
maintainerPATCH v3 18/22 asm-generic/atomic: Use __always_inline for fallback wrappers
In reply to Peter ZijlstraWhile the fallback wrappers aren't pure wrappers, they are trivial nonetheless, and the function they wrap should determine the final inlining policy.
For x86 tinyconfig we observe:
- vmlinux baseline: 1315988
- vmlinux with patch: 1315928 (-60 bytes)
---
include/linux/atomic-fallback.h +171 -169
@@ -6,6 +6,8 @@#ifndef _LINUX_ATOMIC_FALLBACK_H#define _LINUX_ATOMIC_FALLBACK_H +#include <linux/compiler.h> +#ifndef xchg_relaxed#define xchg_relaxed xchg#define xchg_acquire xchg
@@ -76,7 +78,7 @@#endif /* cmpxchg64_relaxed */ #ifndef atomic_read_acquire -static inline int +static __always_inline intatomic_read_acquire (const atomic_t *v) {return smp_load_acquire (&(v)->counter);
@@ -85,7 +87,7 @@ atomic_read_acquire(const atomic_t *v)#endif #ifndef atomic_set_release -static inline void +static __always_inline voidatomic_set_release (atomic_t *v,int i) {smp_store_release (&(v)->counter, i);
@@ -100,7 +102,7 @@ atomic_set_release(atomic_t *v, int i) #else /* atomic_add_return_relaxed */ #ifndef atomic_add_return_acquire -static inline int +static __always_inline int atomic_add_return_acquire(int i, atomic_t *v) { int ret = atomic_add_return_relaxed(i, v);
@@ -111,7 +113,7 @@ atomic_add_return_acquire(int i, atomic_t *v)#endif #ifndef atomic_add_return_release -static inline int +static __always_inline intatomic_add_return_release (int i,atomic_t *v) {__atomic_release_fence ();
@@ -121,7 +123,7 @@ atomic_add_return_release(int i, atomic_t *v)#endif #ifndef atomic_add_return -static inline int +static __always_inline intatomic_add_return (int i,atomic_t *v) {int ret;
@@ -142,7 +144,7 @@ atomic_add_return(int i, atomic_t *v) #else /* atomic_fetch_add_relaxed */ #ifndef atomic_fetch_add_acquire -static inline int +static __always_inline int atomic_fetch_add_acquire(int i, atomic_t *v) { int ret = atomic_fetch_add_relaxed(i, v);
@@ -153,7 +155,7 @@ atomic_fetch_add_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_add_release -static inline int +static __always_inline intatomic_fetch_add_release (int i,atomic_t *v) {__atomic_release_fence ();
@@ -163,7 +165,7 @@ atomic_fetch_add_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_add -static inline int +static __always_inline intatomic_fetch_add (int i,atomic_t *v) {int ret;
@@ -184,7 +186,7 @@ atomic_fetch_add(int i, atomic_t *v) #else /* atomic_sub_return_relaxed */ #ifndef atomic_sub_return_acquire -static inline int +static __always_inline int atomic_sub_return_acquire(int i, atomic_t *v) { int ret = atomic_sub_return_relaxed(i, v);
@@ -195,7 +197,7 @@ atomic_sub_return_acquire(int i, atomic_t *v)#endif #ifndef atomic_sub_return_release -static inline int +static __always_inline intatomic_sub_return_release (int i,atomic_t *v) {__atomic_release_fence ();
@@ -205,7 +207,7 @@ atomic_sub_return_release(int i, atomic_t *v)#endif #ifndef atomic_sub_return -static inline int +static __always_inline intatomic_sub_return (int i,atomic_t *v) {int ret;
@@ -226,7 +228,7 @@ atomic_sub_return(int i, atomic_t *v) #else /* atomic_fetch_sub_relaxed */ #ifndef atomic_fetch_sub_acquire -static inline int +static __always_inline int atomic_fetch_sub_acquire(int i, atomic_t *v) { int ret = atomic_fetch_sub_relaxed(i, v);
@@ -237,7 +239,7 @@ atomic_fetch_sub_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_sub_release -static inline int +static __always_inline intatomic_fetch_sub_release (int i,atomic_t *v) {__atomic_release_fence ();
@@ -247,7 +249,7 @@ atomic_fetch_sub_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_sub -static inline int +static __always_inline intatomic_fetch_sub (int i,atomic_t *v) {int ret;
@@ -262,7 +264,7 @@ atomic_fetch_sub(int i, atomic_t *v)#endif /* atomic_fetch_sub_relaxed */ #ifndef atomic_inc -static inline void +static __always_inline voidatomic_inc (atomic_t *v) {atomic_add (1 , v);
@@ -278,7 +280,7 @@ atomic_inc(atomic_t *v)#endif /* atomic_inc_return */ #ifndef atomic_inc_return -static inline int +static __always_inline intatomic_inc_return (atomic_t *v) {return atomic_add_return (1 , v);
@@ -287,7 +289,7 @@ atomic_inc_return(atomic_t *v)#endif #ifndef atomic_inc_return_acquire -static inline int +static __always_inline intatomic_inc_return_acquire (atomic_t *v) {return atomic_add_return_acquire (1 , v);
@@ -296,7 +298,7 @@ atomic_inc_return_acquire(atomic_t *v)#endif #ifndef atomic_inc_return_release -static inline int +static __always_inline intatomic_inc_return_release (atomic_t *v) {return atomic_add_return_release (1 , v);
@@ -305,7 +307,7 @@ atomic_inc_return_release(atomic_t *v)#endif #ifndef atomic_inc_return_relaxed -static inline int +static __always_inline intatomic_inc_return_relaxed (atomic_t *v) {return atomic_add_return_relaxed (1 , v);
@@ -316,7 +318,7 @@ atomic_inc_return_relaxed(atomic_t *v) #else /* atomic_inc_return_relaxed */ #ifndef atomic_inc_return_acquire -static inline int +static __always_inline int atomic_inc_return_acquire(atomic_t *v) { int ret = atomic_inc_return_relaxed(v);
@@ -327,7 +329,7 @@ atomic_inc_return_acquire(atomic_t *v)#endif #ifndef atomic_inc_return_release -static inline int +static __always_inline intatomic_inc_return_release (atomic_t *v) {__atomic_release_fence ();
@@ -337,7 +339,7 @@ atomic_inc_return_release(atomic_t *v)#endif #ifndef atomic_inc_return -static inline int +static __always_inline intatomic_inc_return (atomic_t *v) {int ret;
@@ -359,7 +361,7 @@ atomic_inc_return(atomic_t *v)#endif /* atomic_fetch_inc */ #ifndef atomic_fetch_inc -static inline int +static __always_inline intatomic_fetch_inc (atomic_t *v) {return atomic_fetch_add (1 , v);
@@ -368,7 +370,7 @@ atomic_fetch_inc(atomic_t *v)#endif #ifndef atomic_fetch_inc_acquire -static inline int +static __always_inline intatomic_fetch_inc_acquire (atomic_t *v) {return atomic_fetch_add_acquire (1 , v);
@@ -377,7 +379,7 @@ atomic_fetch_inc_acquire(atomic_t *v)#endif #ifndef atomic_fetch_inc_release -static inline int +static __always_inline intatomic_fetch_inc_release (atomic_t *v) {return atomic_fetch_add_release (1 , v);
@@ -386,7 +388,7 @@ atomic_fetch_inc_release(atomic_t *v)#endif #ifndef atomic_fetch_inc_relaxed -static inline int +static __always_inline intatomic_fetch_inc_relaxed (atomic_t *v) {return atomic_fetch_add_relaxed (1 , v);
@@ -397,7 +399,7 @@ atomic_fetch_inc_relaxed(atomic_t *v) #else /* atomic_fetch_inc_relaxed */ #ifndef atomic_fetch_inc_acquire -static inline int +static __always_inline int atomic_fetch_inc_acquire(atomic_t *v) { int ret = atomic_fetch_inc_relaxed(v);
@@ -408,7 +410,7 @@ atomic_fetch_inc_acquire(atomic_t *v)#endif #ifndef atomic_fetch_inc_release -static inline int +static __always_inline intatomic_fetch_inc_release (atomic_t *v) {__atomic_release_fence ();
@@ -418,7 +420,7 @@ atomic_fetch_inc_release(atomic_t *v)#endif #ifndef atomic_fetch_inc -static inline int +static __always_inline intatomic_fetch_inc (atomic_t *v) {int ret;
@@ -433,7 +435,7 @@ atomic_fetch_inc(atomic_t *v)#endif /* atomic_fetch_inc_relaxed */ #ifndef atomic_dec -static inline void +static __always_inline voidatomic_dec (atomic_t *v) {atomic_sub (1 , v);
@@ -449,7 +451,7 @@ atomic_dec(atomic_t *v)#endif /* atomic_dec_return */ #ifndef atomic_dec_return -static inline int +static __always_inline intatomic_dec_return (atomic_t *v) {return atomic_sub_return (1 , v);
@@ -458,7 +460,7 @@ atomic_dec_return(atomic_t *v)#endif #ifndef atomic_dec_return_acquire -static inline int +static __always_inline intatomic_dec_return_acquire (atomic_t *v) {return atomic_sub_return_acquire (1 , v);
@@ -467,7 +469,7 @@ atomic_dec_return_acquire(atomic_t *v)#endif #ifndef atomic_dec_return_release -static inline int +static __always_inline intatomic_dec_return_release (atomic_t *v) {return atomic_sub_return_release (1 , v);
@@ -476,7 +478,7 @@ atomic_dec_return_release(atomic_t *v)#endif #ifndef atomic_dec_return_relaxed -static inline int +static __always_inline intatomic_dec_return_relaxed (atomic_t *v) {return atomic_sub_return_relaxed (1 , v);
@@ -487,7 +489,7 @@ atomic_dec_return_relaxed(atomic_t *v) #else /* atomic_dec_return_relaxed */ #ifndef atomic_dec_return_acquire -static inline int +static __always_inline int atomic_dec_return_acquire(atomic_t *v) { int ret = atomic_dec_return_relaxed(v);
@@ -498,7 +500,7 @@ atomic_dec_return_acquire(atomic_t *v)#endif #ifndef atomic_dec_return_release -static inline int +static __always_inline intatomic_dec_return_release (atomic_t *v) {__atomic_release_fence ();
@@ -508,7 +510,7 @@ atomic_dec_return_release(atomic_t *v)#endif #ifndef atomic_dec_return -static inline int +static __always_inline intatomic_dec_return (atomic_t *v) {int ret;
@@ -530,7 +532,7 @@ atomic_dec_return(atomic_t *v)#endif /* atomic_fetch_dec */ #ifndef atomic_fetch_dec -static inline int +static __always_inline intatomic_fetch_dec (atomic_t *v) {return atomic_fetch_sub (1 , v);
@@ -539,7 +541,7 @@ atomic_fetch_dec(atomic_t *v)#endif #ifndef atomic_fetch_dec_acquire -static inline int +static __always_inline intatomic_fetch_dec_acquire (atomic_t *v) {return atomic_fetch_sub_acquire (1 , v);
@@ -548,7 +550,7 @@ atomic_fetch_dec_acquire(atomic_t *v)#endif #ifndef atomic_fetch_dec_release -static inline int +static __always_inline intatomic_fetch_dec_release (atomic_t *v) {return atomic_fetch_sub_release (1 , v);
@@ -557,7 +559,7 @@ atomic_fetch_dec_release(atomic_t *v)#endif #ifndef atomic_fetch_dec_relaxed -static inline int +static __always_inline intatomic_fetch_dec_relaxed (atomic_t *v) {return atomic_fetch_sub_relaxed (1 , v);
@@ -568,7 +570,7 @@ atomic_fetch_dec_relaxed(atomic_t *v) #else /* atomic_fetch_dec_relaxed */ #ifndef atomic_fetch_dec_acquire -static inline int +static __always_inline int atomic_fetch_dec_acquire(atomic_t *v) { int ret = atomic_fetch_dec_relaxed(v);
@@ -579,7 +581,7 @@ atomic_fetch_dec_acquire(atomic_t *v)#endif #ifndef atomic_fetch_dec_release -static inline int +static __always_inline intatomic_fetch_dec_release (atomic_t *v) {__atomic_release_fence ();
@@ -589,7 +591,7 @@ atomic_fetch_dec_release(atomic_t *v)#endif #ifndef atomic_fetch_dec -static inline int +static __always_inline intatomic_fetch_dec (atomic_t *v) {int ret;
@@ -610,7 +612,7 @@ atomic_fetch_dec(atomic_t *v) #else /* atomic_fetch_and_relaxed */ #ifndef atomic_fetch_and_acquire -static inline int +static __always_inline int atomic_fetch_and_acquire(int i, atomic_t *v) { int ret = atomic_fetch_and_relaxed(i, v);
@@ -621,7 +623,7 @@ atomic_fetch_and_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_and_release -static inline int +static __always_inline intatomic_fetch_and_release (int i,atomic_t *v) {__atomic_release_fence ();
@@ -631,7 +633,7 @@ atomic_fetch_and_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_and -static inline int +static __always_inline intatomic_fetch_and (int i,atomic_t *v) {int ret;
@@ -646,7 +648,7 @@ atomic_fetch_and(int i, atomic_t *v)#endif /* atomic_fetch_and_relaxed */ #ifndef atomic_andnot -static inline void +static __always_inline voidatomic_andnot (int i,atomic_t *v) {atomic_and (~i, v);
@@ -662,7 +664,7 @@ atomic_andnot(int i, atomic_t *v)#endif /* atomic_fetch_andnot */ #ifndef atomic_fetch_andnot -static inline int +static __always_inline intatomic_fetch_andnot (int i,atomic_t *v) {return atomic_fetch_and (~i, v);
@@ -671,7 +673,7 @@ atomic_fetch_andnot(int i, atomic_t *v)#endif #ifndef atomic_fetch_andnot_acquire -static inline int +static __always_inline intatomic_fetch_andnot_acquire (int i,atomic_t *v) {return atomic_fetch_and_acquire (~i, v);
@@ -680,7 +682,7 @@ atomic_fetch_andnot_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_andnot_release -static inline int +static __always_inline intatomic_fetch_andnot_release (int i,atomic_t *v) {return atomic_fetch_and_release (~i, v);
@@ -689,7 +691,7 @@ atomic_fetch_andnot_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_andnot_relaxed -static inline int +static __always_inline intatomic_fetch_andnot_relaxed (int i,atomic_t *v) {return atomic_fetch_and_relaxed (~i, v);
@@ -700,7 +702,7 @@ atomic_fetch_andnot_relaxed(int i, atomic_t *v) #else /* atomic_fetch_andnot_relaxed */ #ifndef atomic_fetch_andnot_acquire -static inline int +static __always_inline int atomic_fetch_andnot_acquire(int i, atomic_t *v) { int ret = atomic_fetch_andnot_relaxed(i, v);
@@ -711,7 +713,7 @@ atomic_fetch_andnot_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_andnot_release -static inline int +static __always_inline intatomic_fetch_andnot_release (int i,atomic_t *v) {__atomic_release_fence ();
@@ -721,7 +723,7 @@ atomic_fetch_andnot_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_andnot -static inline int +static __always_inline intatomic_fetch_andnot (int i,atomic_t *v) {int ret;
@@ -742,7 +744,7 @@ atomic_fetch_andnot(int i, atomic_t *v) #else /* atomic_fetch_or_relaxed */ #ifndef atomic_fetch_or_acquire -static inline int +static __always_inline int atomic_fetch_or_acquire(int i, atomic_t *v) { int ret = atomic_fetch_or_relaxed(i, v);
@@ -753,7 +755,7 @@ atomic_fetch_or_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_or_release -static inline int +static __always_inline intatomic_fetch_or_release (int i,atomic_t *v) {__atomic_release_fence ();
@@ -763,7 +765,7 @@ atomic_fetch_or_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_or -static inline int +static __always_inline intatomic_fetch_or (int i,atomic_t *v) {int ret;
@@ -784,7 +786,7 @@ atomic_fetch_or(int i, atomic_t *v) #else /* atomic_fetch_xor_relaxed */ #ifndef atomic_fetch_xor_acquire -static inline int +static __always_inline int atomic_fetch_xor_acquire(int i, atomic_t *v) { int ret = atomic_fetch_xor_relaxed(i, v);
@@ -795,7 +797,7 @@ atomic_fetch_xor_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_xor_release -static inline int +static __always_inline intatomic_fetch_xor_release (int i,atomic_t *v) {__atomic_release_fence ();
@@ -805,7 +807,7 @@ atomic_fetch_xor_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_xor -static inline int +static __always_inline intatomic_fetch_xor (int i,atomic_t *v) {int ret;
@@ -826,7 +828,7 @@ atomic_fetch_xor(int i, atomic_t *v) #else /* atomic_xchg_relaxed */ #ifndef atomic_xchg_acquire -static inline int +static __always_inline int atomic_xchg_acquire(atomic_t *v, int i) { int ret = atomic_xchg_relaxed(v, i);
@@ -837,7 +839,7 @@ atomic_xchg_acquire(atomic_t *v, int i)#endif #ifndef atomic_xchg_release -static inline int +static __always_inline intatomic_xchg_release (atomic_t *v,int i) {__atomic_release_fence ();
@@ -847,7 +849,7 @@ atomic_xchg_release(atomic_t *v, int i)#endif #ifndef atomic_xchg -static inline int +static __always_inline intatomic_xchg (atomic_t *v,int i) {int ret;
@@ -868,7 +870,7 @@ atomic_xchg(atomic_t *v, int i) #else /* atomic_cmpxchg_relaxed */ #ifndef atomic_cmpxchg_acquire -static inline int +static __always_inline int atomic_cmpxchg_acquire(atomic_t *v, int old, int new) { int ret = atomic_cmpxchg_relaxed(v, old, new);
@@ -879,7 +881,7 @@ atomic_cmpxchg_acquire(atomic_t *v, int old, int new)#endif #ifndef atomic_cmpxchg_release -static inline int +static __always_inline intatomic_cmpxchg_release (atomic_t *v,int old,int new) {__atomic_release_fence ();
@@ -889,7 +891,7 @@ atomic_cmpxchg_release(atomic_t *v, int old, int new)#endif #ifndef atomic_cmpxchg -static inline int +static __always_inline intatomic_cmpxchg (atomic_t *v,int old,int new) {int ret;
@@ -911,7 +913,7 @@ atomic_cmpxchg(atomic_t *v, int old, int new)#endif /* atomic_try_cmpxchg */ #ifndef atomic_try_cmpxchg -static inline bool +static __always_inline boolatomic_try_cmpxchg (atomic_t *v,int *old,int new) {int r, o = *old;
@@ -924,7 +926,7 @@ atomic_try_cmpxchg(atomic_t *v, int *old, int new)#endif #ifndef atomic_try_cmpxchg_acquire -static inline bool +static __always_inline boolatomic_try_cmpxchg_acquire (atomic_t *v,int *old,int new) {int r, o = *old;
@@ -937,7 +939,7 @@ atomic_try_cmpxchg_acquire(atomic_t *v, int *old, int new)#endif #ifndef atomic_try_cmpxchg_release -static inline bool +static __always_inline boolatomic_try_cmpxchg_release (atomic_t *v,int *old,int new) {int r, o = *old;
@@ -950,7 +952,7 @@ atomic_try_cmpxchg_release(atomic_t *v, int *old, int new)#endif #ifndef atomic_try_cmpxchg_relaxed -static inline bool +static __always_inline boolatomic_try_cmpxchg_relaxed (atomic_t *v,int *old,int new) {int r, o = *old;
@@ -965,7 +967,7 @@ atomic_try_cmpxchg_relaxed(atomic_t *v, int *old, int new) #else /* atomic_try_cmpxchg_relaxed */ #ifndef atomic_try_cmpxchg_acquire -static inline bool +static __always_inline bool atomic_try_cmpxchg_acquire(atomic_t *v, int *old, int new) { bool ret = atomic_try_cmpxchg_relaxed(v, old, new);
@@ -976,7 +978,7 @@ atomic_try_cmpxchg_acquire(atomic_t *v, int *old, int new)#endif #ifndef atomic_try_cmpxchg_release -static inline bool +static __always_inline boolatomic_try_cmpxchg_release (atomic_t *v,int *old,int new) {__atomic_release_fence ();
@@ -986,7 +988,7 @@ atomic_try_cmpxchg_release(atomic_t *v, int *old, int new)#endif #ifndef atomic_try_cmpxchg -static inline bool +static __always_inline boolatomic_try_cmpxchg (atomic_t *v,int *old,int new) {bool ret;
@@ -1010,7 +1012,7 @@ atomic_try_cmpxchg(atomic_t *v, int *old, int new)* true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline boolatomic_sub_and_test (int i,atomic_t *v) {return atomic_sub_return (i, v) ==0 ;
@@ -1027,7 +1029,7 @@ atomic_sub_and_test(int i, atomic_t *v)* returns true if the result is 0, or false for all other * cases. */ -static inline bool +static __always_inline boolatomic_dec_and_test (atomic_t *v) {return atomic_dec_return (v) ==0 ;
@@ -1044,7 +1046,7 @@ atomic_dec_and_test(atomic_t *v)* and returns true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline boolatomic_inc_and_test (atomic_t *v) {return atomic_inc_return (v) ==0 ;
@@ -1062,7 +1064,7 @@ atomic_inc_and_test(atomic_t *v)* if the result is negative, or false when * result is greater than or equal to zero. */ -static inline bool +static __always_inline boolatomic_add_negative (int i,atomic_t *v) {return atomic_add_return (i, v) <0 ;
@@ -1080,7 +1082,7 @@ atomic_add_negative(int i, atomic_t *v)* Atomically adds @a to @v, so long as @v was not already @u. * Returns original value of @v */ -static inline int +static __always_inline intatomic_fetch_add_unless (atomic_t *v,int a,int u) {int c =atomic_read (v);
@@ -1105,7 +1107,7 @@ atomic_fetch_add_unless(atomic_t *v, int a, int u)* Atomically adds @a to @v, if @v was not already @u. * Returns true if the addition was done. */ -static inline bool +static __always_inline boolatomic_add_unless (atomic_t *v,int a,int u) {return atomic_fetch_add_unless (v, a, u) != u;
@@ -1121,7 +1123,7 @@ atomic_add_unless(atomic_t *v, int a, int u)* Atomically increments @v by 1, if @v is non-zero. * Returns true if the increment was done. */ -static inline bool +static __always_inline boolatomic_inc_not_zero (atomic_t *v) {return atomic_add_unless (v,1 ,0 );
@@ -1130,7 +1132,7 @@ atomic_inc_not_zero(atomic_t *v)#endif #ifndef atomic_inc_unless_negative -static inline bool +static __always_inline boolatomic_inc_unless_negative (atomic_t *v) {int c =atomic_read (v);
@@ -1146,7 +1148,7 @@ atomic_inc_unless_negative(atomic_t *v)#endif #ifndef atomic_dec_unless_positive -static inline bool +static __always_inline boolatomic_dec_unless_positive (atomic_t *v) {int c =atomic_read (v);
@@ -1162,7 +1164,7 @@ atomic_dec_unless_positive(atomic_t *v)#endif #ifndef atomic_dec_if_positive -static inline int +static __always_inline intatomic_dec_if_positive (atomic_t *v) {int dec, c =atomic_read (v);
@@ -1186,7 +1188,7 @@ atomic_dec_if_positive(atomic_t *v)#endif #ifndef atomic64_read_acquire -static inline s64 +static __always_inline s64atomic64_read_acquire (const atomic64_t *v) {return smp_load_acquire (&(v)->counter);
@@ -1195,7 +1197,7 @@ atomic64_read_acquire(const atomic64_t *v)#endif #ifndef atomic64_set_release -static inline void +static __always_inline voidatomic64_set_release (atomic64_t *v,s64 i) {smp_store_release (&(v)->counter, i);
@@ -1210,7 +1212,7 @@ atomic64_set_release(atomic64_t *v, s64 i) #else /* atomic64_add_return_relaxed */ #ifndef atomic64_add_return_acquire -static inline s64 +static __always_inline s64 atomic64_add_return_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_add_return_relaxed(i, v);
@@ -1221,7 +1223,7 @@ atomic64_add_return_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_add_return_release -static inline s64 +static __always_inline s64atomic64_add_return_release (s64 i,atomic64_t *v) {__atomic_release_fence ();
@@ -1231,7 +1233,7 @@ atomic64_add_return_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_add_return -static inline s64 +static __always_inline s64atomic64_add_return (s64 i,atomic64_t *v) {s64 ret;
@@ -1252,7 +1254,7 @@ atomic64_add_return(s64 i, atomic64_t *v) #else /* atomic64_fetch_add_relaxed */ #ifndef atomic64_fetch_add_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_add_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_add_relaxed(i, v);
@@ -1263,7 +1265,7 @@ atomic64_fetch_add_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_add_release -static inline s64 +static __always_inline s64atomic64_fetch_add_release (s64 i,atomic64_t *v) {__atomic_release_fence ();
@@ -1273,7 +1275,7 @@ atomic64_fetch_add_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_add -static inline s64 +static __always_inline s64atomic64_fetch_add (s64 i,atomic64_t *v) {s64 ret;
@@ -1294,7 +1296,7 @@ atomic64_fetch_add(s64 i, atomic64_t *v) #else /* atomic64_sub_return_relaxed */ #ifndef atomic64_sub_return_acquire -static inline s64 +static __always_inline s64 atomic64_sub_return_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_sub_return_relaxed(i, v);
@@ -1305,7 +1307,7 @@ atomic64_sub_return_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_sub_return_release -static inline s64 +static __always_inline s64atomic64_sub_return_release (s64 i,atomic64_t *v) {__atomic_release_fence ();
@@ -1315,7 +1317,7 @@ atomic64_sub_return_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_sub_return -static inline s64 +static __always_inline s64atomic64_sub_return (s64 i,atomic64_t *v) {s64 ret;
@@ -1336,7 +1338,7 @@ atomic64_sub_return(s64 i, atomic64_t *v) #else /* atomic64_fetch_sub_relaxed */ #ifndef atomic64_fetch_sub_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_sub_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_sub_relaxed(i, v);
@@ -1347,7 +1349,7 @@ atomic64_fetch_sub_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_sub_release -static inline s64 +static __always_inline s64atomic64_fetch_sub_release (s64 i,atomic64_t *v) {__atomic_release_fence ();
@@ -1357,7 +1359,7 @@ atomic64_fetch_sub_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_sub -static inline s64 +static __always_inline s64atomic64_fetch_sub (s64 i,atomic64_t *v) {s64 ret;
@@ -1372,7 +1374,7 @@ atomic64_fetch_sub(s64 i, atomic64_t *v)#endif /* atomic64_fetch_sub_relaxed */ #ifndef atomic64_inc -static inline void +static __always_inline voidatomic64_inc (atomic64_t *v) {atomic64_add (1 , v);
@@ -1388,7 +1390,7 @@ atomic64_inc(atomic64_t *v)#endif /* atomic64_inc_return */ #ifndef atomic64_inc_return -static inline s64 +static __always_inline s64atomic64_inc_return (atomic64_t *v) {return atomic64_add_return (1 , v);
@@ -1397,7 +1399,7 @@ atomic64_inc_return(atomic64_t *v)#endif #ifndef atomic64_inc_return_acquire -static inline s64 +static __always_inline s64atomic64_inc_return_acquire (atomic64_t *v) {return atomic64_add_return_acquire (1 , v);
@@ -1406,7 +1408,7 @@ atomic64_inc_return_acquire(atomic64_t *v)#endif #ifndef atomic64_inc_return_release -static inline s64 +static __always_inline s64atomic64_inc_return_release (atomic64_t *v) {return atomic64_add_return_release (1 , v);
@@ -1415,7 +1417,7 @@ atomic64_inc_return_release(atomic64_t *v)#endif #ifndef atomic64_inc_return_relaxed -static inline s64 +static __always_inline s64atomic64_inc_return_relaxed (atomic64_t *v) {return atomic64_add_return_relaxed (1 , v);
@@ -1426,7 +1428,7 @@ atomic64_inc_return_relaxed(atomic64_t *v) #else /* atomic64_inc_return_relaxed */ #ifndef atomic64_inc_return_acquire -static inline s64 +static __always_inline s64 atomic64_inc_return_acquire(atomic64_t *v) { s64 ret = atomic64_inc_return_relaxed(v);
@@ -1437,7 +1439,7 @@ atomic64_inc_return_acquire(atomic64_t *v)#endif #ifndef atomic64_inc_return_release -static inline s64 +static __always_inline s64atomic64_inc_return_release (atomic64_t *v) {__atomic_release_fence ();
@@ -1447,7 +1449,7 @@ atomic64_inc_return_release(atomic64_t *v)#endif #ifndef atomic64_inc_return -static inline s64 +static __always_inline s64atomic64_inc_return (atomic64_t *v) {s64 ret;
@@ -1469,7 +1471,7 @@ atomic64_inc_return(atomic64_t *v)#endif /* atomic64_fetch_inc */ #ifndef atomic64_fetch_inc -static inline s64 +static __always_inline s64atomic64_fetch_inc (atomic64_t *v) {return atomic64_fetch_add (1 , v);
@@ -1478,7 +1480,7 @@ atomic64_fetch_inc(atomic64_t *v)#endif #ifndef atomic64_fetch_inc_acquire -static inline s64 +static __always_inline s64atomic64_fetch_inc_acquire (atomic64_t *v) {return atomic64_fetch_add_acquire (1 , v);
@@ -1487,7 +1489,7 @@ atomic64_fetch_inc_acquire(atomic64_t *v)#endif #ifndef atomic64_fetch_inc_release -static inline s64 +static __always_inline s64atomic64_fetch_inc_release (atomic64_t *v) {return atomic64_fetch_add_release (1 , v);
@@ -1496,7 +1498,7 @@ atomic64_fetch_inc_release(atomic64_t *v)#endif #ifndef atomic64_fetch_inc_relaxed -static inline s64 +static __always_inline s64atomic64_fetch_inc_relaxed (atomic64_t *v) {return atomic64_fetch_add_relaxed (1 , v);
@@ -1507,7 +1509,7 @@ atomic64_fetch_inc_relaxed(atomic64_t *v) #else /* atomic64_fetch_inc_relaxed */ #ifndef atomic64_fetch_inc_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_inc_acquire(atomic64_t *v) { s64 ret = atomic64_fetch_inc_relaxed(v);
@@ -1518,7 +1520,7 @@ atomic64_fetch_inc_acquire(atomic64_t *v)#endif #ifndef atomic64_fetch_inc_release -static inline s64 +static __always_inline s64atomic64_fetch_inc_release (atomic64_t *v) {__atomic_release_fence ();
@@ -1528,7 +1530,7 @@ atomic64_fetch_inc_release(atomic64_t *v)#endif #ifndef atomic64_fetch_inc -static inline s64 +static __always_inline s64atomic64_fetch_inc (atomic64_t *v) {s64 ret;
@@ -1543,7 +1545,7 @@ atomic64_fetch_inc(atomic64_t *v)#endif /* atomic64_fetch_inc_relaxed */ #ifndef atomic64_dec -static inline void +static __always_inline voidatomic64_dec (atomic64_t *v) {atomic64_sub (1 , v);
@@ -1559,7 +1561,7 @@ atomic64_dec(atomic64_t *v)#endif /* atomic64_dec_return */ #ifndef atomic64_dec_return -static inline s64 +static __always_inline s64atomic64_dec_return (atomic64_t *v) {return atomic64_sub_return (1 , v);
@@ -1568,7 +1570,7 @@ atomic64_dec_return(atomic64_t *v)#endif #ifndef atomic64_dec_return_acquire -static inline s64 +static __always_inline s64atomic64_dec_return_acquire (atomic64_t *v) {return atomic64_sub_return_acquire (1 , v);
@@ -1577,7 +1579,7 @@ atomic64_dec_return_acquire(atomic64_t *v)#endif #ifndef atomic64_dec_return_release -static inline s64 +static __always_inline s64atomic64_dec_return_release (atomic64_t *v) {return atomic64_sub_return_release (1 , v);
@@ -1586,7 +1588,7 @@ atomic64_dec_return_release(atomic64_t *v)#endif #ifndef atomic64_dec_return_relaxed -static inline s64 +static __always_inline s64atomic64_dec_return_relaxed (atomic64_t *v) {return atomic64_sub_return_relaxed (1 , v);
@@ -1597,7 +1599,7 @@ atomic64_dec_return_relaxed(atomic64_t *v) #else /* atomic64_dec_return_relaxed */ #ifndef atomic64_dec_return_acquire -static inline s64 +static __always_inline s64 atomic64_dec_return_acquire(atomic64_t *v) { s64 ret = atomic64_dec_return_relaxed(v);
@@ -1608,7 +1610,7 @@ atomic64_dec_return_acquire(atomic64_t *v)#endif #ifndef atomic64_dec_return_release -static inline s64 +static __always_inline s64atomic64_dec_return_release (atomic64_t *v) {__atomic_release_fence ();
@@ -1618,7 +1620,7 @@ atomic64_dec_return_release(atomic64_t *v)#endif #ifndef atomic64_dec_return -static inline s64 +static __always_inline s64atomic64_dec_return (atomic64_t *v) {s64 ret;
@@ -1640,7 +1642,7 @@ atomic64_dec_return(atomic64_t *v)#endif /* atomic64_fetch_dec */ #ifndef atomic64_fetch_dec -static inline s64 +static __always_inline s64atomic64_fetch_dec (atomic64_t *v) {return atomic64_fetch_sub (1 , v);
@@ -1649,7 +1651,7 @@ atomic64_fetch_dec(atomic64_t *v)#endif #ifndef atomic64_fetch_dec_acquire -static inline s64 +static __always_inline s64atomic64_fetch_dec_acquire (atomic64_t *v) {return atomic64_fetch_sub_acquire (1 , v);
@@ -1658,7 +1660,7 @@ atomic64_fetch_dec_acquire(atomic64_t *v)#endif #ifndef atomic64_fetch_dec_release -static inline s64 +static __always_inline s64atomic64_fetch_dec_release (atomic64_t *v) {return atomic64_fetch_sub_release (1 , v);
@@ -1667,7 +1669,7 @@ atomic64_fetch_dec_release(atomic64_t *v)#endif #ifndef atomic64_fetch_dec_relaxed -static inline s64 +static __always_inline s64atomic64_fetch_dec_relaxed (atomic64_t *v) {return atomic64_fetch_sub_relaxed (1 , v);
@@ -1678,7 +1680,7 @@ atomic64_fetch_dec_relaxed(atomic64_t *v) #else /* atomic64_fetch_dec_relaxed */ #ifndef atomic64_fetch_dec_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_dec_acquire(atomic64_t *v) { s64 ret = atomic64_fetch_dec_relaxed(v);
@@ -1689,7 +1691,7 @@ atomic64_fetch_dec_acquire(atomic64_t *v)#endif #ifndef atomic64_fetch_dec_release -static inline s64 +static __always_inline s64atomic64_fetch_dec_release (atomic64_t *v) {__atomic_release_fence ();
@@ -1699,7 +1701,7 @@ atomic64_fetch_dec_release(atomic64_t *v)#endif #ifndef atomic64_fetch_dec -static inline s64 +static __always_inline s64atomic64_fetch_dec (atomic64_t *v) {s64 ret;
@@ -1720,7 +1722,7 @@ atomic64_fetch_dec(atomic64_t *v) #else /* atomic64_fetch_and_relaxed */ #ifndef atomic64_fetch_and_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_and_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_and_relaxed(i, v);
@@ -1731,7 +1733,7 @@ atomic64_fetch_and_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_and_release -static inline s64 +static __always_inline s64atomic64_fetch_and_release (s64 i,atomic64_t *v) {__atomic_release_fence ();
@@ -1741,7 +1743,7 @@ atomic64_fetch_and_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_and -static inline s64 +static __always_inline s64atomic64_fetch_and (s64 i,atomic64_t *v) {s64 ret;
@@ -1756,7 +1758,7 @@ atomic64_fetch_and(s64 i, atomic64_t *v)#endif /* atomic64_fetch_and_relaxed */ #ifndef atomic64_andnot -static inline void +static __always_inline voidatomic64_andnot (s64 i,atomic64_t *v) {atomic64_and (~i, v);
@@ -1772,7 +1774,7 @@ atomic64_andnot(s64 i, atomic64_t *v)#endif /* atomic64_fetch_andnot */ #ifndef atomic64_fetch_andnot -static inline s64 +static __always_inline s64atomic64_fetch_andnot (s64 i,atomic64_t *v) {return atomic64_fetch_and (~i, v);
@@ -1781,7 +1783,7 @@ atomic64_fetch_andnot(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_andnot_acquire -static inline s64 +static __always_inline s64atomic64_fetch_andnot_acquire (s64 i,atomic64_t *v) {return atomic64_fetch_and_acquire (~i, v);
@@ -1790,7 +1792,7 @@ atomic64_fetch_andnot_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_andnot_release -static inline s64 +static __always_inline s64atomic64_fetch_andnot_release (s64 i,atomic64_t *v) {return atomic64_fetch_and_release (~i, v);
@@ -1799,7 +1801,7 @@ atomic64_fetch_andnot_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_andnot_relaxed -static inline s64 +static __always_inline s64atomic64_fetch_andnot_relaxed (s64 i,atomic64_t *v) {return atomic64_fetch_and_relaxed (~i, v);
@@ -1810,7 +1812,7 @@ atomic64_fetch_andnot_relaxed(s64 i, atomic64_t *v) #else /* atomic64_fetch_andnot_relaxed */ #ifndef atomic64_fetch_andnot_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_andnot_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_andnot_relaxed(i, v);
@@ -1821,7 +1823,7 @@ atomic64_fetch_andnot_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_andnot_release -static inline s64 +static __always_inline s64atomic64_fetch_andnot_release (s64 i,atomic64_t *v) {__atomic_release_fence ();
@@ -1831,7 +1833,7 @@ atomic64_fetch_andnot_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_andnot -static inline s64 +static __always_inline s64atomic64_fetch_andnot (s64 i,atomic64_t *v) {s64 ret;
@@ -1852,7 +1854,7 @@ atomic64_fetch_andnot(s64 i, atomic64_t *v) #else /* atomic64_fetch_or_relaxed */ #ifndef atomic64_fetch_or_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_or_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_or_relaxed(i, v);
@@ -1863,7 +1865,7 @@ atomic64_fetch_or_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_or_release -static inline s64 +static __always_inline s64atomic64_fetch_or_release (s64 i,atomic64_t *v) {__atomic_release_fence ();
@@ -1873,7 +1875,7 @@ atomic64_fetch_or_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_or -static inline s64 +static __always_inline s64atomic64_fetch_or (s64 i,atomic64_t *v) {s64 ret;
@@ -1894,7 +1896,7 @@ atomic64_fetch_or(s64 i, atomic64_t *v) #else /* atomic64_fetch_xor_relaxed */ #ifndef atomic64_fetch_xor_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_xor_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_xor_relaxed(i, v);
@@ -1905,7 +1907,7 @@ atomic64_fetch_xor_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_xor_release -static inline s64 +static __always_inline s64atomic64_fetch_xor_release (s64 i,atomic64_t *v) {__atomic_release_fence ();
@@ -1915,7 +1917,7 @@ atomic64_fetch_xor_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_xor -static inline s64 +static __always_inline s64atomic64_fetch_xor (s64 i,atomic64_t *v) {s64 ret;
@@ -1936,7 +1938,7 @@ atomic64_fetch_xor(s64 i, atomic64_t *v) #else /* atomic64_xchg_relaxed */ #ifndef atomic64_xchg_acquire -static inline s64 +static __always_inline s64 atomic64_xchg_acquire(atomic64_t *v, s64 i) { s64 ret = atomic64_xchg_relaxed(v, i);
@@ -1947,7 +1949,7 @@ atomic64_xchg_acquire(atomic64_t *v, s64 i)#endif #ifndef atomic64_xchg_release -static inline s64 +static __always_inline s64atomic64_xchg_release (atomic64_t *v,s64 i) {__atomic_release_fence ();
@@ -1957,7 +1959,7 @@ atomic64_xchg_release(atomic64_t *v, s64 i)#endif #ifndef atomic64_xchg -static inline s64 +static __always_inline s64atomic64_xchg (atomic64_t *v,s64 i) {s64 ret;
@@ -1978,7 +1980,7 @@ atomic64_xchg(atomic64_t *v, s64 i) #else /* atomic64_cmpxchg_relaxed */ #ifndef atomic64_cmpxchg_acquire -static inline s64 +static __always_inline s64 atomic64_cmpxchg_acquire(atomic64_t *v, s64 old, s64 new) { s64 ret = atomic64_cmpxchg_relaxed(v, old, new);
@@ -1989,7 +1991,7 @@ atomic64_cmpxchg_acquire(atomic64_t *v, s64 old, s64 new)#endif #ifndef atomic64_cmpxchg_release -static inline s64 +static __always_inline s64atomic64_cmpxchg_release (atomic64_t *v,s64 old,s64 new) {__atomic_release_fence ();
@@ -1999,7 +2001,7 @@ atomic64_cmpxchg_release(atomic64_t *v, s64 old, s64 new)#endif #ifndef atomic64_cmpxchg -static inline s64 +static __always_inline s64atomic64_cmpxchg (atomic64_t *v,s64 old,s64 new) {s64 ret;
@@ -2021,7 +2023,7 @@ atomic64_cmpxchg(atomic64_t *v, s64 old, s64 new)#endif /* atomic64_try_cmpxchg */ #ifndef atomic64_try_cmpxchg -static inline bool +static __always_inline boolatomic64_try_cmpxchg (atomic64_t *v,s64 *old,s64 new) {s64 r, o = *old;
@@ -2034,7 +2036,7 @@ atomic64_try_cmpxchg(atomic64_t *v, s64 *old, s64 new)#endif #ifndef atomic64_try_cmpxchg_acquire -static inline bool +static __always_inline boolatomic64_try_cmpxchg_acquire (atomic64_t *v,s64 *old,s64 new) {s64 r, o = *old;
@@ -2047,7 +2049,7 @@ atomic64_try_cmpxchg_acquire(atomic64_t *v, s64 *old, s64 new)#endif #ifndef atomic64_try_cmpxchg_release -static inline bool +static __always_inline boolatomic64_try_cmpxchg_release (atomic64_t *v,s64 *old,s64 new) {s64 r, o = *old;
@@ -2060,7 +2062,7 @@ atomic64_try_cmpxchg_release(atomic64_t *v, s64 *old, s64 new)#endif #ifndef atomic64_try_cmpxchg_relaxed -static inline bool +static __always_inline boolatomic64_try_cmpxchg_relaxed (atomic64_t *v,s64 *old,s64 new) {s64 r, o = *old;
@@ -2075,7 +2077,7 @@ atomic64_try_cmpxchg_relaxed(atomic64_t *v, s64 *old, s64 new) #else /* atomic64_try_cmpxchg_relaxed */ #ifndef atomic64_try_cmpxchg_acquire -static inline bool +static __always_inline bool atomic64_try_cmpxchg_acquire(atomic64_t *v, s64 *old, s64 new) { bool ret = atomic64_try_cmpxchg_relaxed(v, old, new);
@@ -2086,7 +2088,7 @@ atomic64_try_cmpxchg_acquire(atomic64_t *v, s64 *old, s64 new)#endif #ifndef atomic64_try_cmpxchg_release -static inline bool +static __always_inline boolatomic64_try_cmpxchg_release (atomic64_t *v,s64 *old,s64 new) {__atomic_release_fence ();
@@ -2096,7 +2098,7 @@ atomic64_try_cmpxchg_release(atomic64_t *v, s64 *old, s64 new)#endif #ifndef atomic64_try_cmpxchg -static inline bool +static __always_inline boolatomic64_try_cmpxchg (atomic64_t *v,s64 *old,s64 new) {bool ret;
@@ -2120,7 +2122,7 @@ atomic64_try_cmpxchg(atomic64_t *v, s64 *old, s64 new)* true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline boolatomic64_sub_and_test (s64 i,atomic64_t *v) {return atomic64_sub_return (i, v) ==0 ;
@@ -2137,7 +2139,7 @@ atomic64_sub_and_test(s64 i, atomic64_t *v)* returns true if the result is 0, or false for all other * cases. */ -static inline bool +static __always_inline boolatomic64_dec_and_test (atomic64_t *v) {return atomic64_dec_return (v) ==0 ;
@@ -2154,7 +2156,7 @@ atomic64_dec_and_test(atomic64_t *v)* and returns true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline boolatomic64_inc_and_test (atomic64_t *v) {return atomic64_inc_return (v) ==0 ;
@@ -2172,7 +2174,7 @@ atomic64_inc_and_test(atomic64_t *v)* if the result is negative, or false when * result is greater than or equal to zero. */ -static inline bool +static __always_inline boolatomic64_add_negative (s64 i,atomic64_t *v) {return atomic64_add_return (i, v) <0 ;
@@ -2190,7 +2192,7 @@ atomic64_add_negative(s64 i, atomic64_t *v)* Atomically adds @a to @v, so long as @v was not already @u. * Returns original value of @v */ -static inline s64 +static __always_inline s64atomic64_fetch_add_unless (atomic64_t *v,s64 a,s64 u) {s64 c =atomic64_read (v);
@@ -2215,7 +2217,7 @@ atomic64_fetch_add_unless(atomic64_t *v, s64 a, s64 u)* Atomically adds @a to @v, if @v was not already @u. * Returns true if the addition was done. */ -static inline bool +static __always_inline boolatomic64_add_unless (atomic64_t *v,s64 a,s64 u) {return atomic64_fetch_add_unless (v, a, u) != u;
@@ -2231,7 +2233,7 @@ atomic64_add_unless(atomic64_t *v, s64 a, s64 u)* Atomically increments @v by 1, if @v is non-zero. * Returns true if the increment was done. */ -static inline bool +static __always_inline boolatomic64_inc_not_zero (atomic64_t *v) {return atomic64_add_unless (v,1 ,0 );
@@ -2240,7 +2242,7 @@ atomic64_inc_not_zero(atomic64_t *v)#endif #ifndef atomic64_inc_unless_negative -static inline bool +static __always_inline boolatomic64_inc_unless_negative (atomic64_t *v) {s64 c =atomic64_read (v);
@@ -2256,7 +2258,7 @@ atomic64_inc_unless_negative(atomic64_t *v)#endif #ifndef atomic64_dec_unless_positive -static inline bool +static __always_inline boolatomic64_dec_unless_positive (atomic64_t *v) {s64 c =atomic64_read (v);
@@ -2272,7 +2274,7 @@ atomic64_dec_unless_positive(atomic64_t *v)#endif #ifndef atomic64_dec_if_positive -static inline s64 +static __always_inline s64atomic64_dec_if_positive (atomic64_t *v) {s64 dec, c =atomic64_read (v);
@@ -2292,4 +2294,4 @@ atomic64_dec_if_positive(atomic64_t *v)#define atomic64_cond_read_relaxed (v, c) smp_cond_load_relaxed(&(v)->counter, (c))#endif /* _LINUX_ATOMIC_FALLBACK_H */ -// 25de4a2804d70f57e994fe3b419148658bb5378a +// baaf45f4c24ed88ceae58baca39d7fd80bb8101b
scripts/atomic/fallbacks/acquire +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}${name}${sfx}_acquire(${params}) { ${ret} ret = ${atomic}_${pfx}${name}${sfx}_relaxed(${args});
scripts/atomic/fallbacks/add_negative +1 -1
@@ -8,7 +8,7 @@ cat <<EOF * if the result is negative, or false when * result is greater than or equal to zero. */ -static inline bool +static __always_inline bool ${atomic}_add_negative(${int} i, ${atomic}_t *v) { return ${atomic}_add_return(i, v) < 0;
scripts/atomic/fallbacks/add_unless +1 -1
@@ -8,7 +8,7 @@ cat << EOF * Atomically adds @a to @v, if @v was not already @u. * Returns true if the addition was done. */ -static inline bool +static __always_inline bool ${atomic}_add_unless(${atomic}_t *v, ${int} a, ${int} u) { return ${atomic}_fetch_add_unless(v, a, u) != u;
scripts/atomic/fallbacks/andnot +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}andnot${sfx}${order}(${int} i, ${atomic}_t *v) { ${retstmt}${atomic}_${pfx}and${sfx}${order}(~i, v);
scripts/atomic/fallbacks/dec +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}dec${sfx}${order}(${atomic}_t *v) { ${retstmt}${atomic}_${pfx}sub${sfx}${order}(1, v);
scripts/atomic/fallbacks/dec_and_test +1 -1
@@ -7,7 +7,7 @@ cat <<EOF * returns true if the result is 0, or false for all other * cases. */ -static inline bool +static __always_inline bool ${atomic}_dec_and_test(${atomic}_t *v) { return ${atomic}_dec_return(v) == 0;
scripts/atomic/fallbacks/dec_if_positive +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_dec_if_positive(${atomic}_t *v) { ${int} dec, c = ${atomic}_read(v);
scripts/atomic/fallbacks/dec_unless_positive +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline bool +static __always_inline bool ${atomic}_dec_unless_positive(${atomic}_t *v) { ${int} c = ${atomic}_read(v);
scripts/atomic/fallbacks/fence +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}${name}${sfx}(${params}) { ${ret} ret;
scripts/atomic/fallbacks/fetch_add_unless +1 -1
@@ -8,7 +8,7 @@ cat << EOF * Atomically adds @a to @v, so long as @v was not already @u. * Returns original value of @v */ -static inline ${int} +static __always_inline ${int} ${atomic}_fetch_add_unless(${atomic}_t *v, ${int} a, ${int} u) { ${int} c = ${atomic}_read(v);
scripts/atomic/fallbacks/inc +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}inc${sfx}${order}(${atomic}_t *v) { ${retstmt}${atomic}_${pfx}add${sfx}${order}(1, v);
scripts/atomic/fallbacks/inc_and_test +1 -1
@@ -7,7 +7,7 @@ cat <<EOF * and returns true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline bool ${atomic}_inc_and_test(${atomic}_t *v) { return ${atomic}_inc_return(v) == 0;
scripts/atomic/fallbacks/inc_not_zero +1 -1
@@ -6,7 +6,7 @@ cat <<EOF * Atomically increments @v by 1, if @v is non-zero. * Returns true if the increment was done. */ -static inline bool +static __always_inline bool ${atomic}_inc_not_zero(${atomic}_t *v) { return ${atomic}_add_unless(v, 1, 0);
scripts/atomic/fallbacks/inc_unless_negative +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline bool +static __always_inline bool ${atomic}_inc_unless_negative(${atomic}_t *v) { ${int} c = ${atomic}_read(v);
scripts/atomic/fallbacks/read_acquire +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_read_acquire(const ${atomic}_t *v) { return smp_load_acquire(&(v)->counter);
scripts/atomic/fallbacks/release +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}${name}${sfx}_release(${params}) { __atomic_release_fence();
scripts/atomic/fallbacks/set_release +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline void +static __always_inline void ${atomic}_set_release(${atomic}_t *v, ${int} i) { smp_store_release(&(v)->counter, i);
scripts/atomic/fallbacks/sub_and_test +1 -1
@@ -8,7 +8,7 @@ cat <<EOF * true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline bool ${atomic}_sub_and_test(${int} i, ${atomic}_t *v) { return ${atomic}_sub_return(i, v) == 0;
scripts/atomic/fallbacks/try_cmpxchg +1 -1
@@ -1,5 +1,5 @@ cat <<EOF -static inline bool +static __always_inline bool ${atomic}_try_cmpxchg${order}(${atomic}_t *v, ${int} *old, ${int} new) { ${int} r, o = *old;
scripts/atomic/gen-atomic-fallback.sh +2 -0
@@ -149,6 +149,8 @@ cat << EOF #ifndef _LINUX_ATOMIC_FALLBACK_H #define _LINUX_ATOMIC_FALLBACK_H +#include <linux/compiler.h> + EOF for xchg in "xchg" "cmpxchg" "cmpxchg64"; do
Paul E. McKenney
maintainerRe: [PATCH v3 18/22] asm-generic/atomic: Use __always_inline for fallback wrappers
Quoted 4 lines · Peter Zijlstra
While the fallback wrappers aren't pure wrappers, they are trivial nonetheless, and the function they wrap should determine the final inlining policy.
Quoted 8 lines
For x86 tinyconfig we observe:
- vmlinux baseline: 1315988
- vmlinux with patch: 1315928 (-60 bytes)Suggested-by Mark Rutland <[email protected]>Signed-off-by Marco Elver <[email protected]>Acked-by Mark Rutland <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>
And this one and the previous one are also already in -tip, FYI.
Thanx, Paul
Quoted 1,770 lines
---
include/linux/atomic-fallback.h +171
-169@@ -6,6 +6,8 @@#ifndef _LINUX_ATOMIC_FALLBACK_H#define _LINUX_ATOMIC_FALLBACK_H +#include <linux/compiler.h> +#ifndef xchg_relaxed#define xchg_relaxed xchg#define xchg_acquire xchg@@ -76,7 +78,7 @@#endif /* cmpxchg64_relaxed */ #ifndef atomic_read_acquire -static inline int +static __always_inline intatomic_read_acquire (const atomic_t *v) {return smp_load_acquire (&(v)->counter);@@ -85,7 +87,7 @@ atomic_read_acquire(const atomic_t *v)#endif #ifndef atomic_set_release -static inline void +static __always_inline voidatomic_set_release (atomic_t *v,int i) {smp_store_release (&(v)->counter, i);@@ -100,7 +102,7 @@ atomic_set_release(atomic_t *v, int i) #else /* atomic_add_return_relaxed */ #ifndef atomic_add_return_acquire -static inline int +static __always_inline int atomic_add_return_acquire(int i, atomic_t *v) { int ret = atomic_add_return_relaxed(i, v);@@ -111,7 +113,7 @@ atomic_add_return_acquire(int i, atomic_t *v)#endif #ifndef atomic_add_return_release -static inline int +static __always_inline intatomic_add_return_release (int i,atomic_t *v) {__atomic_release_fence ();@@ -121,7 +123,7 @@ atomic_add_return_release(int i, atomic_t *v)#endif #ifndef atomic_add_return -static inline int +static __always_inline intatomic_add_return (int i,atomic_t *v) {int ret;@@ -142,7 +144,7 @@ atomic_add_return(int i, atomic_t *v) #else /* atomic_fetch_add_relaxed */ #ifndef atomic_fetch_add_acquire -static inline int +static __always_inline int atomic_fetch_add_acquire(int i, atomic_t *v) { int ret = atomic_fetch_add_relaxed(i, v);@@ -153,7 +155,7 @@ atomic_fetch_add_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_add_release -static inline int +static __always_inline intatomic_fetch_add_release (int i,atomic_t *v) {__atomic_release_fence ();@@ -163,7 +165,7 @@ atomic_fetch_add_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_add -static inline int +static __always_inline intatomic_fetch_add (int i,atomic_t *v) {int ret;@@ -184,7 +186,7 @@ atomic_fetch_add(int i, atomic_t *v) #else /* atomic_sub_return_relaxed */ #ifndef atomic_sub_return_acquire -static inline int +static __always_inline int atomic_sub_return_acquire(int i, atomic_t *v) { int ret = atomic_sub_return_relaxed(i, v);@@ -195,7 +197,7 @@ atomic_sub_return_acquire(int i, atomic_t *v)#endif #ifndef atomic_sub_return_release -static inline int +static __always_inline intatomic_sub_return_release (int i,atomic_t *v) {__atomic_release_fence ();@@ -205,7 +207,7 @@ atomic_sub_return_release(int i, atomic_t *v)#endif #ifndef atomic_sub_return -static inline int +static __always_inline intatomic_sub_return (int i,atomic_t *v) {int ret;@@ -226,7 +228,7 @@ atomic_sub_return(int i, atomic_t *v) #else /* atomic_fetch_sub_relaxed */ #ifndef atomic_fetch_sub_acquire -static inline int +static __always_inline int atomic_fetch_sub_acquire(int i, atomic_t *v) { int ret = atomic_fetch_sub_relaxed(i, v);@@ -237,7 +239,7 @@ atomic_fetch_sub_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_sub_release -static inline int +static __always_inline intatomic_fetch_sub_release (int i,atomic_t *v) {__atomic_release_fence ();@@ -247,7 +249,7 @@ atomic_fetch_sub_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_sub -static inline int +static __always_inline intatomic_fetch_sub (int i,atomic_t *v) {int ret;@@ -262,7 +264,7 @@ atomic_fetch_sub(int i, atomic_t *v)#endif /* atomic_fetch_sub_relaxed */ #ifndef atomic_inc -static inline void +static __always_inline voidatomic_inc (atomic_t *v) {atomic_add (1 , v);@@ -278,7 +280,7 @@ atomic_inc(atomic_t *v)#endif /* atomic_inc_return */ #ifndef atomic_inc_return -static inline int +static __always_inline intatomic_inc_return (atomic_t *v) {return atomic_add_return (1 , v);@@ -287,7 +289,7 @@ atomic_inc_return(atomic_t *v)#endif #ifndef atomic_inc_return_acquire -static inline int +static __always_inline intatomic_inc_return_acquire (atomic_t *v) {return atomic_add_return_acquire (1 , v);@@ -296,7 +298,7 @@ atomic_inc_return_acquire(atomic_t *v)#endif #ifndef atomic_inc_return_release -static inline int +static __always_inline intatomic_inc_return_release (atomic_t *v) {return atomic_add_return_release (1 , v);@@ -305,7 +307,7 @@ atomic_inc_return_release(atomic_t *v)#endif #ifndef atomic_inc_return_relaxed -static inline int +static __always_inline intatomic_inc_return_relaxed (atomic_t *v) {return atomic_add_return_relaxed (1 , v);@@ -316,7 +318,7 @@ atomic_inc_return_relaxed(atomic_t *v) #else /* atomic_inc_return_relaxed */ #ifndef atomic_inc_return_acquire -static inline int +static __always_inline int atomic_inc_return_acquire(atomic_t *v) { int ret = atomic_inc_return_relaxed(v);@@ -327,7 +329,7 @@ atomic_inc_return_acquire(atomic_t *v)#endif #ifndef atomic_inc_return_release -static inline int +static __always_inline intatomic_inc_return_release (atomic_t *v) {__atomic_release_fence ();@@ -337,7 +339,7 @@ atomic_inc_return_release(atomic_t *v)#endif #ifndef atomic_inc_return -static inline int +static __always_inline intatomic_inc_return (atomic_t *v) {int ret;@@ -359,7 +361,7 @@ atomic_inc_return(atomic_t *v)#endif /* atomic_fetch_inc */ #ifndef atomic_fetch_inc -static inline int +static __always_inline intatomic_fetch_inc (atomic_t *v) {return atomic_fetch_add (1 , v);@@ -368,7 +370,7 @@ atomic_fetch_inc(atomic_t *v)#endif #ifndef atomic_fetch_inc_acquire -static inline int +static __always_inline intatomic_fetch_inc_acquire (atomic_t *v) {return atomic_fetch_add_acquire (1 , v);@@ -377,7 +379,7 @@ atomic_fetch_inc_acquire(atomic_t *v)#endif #ifndef atomic_fetch_inc_release -static inline int +static __always_inline intatomic_fetch_inc_release (atomic_t *v) {return atomic_fetch_add_release (1 , v);@@ -386,7 +388,7 @@ atomic_fetch_inc_release(atomic_t *v)#endif #ifndef atomic_fetch_inc_relaxed -static inline int +static __always_inline intatomic_fetch_inc_relaxed (atomic_t *v) {return atomic_fetch_add_relaxed (1 , v);@@ -397,7 +399,7 @@ atomic_fetch_inc_relaxed(atomic_t *v) #else /* atomic_fetch_inc_relaxed */ #ifndef atomic_fetch_inc_acquire -static inline int +static __always_inline int atomic_fetch_inc_acquire(atomic_t *v) { int ret = atomic_fetch_inc_relaxed(v);@@ -408,7 +410,7 @@ atomic_fetch_inc_acquire(atomic_t *v)#endif #ifndef atomic_fetch_inc_release -static inline int +static __always_inline intatomic_fetch_inc_release (atomic_t *v) {__atomic_release_fence ();@@ -418,7 +420,7 @@ atomic_fetch_inc_release(atomic_t *v)#endif #ifndef atomic_fetch_inc -static inline int +static __always_inline intatomic_fetch_inc (atomic_t *v) {int ret;@@ -433,7 +435,7 @@ atomic_fetch_inc(atomic_t *v)#endif /* atomic_fetch_inc_relaxed */ #ifndef atomic_dec -static inline void +static __always_inline voidatomic_dec (atomic_t *v) {atomic_sub (1 , v);@@ -449,7 +451,7 @@ atomic_dec(atomic_t *v)#endif /* atomic_dec_return */ #ifndef atomic_dec_return -static inline int +static __always_inline intatomic_dec_return (atomic_t *v) {return atomic_sub_return (1 , v);@@ -458,7 +460,7 @@ atomic_dec_return(atomic_t *v)#endif #ifndef atomic_dec_return_acquire -static inline int +static __always_inline intatomic_dec_return_acquire (atomic_t *v) {return atomic_sub_return_acquire (1 , v);@@ -467,7 +469,7 @@ atomic_dec_return_acquire(atomic_t *v)#endif #ifndef atomic_dec_return_release -static inline int +static __always_inline intatomic_dec_return_release (atomic_t *v) {return atomic_sub_return_release (1 , v);@@ -476,7 +478,7 @@ atomic_dec_return_release(atomic_t *v)#endif #ifndef atomic_dec_return_relaxed -static inline int +static __always_inline intatomic_dec_return_relaxed (atomic_t *v) {return atomic_sub_return_relaxed (1 , v);@@ -487,7 +489,7 @@ atomic_dec_return_relaxed(atomic_t *v) #else /* atomic_dec_return_relaxed */ #ifndef atomic_dec_return_acquire -static inline int +static __always_inline int atomic_dec_return_acquire(atomic_t *v) { int ret = atomic_dec_return_relaxed(v);@@ -498,7 +500,7 @@ atomic_dec_return_acquire(atomic_t *v)#endif #ifndef atomic_dec_return_release -static inline int +static __always_inline intatomic_dec_return_release (atomic_t *v) {__atomic_release_fence ();@@ -508,7 +510,7 @@ atomic_dec_return_release(atomic_t *v)#endif #ifndef atomic_dec_return -static inline int +static __always_inline intatomic_dec_return (atomic_t *v) {int ret;@@ -530,7 +532,7 @@ atomic_dec_return(atomic_t *v)#endif /* atomic_fetch_dec */ #ifndef atomic_fetch_dec -static inline int +static __always_inline intatomic_fetch_dec (atomic_t *v) {return atomic_fetch_sub (1 , v);@@ -539,7 +541,7 @@ atomic_fetch_dec(atomic_t *v)#endif #ifndef atomic_fetch_dec_acquire -static inline int +static __always_inline intatomic_fetch_dec_acquire (atomic_t *v) {return atomic_fetch_sub_acquire (1 , v);@@ -548,7 +550,7 @@ atomic_fetch_dec_acquire(atomic_t *v)#endif #ifndef atomic_fetch_dec_release -static inline int +static __always_inline intatomic_fetch_dec_release (atomic_t *v) {return atomic_fetch_sub_release (1 , v);@@ -557,7 +559,7 @@ atomic_fetch_dec_release(atomic_t *v)#endif #ifndef atomic_fetch_dec_relaxed -static inline int +static __always_inline intatomic_fetch_dec_relaxed (atomic_t *v) {return atomic_fetch_sub_relaxed (1 , v);@@ -568,7 +570,7 @@ atomic_fetch_dec_relaxed(atomic_t *v) #else /* atomic_fetch_dec_relaxed */ #ifndef atomic_fetch_dec_acquire -static inline int +static __always_inline int atomic_fetch_dec_acquire(atomic_t *v) { int ret = atomic_fetch_dec_relaxed(v);@@ -579,7 +581,7 @@ atomic_fetch_dec_acquire(atomic_t *v)#endif #ifndef atomic_fetch_dec_release -static inline int +static __always_inline intatomic_fetch_dec_release (atomic_t *v) {__atomic_release_fence ();@@ -589,7 +591,7 @@ atomic_fetch_dec_release(atomic_t *v)#endif #ifndef atomic_fetch_dec -static inline int +static __always_inline intatomic_fetch_dec (atomic_t *v) {int ret;@@ -610,7 +612,7 @@ atomic_fetch_dec(atomic_t *v) #else /* atomic_fetch_and_relaxed */ #ifndef atomic_fetch_and_acquire -static inline int +static __always_inline int atomic_fetch_and_acquire(int i, atomic_t *v) { int ret = atomic_fetch_and_relaxed(i, v);@@ -621,7 +623,7 @@ atomic_fetch_and_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_and_release -static inline int +static __always_inline intatomic_fetch_and_release (int i,atomic_t *v) {__atomic_release_fence ();@@ -631,7 +633,7 @@ atomic_fetch_and_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_and -static inline int +static __always_inline intatomic_fetch_and (int i,atomic_t *v) {int ret;@@ -646,7 +648,7 @@ atomic_fetch_and(int i, atomic_t *v)#endif /* atomic_fetch_and_relaxed */ #ifndef atomic_andnot -static inline void +static __always_inline voidatomic_andnot (int i,atomic_t *v) {atomic_and (~i, v);@@ -662,7 +664,7 @@ atomic_andnot(int i, atomic_t *v)#endif /* atomic_fetch_andnot */ #ifndef atomic_fetch_andnot -static inline int +static __always_inline intatomic_fetch_andnot (int i,atomic_t *v) {return atomic_fetch_and (~i, v);@@ -671,7 +673,7 @@ atomic_fetch_andnot(int i, atomic_t *v)#endif #ifndef atomic_fetch_andnot_acquire -static inline int +static __always_inline intatomic_fetch_andnot_acquire (int i,atomic_t *v) {return atomic_fetch_and_acquire (~i, v);@@ -680,7 +682,7 @@ atomic_fetch_andnot_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_andnot_release -static inline int +static __always_inline intatomic_fetch_andnot_release (int i,atomic_t *v) {return atomic_fetch_and_release (~i, v);@@ -689,7 +691,7 @@ atomic_fetch_andnot_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_andnot_relaxed -static inline int +static __always_inline intatomic_fetch_andnot_relaxed (int i,atomic_t *v) {return atomic_fetch_and_relaxed (~i, v);@@ -700,7 +702,7 @@ atomic_fetch_andnot_relaxed(int i, atomic_t *v) #else /* atomic_fetch_andnot_relaxed */ #ifndef atomic_fetch_andnot_acquire -static inline int +static __always_inline int atomic_fetch_andnot_acquire(int i, atomic_t *v) { int ret = atomic_fetch_andnot_relaxed(i, v);@@ -711,7 +713,7 @@ atomic_fetch_andnot_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_andnot_release -static inline int +static __always_inline intatomic_fetch_andnot_release (int i,atomic_t *v) {__atomic_release_fence ();@@ -721,7 +723,7 @@ atomic_fetch_andnot_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_andnot -static inline int +static __always_inline intatomic_fetch_andnot (int i,atomic_t *v) {int ret;@@ -742,7 +744,7 @@ atomic_fetch_andnot(int i, atomic_t *v) #else /* atomic_fetch_or_relaxed */ #ifndef atomic_fetch_or_acquire -static inline int +static __always_inline int atomic_fetch_or_acquire(int i, atomic_t *v) { int ret = atomic_fetch_or_relaxed(i, v);@@ -753,7 +755,7 @@ atomic_fetch_or_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_or_release -static inline int +static __always_inline intatomic_fetch_or_release (int i,atomic_t *v) {__atomic_release_fence ();@@ -763,7 +765,7 @@ atomic_fetch_or_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_or -static inline int +static __always_inline intatomic_fetch_or (int i,atomic_t *v) {int ret;@@ -784,7 +786,7 @@ atomic_fetch_or(int i, atomic_t *v) #else /* atomic_fetch_xor_relaxed */ #ifndef atomic_fetch_xor_acquire -static inline int +static __always_inline int atomic_fetch_xor_acquire(int i, atomic_t *v) { int ret = atomic_fetch_xor_relaxed(i, v);@@ -795,7 +797,7 @@ atomic_fetch_xor_acquire(int i, atomic_t *v)#endif #ifndef atomic_fetch_xor_release -static inline int +static __always_inline intatomic_fetch_xor_release (int i,atomic_t *v) {__atomic_release_fence ();@@ -805,7 +807,7 @@ atomic_fetch_xor_release(int i, atomic_t *v)#endif #ifndef atomic_fetch_xor -static inline int +static __always_inline intatomic_fetch_xor (int i,atomic_t *v) {int ret;@@ -826,7 +828,7 @@ atomic_fetch_xor(int i, atomic_t *v) #else /* atomic_xchg_relaxed */ #ifndef atomic_xchg_acquire -static inline int +static __always_inline int atomic_xchg_acquire(atomic_t *v, int i) { int ret = atomic_xchg_relaxed(v, i);@@ -837,7 +839,7 @@ atomic_xchg_acquire(atomic_t *v, int i)#endif #ifndef atomic_xchg_release -static inline int +static __always_inline intatomic_xchg_release (atomic_t *v,int i) {__atomic_release_fence ();@@ -847,7 +849,7 @@ atomic_xchg_release(atomic_t *v, int i)#endif #ifndef atomic_xchg -static inline int +static __always_inline intatomic_xchg (atomic_t *v,int i) {int ret;@@ -868,7 +870,7 @@ atomic_xchg(atomic_t *v, int i) #else /* atomic_cmpxchg_relaxed */ #ifndef atomic_cmpxchg_acquire -static inline int +static __always_inline int atomic_cmpxchg_acquire(atomic_t *v, int old, int new) { int ret = atomic_cmpxchg_relaxed(v, old, new);@@ -879,7 +881,7 @@ atomic_cmpxchg_acquire(atomic_t *v, int old, int new)#endif #ifndef atomic_cmpxchg_release -static inline int +static __always_inline intatomic_cmpxchg_release (atomic_t *v,int old,int new) {__atomic_release_fence ();@@ -889,7 +891,7 @@ atomic_cmpxchg_release(atomic_t *v, int old, int new)#endif #ifndef atomic_cmpxchg -static inline int +static __always_inline intatomic_cmpxchg (atomic_t *v,int old,int new) {int ret;@@ -911,7 +913,7 @@ atomic_cmpxchg(atomic_t *v, int old, int new)#endif /* atomic_try_cmpxchg */ #ifndef atomic_try_cmpxchg -static inline bool +static __always_inline boolatomic_try_cmpxchg (atomic_t *v,int *old,int new) {int r, o = *old;@@ -924,7 +926,7 @@ atomic_try_cmpxchg(atomic_t *v, int *old, int new)#endif #ifndef atomic_try_cmpxchg_acquire -static inline bool +static __always_inline boolatomic_try_cmpxchg_acquire (atomic_t *v,int *old,int new) {int r, o = *old;@@ -937,7 +939,7 @@ atomic_try_cmpxchg_acquire(atomic_t *v, int *old, int new)#endif #ifndef atomic_try_cmpxchg_release -static inline bool +static __always_inline boolatomic_try_cmpxchg_release (atomic_t *v,int *old,int new) {int r, o = *old;@@ -950,7 +952,7 @@ atomic_try_cmpxchg_release(atomic_t *v, int *old, int new)#endif #ifndef atomic_try_cmpxchg_relaxed -static inline bool +static __always_inline boolatomic_try_cmpxchg_relaxed (atomic_t *v,int *old,int new) {int r, o = *old;@@ -965,7 +967,7 @@ atomic_try_cmpxchg_relaxed(atomic_t *v, int *old, int new) #else /* atomic_try_cmpxchg_relaxed */ #ifndef atomic_try_cmpxchg_acquire -static inline bool +static __always_inline bool atomic_try_cmpxchg_acquire(atomic_t *v, int *old, int new) { bool ret = atomic_try_cmpxchg_relaxed(v, old, new);@@ -976,7 +978,7 @@ atomic_try_cmpxchg_acquire(atomic_t *v, int *old, int new)#endif #ifndef atomic_try_cmpxchg_release -static inline bool +static __always_inline boolatomic_try_cmpxchg_release (atomic_t *v,int *old,int new) {__atomic_release_fence ();@@ -986,7 +988,7 @@ atomic_try_cmpxchg_release(atomic_t *v, int *old, int new)#endif #ifndef atomic_try_cmpxchg -static inline bool +static __always_inline boolatomic_try_cmpxchg (atomic_t *v,int *old,int new) {bool ret;@@ -1010,7 +1012,7 @@ atomic_try_cmpxchg(atomic_t *v, int *old, int new)* true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline boolatomic_sub_and_test (int i,atomic_t *v) {return atomic_sub_return (i, v) ==0 ;@@ -1027,7 +1029,7 @@ atomic_sub_and_test(int i, atomic_t *v)* returns true if the result is 0, or false for all other * cases. */ -static inline bool +static __always_inline boolatomic_dec_and_test (atomic_t *v) {return atomic_dec_return (v) ==0 ;@@ -1044,7 +1046,7 @@ atomic_dec_and_test(atomic_t *v)* and returns true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline boolatomic_inc_and_test (atomic_t *v) {return atomic_inc_return (v) ==0 ;@@ -1062,7 +1064,7 @@ atomic_inc_and_test(atomic_t *v)* if the result is negative, or false when * result is greater than or equal to zero. */ -static inline bool +static __always_inline boolatomic_add_negative (int i,atomic_t *v) {return atomic_add_return (i, v) <0 ;@@ -1080,7 +1082,7 @@ atomic_add_negative(int i, atomic_t *v)* Atomically adds @a to @v, so long as @v was not already @u. * Returns original value of @v */ -static inline int +static __always_inline intatomic_fetch_add_unless (atomic_t *v,int a,int u) {int c =atomic_read (v);@@ -1105,7 +1107,7 @@ atomic_fetch_add_unless(atomic_t *v, int a, int u)* Atomically adds @a to @v, if @v was not already @u. * Returns true if the addition was done. */ -static inline bool +static __always_inline boolatomic_add_unless (atomic_t *v,int a,int u) {return atomic_fetch_add_unless (v, a, u) != u;@@ -1121,7 +1123,7 @@ atomic_add_unless(atomic_t *v, int a, int u)* Atomically increments @v by 1, if @v is non-zero. * Returns true if the increment was done. */ -static inline bool +static __always_inline boolatomic_inc_not_zero (atomic_t *v) {return atomic_add_unless (v,1 ,0 );@@ -1130,7 +1132,7 @@ atomic_inc_not_zero(atomic_t *v)#endif #ifndef atomic_inc_unless_negative -static inline bool +static __always_inline boolatomic_inc_unless_negative (atomic_t *v) {int c =atomic_read (v);@@ -1146,7 +1148,7 @@ atomic_inc_unless_negative(atomic_t *v)#endif #ifndef atomic_dec_unless_positive -static inline bool +static __always_inline boolatomic_dec_unless_positive (atomic_t *v) {int c =atomic_read (v);@@ -1162,7 +1164,7 @@ atomic_dec_unless_positive(atomic_t *v)#endif #ifndef atomic_dec_if_positive -static inline int +static __always_inline intatomic_dec_if_positive (atomic_t *v) {int dec, c =atomic_read (v);@@ -1186,7 +1188,7 @@ atomic_dec_if_positive(atomic_t *v)#endif #ifndef atomic64_read_acquire -static inline s64 +static __always_inline s64atomic64_read_acquire (const atomic64_t *v) {return smp_load_acquire (&(v)->counter);@@ -1195,7 +1197,7 @@ atomic64_read_acquire(const atomic64_t *v)#endif #ifndef atomic64_set_release -static inline void +static __always_inline voidatomic64_set_release (atomic64_t *v,s64 i) {smp_store_release (&(v)->counter, i);@@ -1210,7 +1212,7 @@ atomic64_set_release(atomic64_t *v, s64 i) #else /* atomic64_add_return_relaxed */ #ifndef atomic64_add_return_acquire -static inline s64 +static __always_inline s64 atomic64_add_return_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_add_return_relaxed(i, v);@@ -1221,7 +1223,7 @@ atomic64_add_return_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_add_return_release -static inline s64 +static __always_inline s64atomic64_add_return_release (s64 i,atomic64_t *v) {__atomic_release_fence ();@@ -1231,7 +1233,7 @@ atomic64_add_return_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_add_return -static inline s64 +static __always_inline s64atomic64_add_return (s64 i,atomic64_t *v) {s64 ret;@@ -1252,7 +1254,7 @@ atomic64_add_return(s64 i, atomic64_t *v) #else /* atomic64_fetch_add_relaxed */ #ifndef atomic64_fetch_add_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_add_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_add_relaxed(i, v);@@ -1263,7 +1265,7 @@ atomic64_fetch_add_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_add_release -static inline s64 +static __always_inline s64atomic64_fetch_add_release (s64 i,atomic64_t *v) {__atomic_release_fence ();@@ -1273,7 +1275,7 @@ atomic64_fetch_add_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_add -static inline s64 +static __always_inline s64atomic64_fetch_add (s64 i,atomic64_t *v) {s64 ret;@@ -1294,7 +1296,7 @@ atomic64_fetch_add(s64 i, atomic64_t *v) #else /* atomic64_sub_return_relaxed */ #ifndef atomic64_sub_return_acquire -static inline s64 +static __always_inline s64 atomic64_sub_return_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_sub_return_relaxed(i, v);@@ -1305,7 +1307,7 @@ atomic64_sub_return_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_sub_return_release -static inline s64 +static __always_inline s64atomic64_sub_return_release (s64 i,atomic64_t *v) {__atomic_release_fence ();@@ -1315,7 +1317,7 @@ atomic64_sub_return_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_sub_return -static inline s64 +static __always_inline s64atomic64_sub_return (s64 i,atomic64_t *v) {s64 ret;@@ -1336,7 +1338,7 @@ atomic64_sub_return(s64 i, atomic64_t *v) #else /* atomic64_fetch_sub_relaxed */ #ifndef atomic64_fetch_sub_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_sub_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_sub_relaxed(i, v);@@ -1347,7 +1349,7 @@ atomic64_fetch_sub_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_sub_release -static inline s64 +static __always_inline s64atomic64_fetch_sub_release (s64 i,atomic64_t *v) {__atomic_release_fence ();@@ -1357,7 +1359,7 @@ atomic64_fetch_sub_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_sub -static inline s64 +static __always_inline s64atomic64_fetch_sub (s64 i,atomic64_t *v) {s64 ret;@@ -1372,7 +1374,7 @@ atomic64_fetch_sub(s64 i, atomic64_t *v)#endif /* atomic64_fetch_sub_relaxed */ #ifndef atomic64_inc -static inline void +static __always_inline voidatomic64_inc (atomic64_t *v) {atomic64_add (1 , v);@@ -1388,7 +1390,7 @@ atomic64_inc(atomic64_t *v)#endif /* atomic64_inc_return */ #ifndef atomic64_inc_return -static inline s64 +static __always_inline s64atomic64_inc_return (atomic64_t *v) {return atomic64_add_return (1 , v);@@ -1397,7 +1399,7 @@ atomic64_inc_return(atomic64_t *v)#endif #ifndef atomic64_inc_return_acquire -static inline s64 +static __always_inline s64atomic64_inc_return_acquire (atomic64_t *v) {return atomic64_add_return_acquire (1 , v);@@ -1406,7 +1408,7 @@ atomic64_inc_return_acquire(atomic64_t *v)#endif #ifndef atomic64_inc_return_release -static inline s64 +static __always_inline s64atomic64_inc_return_release (atomic64_t *v) {return atomic64_add_return_release (1 , v);@@ -1415,7 +1417,7 @@ atomic64_inc_return_release(atomic64_t *v)#endif #ifndef atomic64_inc_return_relaxed -static inline s64 +static __always_inline s64atomic64_inc_return_relaxed (atomic64_t *v) {return atomic64_add_return_relaxed (1 , v);@@ -1426,7 +1428,7 @@ atomic64_inc_return_relaxed(atomic64_t *v) #else /* atomic64_inc_return_relaxed */ #ifndef atomic64_inc_return_acquire -static inline s64 +static __always_inline s64 atomic64_inc_return_acquire(atomic64_t *v) { s64 ret = atomic64_inc_return_relaxed(v);@@ -1437,7 +1439,7 @@ atomic64_inc_return_acquire(atomic64_t *v)#endif #ifndef atomic64_inc_return_release -static inline s64 +static __always_inline s64atomic64_inc_return_release (atomic64_t *v) {__atomic_release_fence ();@@ -1447,7 +1449,7 @@ atomic64_inc_return_release(atomic64_t *v)#endif #ifndef atomic64_inc_return -static inline s64 +static __always_inline s64atomic64_inc_return (atomic64_t *v) {s64 ret;@@ -1469,7 +1471,7 @@ atomic64_inc_return(atomic64_t *v)#endif /* atomic64_fetch_inc */ #ifndef atomic64_fetch_inc -static inline s64 +static __always_inline s64atomic64_fetch_inc (atomic64_t *v) {return atomic64_fetch_add (1 , v);@@ -1478,7 +1480,7 @@ atomic64_fetch_inc(atomic64_t *v)#endif #ifndef atomic64_fetch_inc_acquire -static inline s64 +static __always_inline s64atomic64_fetch_inc_acquire (atomic64_t *v) {return atomic64_fetch_add_acquire (1 , v);@@ -1487,7 +1489,7 @@ atomic64_fetch_inc_acquire(atomic64_t *v)#endif #ifndef atomic64_fetch_inc_release -static inline s64 +static __always_inline s64atomic64_fetch_inc_release (atomic64_t *v) {return atomic64_fetch_add_release (1 , v);@@ -1496,7 +1498,7 @@ atomic64_fetch_inc_release(atomic64_t *v)#endif #ifndef atomic64_fetch_inc_relaxed -static inline s64 +static __always_inline s64atomic64_fetch_inc_relaxed (atomic64_t *v) {return atomic64_fetch_add_relaxed (1 , v);@@ -1507,7 +1509,7 @@ atomic64_fetch_inc_relaxed(atomic64_t *v) #else /* atomic64_fetch_inc_relaxed */ #ifndef atomic64_fetch_inc_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_inc_acquire(atomic64_t *v) { s64 ret = atomic64_fetch_inc_relaxed(v);@@ -1518,7 +1520,7 @@ atomic64_fetch_inc_acquire(atomic64_t *v)#endif #ifndef atomic64_fetch_inc_release -static inline s64 +static __always_inline s64atomic64_fetch_inc_release (atomic64_t *v) {__atomic_release_fence ();@@ -1528,7 +1530,7 @@ atomic64_fetch_inc_release(atomic64_t *v)#endif #ifndef atomic64_fetch_inc -static inline s64 +static __always_inline s64atomic64_fetch_inc (atomic64_t *v) {s64 ret;@@ -1543,7 +1545,7 @@ atomic64_fetch_inc(atomic64_t *v)#endif /* atomic64_fetch_inc_relaxed */ #ifndef atomic64_dec -static inline void +static __always_inline voidatomic64_dec (atomic64_t *v) {atomic64_sub (1 , v);@@ -1559,7 +1561,7 @@ atomic64_dec(atomic64_t *v)#endif /* atomic64_dec_return */ #ifndef atomic64_dec_return -static inline s64 +static __always_inline s64atomic64_dec_return (atomic64_t *v) {return atomic64_sub_return (1 , v);@@ -1568,7 +1570,7 @@ atomic64_dec_return(atomic64_t *v)#endif #ifndef atomic64_dec_return_acquire -static inline s64 +static __always_inline s64atomic64_dec_return_acquire (atomic64_t *v) {return atomic64_sub_return_acquire (1 , v);@@ -1577,7 +1579,7 @@ atomic64_dec_return_acquire(atomic64_t *v)#endif #ifndef atomic64_dec_return_release -static inline s64 +static __always_inline s64atomic64_dec_return_release (atomic64_t *v) {return atomic64_sub_return_release (1 , v);@@ -1586,7 +1588,7 @@ atomic64_dec_return_release(atomic64_t *v)#endif #ifndef atomic64_dec_return_relaxed -static inline s64 +static __always_inline s64atomic64_dec_return_relaxed (atomic64_t *v) {return atomic64_sub_return_relaxed (1 , v);@@ -1597,7 +1599,7 @@ atomic64_dec_return_relaxed(atomic64_t *v) #else /* atomic64_dec_return_relaxed */ #ifndef atomic64_dec_return_acquire -static inline s64 +static __always_inline s64 atomic64_dec_return_acquire(atomic64_t *v) { s64 ret = atomic64_dec_return_relaxed(v);@@ -1608,7 +1610,7 @@ atomic64_dec_return_acquire(atomic64_t *v)#endif #ifndef atomic64_dec_return_release -static inline s64 +static __always_inline s64atomic64_dec_return_release (atomic64_t *v) {__atomic_release_fence ();@@ -1618,7 +1620,7 @@ atomic64_dec_return_release(atomic64_t *v)#endif #ifndef atomic64_dec_return -static inline s64 +static __always_inline s64atomic64_dec_return (atomic64_t *v) {s64 ret;@@ -1640,7 +1642,7 @@ atomic64_dec_return(atomic64_t *v)#endif /* atomic64_fetch_dec */ #ifndef atomic64_fetch_dec -static inline s64 +static __always_inline s64atomic64_fetch_dec (atomic64_t *v) {return atomic64_fetch_sub (1 , v);@@ -1649,7 +1651,7 @@ atomic64_fetch_dec(atomic64_t *v)#endif #ifndef atomic64_fetch_dec_acquire -static inline s64 +static __always_inline s64atomic64_fetch_dec_acquire (atomic64_t *v) {return atomic64_fetch_sub_acquire (1 , v);@@ -1658,7 +1660,7 @@ atomic64_fetch_dec_acquire(atomic64_t *v)#endif #ifndef atomic64_fetch_dec_release -static inline s64 +static __always_inline s64atomic64_fetch_dec_release (atomic64_t *v) {return atomic64_fetch_sub_release (1 , v);@@ -1667,7 +1669,7 @@ atomic64_fetch_dec_release(atomic64_t *v)#endif #ifndef atomic64_fetch_dec_relaxed -static inline s64 +static __always_inline s64atomic64_fetch_dec_relaxed (atomic64_t *v) {return atomic64_fetch_sub_relaxed (1 , v);@@ -1678,7 +1680,7 @@ atomic64_fetch_dec_relaxed(atomic64_t *v) #else /* atomic64_fetch_dec_relaxed */ #ifndef atomic64_fetch_dec_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_dec_acquire(atomic64_t *v) { s64 ret = atomic64_fetch_dec_relaxed(v);@@ -1689,7 +1691,7 @@ atomic64_fetch_dec_acquire(atomic64_t *v)#endif #ifndef atomic64_fetch_dec_release -static inline s64 +static __always_inline s64atomic64_fetch_dec_release (atomic64_t *v) {__atomic_release_fence ();@@ -1699,7 +1701,7 @@ atomic64_fetch_dec_release(atomic64_t *v)#endif #ifndef atomic64_fetch_dec -static inline s64 +static __always_inline s64atomic64_fetch_dec (atomic64_t *v) {s64 ret;@@ -1720,7 +1722,7 @@ atomic64_fetch_dec(atomic64_t *v) #else /* atomic64_fetch_and_relaxed */ #ifndef atomic64_fetch_and_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_and_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_and_relaxed(i, v);@@ -1731,7 +1733,7 @@ atomic64_fetch_and_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_and_release -static inline s64 +static __always_inline s64atomic64_fetch_and_release (s64 i,atomic64_t *v) {__atomic_release_fence ();@@ -1741,7 +1743,7 @@ atomic64_fetch_and_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_and -static inline s64 +static __always_inline s64atomic64_fetch_and (s64 i,atomic64_t *v) {s64 ret;@@ -1756,7 +1758,7 @@ atomic64_fetch_and(s64 i, atomic64_t *v)#endif /* atomic64_fetch_and_relaxed */ #ifndef atomic64_andnot -static inline void +static __always_inline voidatomic64_andnot (s64 i,atomic64_t *v) {atomic64_and (~i, v);@@ -1772,7 +1774,7 @@ atomic64_andnot(s64 i, atomic64_t *v)#endif /* atomic64_fetch_andnot */ #ifndef atomic64_fetch_andnot -static inline s64 +static __always_inline s64atomic64_fetch_andnot (s64 i,atomic64_t *v) {return atomic64_fetch_and (~i, v);@@ -1781,7 +1783,7 @@ atomic64_fetch_andnot(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_andnot_acquire -static inline s64 +static __always_inline s64atomic64_fetch_andnot_acquire (s64 i,atomic64_t *v) {return atomic64_fetch_and_acquire (~i, v);@@ -1790,7 +1792,7 @@ atomic64_fetch_andnot_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_andnot_release -static inline s64 +static __always_inline s64atomic64_fetch_andnot_release (s64 i,atomic64_t *v) {return atomic64_fetch_and_release (~i, v);@@ -1799,7 +1801,7 @@ atomic64_fetch_andnot_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_andnot_relaxed -static inline s64 +static __always_inline s64atomic64_fetch_andnot_relaxed (s64 i,atomic64_t *v) {return atomic64_fetch_and_relaxed (~i, v);@@ -1810,7 +1812,7 @@ atomic64_fetch_andnot_relaxed(s64 i, atomic64_t *v) #else /* atomic64_fetch_andnot_relaxed */ #ifndef atomic64_fetch_andnot_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_andnot_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_andnot_relaxed(i, v);@@ -1821,7 +1823,7 @@ atomic64_fetch_andnot_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_andnot_release -static inline s64 +static __always_inline s64atomic64_fetch_andnot_release (s64 i,atomic64_t *v) {__atomic_release_fence ();@@ -1831,7 +1833,7 @@ atomic64_fetch_andnot_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_andnot -static inline s64 +static __always_inline s64atomic64_fetch_andnot (s64 i,atomic64_t *v) {s64 ret;@@ -1852,7 +1854,7 @@ atomic64_fetch_andnot(s64 i, atomic64_t *v) #else /* atomic64_fetch_or_relaxed */ #ifndef atomic64_fetch_or_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_or_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_or_relaxed(i, v);@@ -1863,7 +1865,7 @@ atomic64_fetch_or_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_or_release -static inline s64 +static __always_inline s64atomic64_fetch_or_release (s64 i,atomic64_t *v) {__atomic_release_fence ();@@ -1873,7 +1875,7 @@ atomic64_fetch_or_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_or -static inline s64 +static __always_inline s64atomic64_fetch_or (s64 i,atomic64_t *v) {s64 ret;@@ -1894,7 +1896,7 @@ atomic64_fetch_or(s64 i, atomic64_t *v) #else /* atomic64_fetch_xor_relaxed */ #ifndef atomic64_fetch_xor_acquire -static inline s64 +static __always_inline s64 atomic64_fetch_xor_acquire(s64 i, atomic64_t *v) { s64 ret = atomic64_fetch_xor_relaxed(i, v);@@ -1905,7 +1907,7 @@ atomic64_fetch_xor_acquire(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_xor_release -static inline s64 +static __always_inline s64atomic64_fetch_xor_release (s64 i,atomic64_t *v) {__atomic_release_fence ();@@ -1915,7 +1917,7 @@ atomic64_fetch_xor_release(s64 i, atomic64_t *v)#endif #ifndef atomic64_fetch_xor -static inline s64 +static __always_inline s64atomic64_fetch_xor (s64 i,atomic64_t *v) {s64 ret;@@ -1936,7 +1938,7 @@ atomic64_fetch_xor(s64 i, atomic64_t *v) #else /* atomic64_xchg_relaxed */ #ifndef atomic64_xchg_acquire -static inline s64 +static __always_inline s64 atomic64_xchg_acquire(atomic64_t *v, s64 i) { s64 ret = atomic64_xchg_relaxed(v, i);@@ -1947,7 +1949,7 @@ atomic64_xchg_acquire(atomic64_t *v, s64 i)#endif #ifndef atomic64_xchg_release -static inline s64 +static __always_inline s64atomic64_xchg_release (atomic64_t *v,s64 i) {__atomic_release_fence ();@@ -1957,7 +1959,7 @@ atomic64_xchg_release(atomic64_t *v, s64 i)#endif #ifndef atomic64_xchg -static inline s64 +static __always_inline s64atomic64_xchg (atomic64_t *v,s64 i) {s64 ret;@@ -1978,7 +1980,7 @@ atomic64_xchg(atomic64_t *v, s64 i) #else /* atomic64_cmpxchg_relaxed */ #ifndef atomic64_cmpxchg_acquire -static inline s64 +static __always_inline s64 atomic64_cmpxchg_acquire(atomic64_t *v, s64 old, s64 new) { s64 ret = atomic64_cmpxchg_relaxed(v, old, new);@@ -1989,7 +1991,7 @@ atomic64_cmpxchg_acquire(atomic64_t *v, s64 old, s64 new)#endif #ifndef atomic64_cmpxchg_release -static inline s64 +static __always_inline s64atomic64_cmpxchg_release (atomic64_t *v,s64 old,s64 new) {__atomic_release_fence ();@@ -1999,7 +2001,7 @@ atomic64_cmpxchg_release(atomic64_t *v, s64 old, s64 new)#endif #ifndef atomic64_cmpxchg -static inline s64 +static __always_inline s64atomic64_cmpxchg (atomic64_t *v,s64 old,s64 new) {s64 ret;@@ -2021,7 +2023,7 @@ atomic64_cmpxchg(atomic64_t *v, s64 old, s64 new)#endif /* atomic64_try_cmpxchg */ #ifndef atomic64_try_cmpxchg -static inline bool +static __always_inline boolatomic64_try_cmpxchg (atomic64_t *v,s64 *old,s64 new) {s64 r, o = *old;@@ -2034,7 +2036,7 @@ atomic64_try_cmpxchg(atomic64_t *v, s64 *old, s64 new)#endif #ifndef atomic64_try_cmpxchg_acquire -static inline bool +static __always_inline boolatomic64_try_cmpxchg_acquire (atomic64_t *v,s64 *old,s64 new) {s64 r, o = *old;@@ -2047,7 +2049,7 @@ atomic64_try_cmpxchg_acquire(atomic64_t *v, s64 *old, s64 new)#endif #ifndef atomic64_try_cmpxchg_release -static inline bool +static __always_inline boolatomic64_try_cmpxchg_release (atomic64_t *v,s64 *old,s64 new) {s64 r, o = *old;@@ -2060,7 +2062,7 @@ atomic64_try_cmpxchg_release(atomic64_t *v, s64 *old, s64 new)#endif #ifndef atomic64_try_cmpxchg_relaxed -static inline bool +static __always_inline boolatomic64_try_cmpxchg_relaxed (atomic64_t *v,s64 *old,s64 new) {s64 r, o = *old;@@ -2075,7 +2077,7 @@ atomic64_try_cmpxchg_relaxed(atomic64_t *v, s64 *old, s64 new) #else /* atomic64_try_cmpxchg_relaxed */ #ifndef atomic64_try_cmpxchg_acquire -static inline bool +static __always_inline bool atomic64_try_cmpxchg_acquire(atomic64_t *v, s64 *old, s64 new) { bool ret = atomic64_try_cmpxchg_relaxed(v, old, new);@@ -2086,7 +2088,7 @@ atomic64_try_cmpxchg_acquire(atomic64_t *v, s64 *old, s64 new)#endif #ifndef atomic64_try_cmpxchg_release -static inline bool +static __always_inline boolatomic64_try_cmpxchg_release (atomic64_t *v,s64 *old,s64 new) {__atomic_release_fence ();@@ -2096,7 +2098,7 @@ atomic64_try_cmpxchg_release(atomic64_t *v, s64 *old, s64 new)#endif #ifndef atomic64_try_cmpxchg -static inline bool +static __always_inline boolatomic64_try_cmpxchg (atomic64_t *v,s64 *old,s64 new) {bool ret;@@ -2120,7 +2122,7 @@ atomic64_try_cmpxchg(atomic64_t *v, s64 *old, s64 new)* true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline boolatomic64_sub_and_test (s64 i,atomic64_t *v) {return atomic64_sub_return (i, v) ==0 ;@@ -2137,7 +2139,7 @@ atomic64_sub_and_test(s64 i, atomic64_t *v)* returns true if the result is 0, or false for all other * cases. */ -static inline bool +static __always_inline boolatomic64_dec_and_test (atomic64_t *v) {return atomic64_dec_return (v) ==0 ;@@ -2154,7 +2156,7 @@ atomic64_dec_and_test(atomic64_t *v)* and returns true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline boolatomic64_inc_and_test (atomic64_t *v) {return atomic64_inc_return (v) ==0 ;@@ -2172,7 +2174,7 @@ atomic64_inc_and_test(atomic64_t *v)* if the result is negative, or false when * result is greater than or equal to zero. */ -static inline bool +static __always_inline boolatomic64_add_negative (s64 i,atomic64_t *v) {return atomic64_add_return (i, v) <0 ;@@ -2190,7 +2192,7 @@ atomic64_add_negative(s64 i, atomic64_t *v)* Atomically adds @a to @v, so long as @v was not already @u. * Returns original value of @v */ -static inline s64 +static __always_inline s64atomic64_fetch_add_unless (atomic64_t *v,s64 a,s64 u) {s64 c =atomic64_read (v);@@ -2215,7 +2217,7 @@ atomic64_fetch_add_unless(atomic64_t *v, s64 a, s64 u)* Atomically adds @a to @v, if @v was not already @u. * Returns true if the addition was done. */ -static inline bool +static __always_inline boolatomic64_add_unless (atomic64_t *v,s64 a,s64 u) {return atomic64_fetch_add_unless (v, a, u) != u;@@ -2231,7 +2233,7 @@ atomic64_add_unless(atomic64_t *v, s64 a, s64 u)* Atomically increments @v by 1, if @v is non-zero. * Returns true if the increment was done. */ -static inline bool +static __always_inline boolatomic64_inc_not_zero (atomic64_t *v) {return atomic64_add_unless (v,1 ,0 );@@ -2240,7 +2242,7 @@ atomic64_inc_not_zero(atomic64_t *v)#endif #ifndef atomic64_inc_unless_negative -static inline bool +static __always_inline boolatomic64_inc_unless_negative (atomic64_t *v) {s64 c =atomic64_read (v);@@ -2256,7 +2258,7 @@ atomic64_inc_unless_negative(atomic64_t *v)#endif #ifndef atomic64_dec_unless_positive -static inline bool +static __always_inline boolatomic64_dec_unless_positive (atomic64_t *v) {s64 c =atomic64_read (v);@@ -2272,7 +2274,7 @@ atomic64_dec_unless_positive(atomic64_t *v)#endif #ifndef atomic64_dec_if_positive -static inline s64 +static __always_inline s64atomic64_dec_if_positive (atomic64_t *v) {s64 dec, c =atomic64_read (v);@@ -2292,4 +2294,4 @@ atomic64_dec_if_positive(atomic64_t *v)#define atomic64_cond_read_relaxed (v, c) smp_cond_load_relaxed(&(v)->counter, (c))#endif /* _LINUX_ATOMIC_FALLBACK_H */ -// 25de4a2804d70f57e994fe3b419148658bb5378a +// baaf45f4c24ed88ceae58baca39d7fd80bb8101b scripts/atomic/fallbacks/acquire +1
-1@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}${name}${sfx}_acquire(${params}) { ${ret} ret = ${atomic}_${pfx}${name}${sfx}_relaxed(${args});scripts/atomic/fallbacks/add_negative +1
-1@@ -8,7 +8,7 @@ cat <<EOF * if the result is negative, or false when * result is greater than or equal to zero. */ -static inline bool +static __always_inline bool ${atomic}_add_negative(${int} i, ${atomic}_t *v) { return ${atomic}_add_return(i, v) < 0;scripts/atomic/fallbacks/add_unless +1
-1@@ -8,7 +8,7 @@ cat << EOF * Atomically adds @a to @v, if @v was not already @u. * Returns true if the addition was done. */ -static inline bool +static __always_inline bool ${atomic}_add_unless(${atomic}_t *v, ${int} a, ${int} u) { return ${atomic}_fetch_add_unless(v, a, u) != u;scripts/atomic/fallbacks/andnot +1
-1@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}andnot${sfx}${order}(${int} i, ${atomic}_t *v) { ${retstmt}${atomic}_${pfx}and${sfx}${order}(~i, v);scripts/atomic/fallbacks/dec +1
-1@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}dec${sfx}${order}(${atomic}_t *v) { ${retstmt}${atomic}_${pfx}sub${sfx}${order}(1, v);scripts/atomic/fallbacks/dec_and_test +1
-1@@ -7,7 +7,7 @@ cat <<EOF * returns true if the result is 0, or false for all other * cases. */ -static inline bool +static __always_inline bool ${atomic}_dec_and_test(${atomic}_t *v) { return ${atomic}_dec_return(v) == 0;scripts/atomic/fallbacks/dec_if_positive +1
-1@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_dec_if_positive(${atomic}_t *v) { ${int} dec, c = ${atomic}_read(v);scripts/atomic/fallbacks/dec_unless_positive +1
-1@@ -1,5 +1,5 @@ cat <<EOF -static inline bool +static __always_inline bool ${atomic}_dec_unless_positive(${atomic}_t *v) { ${int} c = ${atomic}_read(v);scripts/atomic/fallbacks/fence +1
-1@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}${name}${sfx}(${params}) { ${ret} ret;scripts/atomic/fallbacks/fetch_add_unless +1
-1@@ -8,7 +8,7 @@ cat << EOF * Atomically adds @a to @v, so long as @v was not already @u. * Returns original value of @v */ -static inline ${int} +static __always_inline ${int} ${atomic}_fetch_add_unless(${atomic}_t *v, ${int} a, ${int} u) { ${int} c = ${atomic}_read(v);scripts/atomic/fallbacks/inc +1
-1@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}inc${sfx}${order}(${atomic}_t *v) { ${retstmt}${atomic}_${pfx}add${sfx}${order}(1, v);scripts/atomic/fallbacks/inc_and_test +1
-1@@ -7,7 +7,7 @@ cat <<EOF * and returns true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline bool ${atomic}_inc_and_test(${atomic}_t *v) { return ${atomic}_inc_return(v) == 0;scripts/atomic/fallbacks/inc_not_zero +1
-1@@ -6,7 +6,7 @@ cat <<EOF * Atomically increments @v by 1, if @v is non-zero. * Returns true if the increment was done. */ -static inline bool +static __always_inline bool ${atomic}_inc_not_zero(${atomic}_t *v) { return ${atomic}_add_unless(v, 1, 0);scripts/atomic/fallbacks/inc_unless_negative +1
-1@@ -1,5 +1,5 @@ cat <<EOF -static inline bool +static __always_inline bool ${atomic}_inc_unless_negative(${atomic}_t *v) { ${int} c = ${atomic}_read(v);scripts/atomic/fallbacks/read_acquire +1
-1@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_read_acquire(const ${atomic}_t *v) { return smp_load_acquire(&(v)->counter);scripts/atomic/fallbacks/release +1
-1@@ -1,5 +1,5 @@ cat <<EOF -static inline ${ret} +static __always_inline ${ret} ${atomic}_${pfx}${name}${sfx}_release(${params}) { __atomic_release_fence();scripts/atomic/fallbacks/set_release +1
-1@@ -1,5 +1,5 @@ cat <<EOF -static inline void +static __always_inline void ${atomic}_set_release(${atomic}_t *v, ${int} i) { smp_store_release(&(v)->counter, i);scripts/atomic/fallbacks/sub_and_test +1
-1@@ -8,7 +8,7 @@ cat <<EOF * true if the result is zero, or false for all * other cases. */ -static inline bool +static __always_inline bool ${atomic}_sub_and_test(${int} i, ${atomic}_t *v) { return ${atomic}_sub_return(i, v) == 0;scripts/atomic/fallbacks/try_cmpxchg +1
-1@@ -1,5 +1,5 @@ cat <<EOF -static inline bool +static __always_inline bool ${atomic}_try_cmpxchg${order}(${atomic}_t *v, ${int} *old, ${int} new) { ${int} r, o = *old;scripts/atomic/gen-atomic-fallback.sh +2
-0@@ -149,6 +149,8 @@ cat << EOF #ifndef _LINUX_ATOMIC_FALLBACK_H #define _LINUX_ATOMIC_FALLBACK_H +#include <linux/compiler.h> + EOF for xchg in "xchg" "cmpxchg" "cmpxchg64"; do
Peter Zijlstra
maintainerRe: [PATCH v3 18/22] asm-generic/atomic: Use __always_inline for fallback wrappers
Quoted 9 lines · Paul E. McKenney
Quoted 8 lines · Peter Zijlstra
While the fallback wrappers aren't pure wrappers, they are trivial nonetheless, and the function they wrap should determine the final inlining policy.
For x86 tinyconfig we observe:
- vmlinux baseline: 1315988
- vmlinux with patch: 1315928 (-60 bytes)
Quoted 6 lines
Quoted 4 lines
Suggested-by Mark Rutland <[email protected]>Signed-off-by Marco Elver <[email protected]>Acked-by Mark Rutland <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>And this one and the previous one are also already in -tip, FYI.
That's where I found them ;-) Stole them from tip/locking/kcsan.
Paul E. McKenney
maintainerRe: [PATCH v3 18/22] asm-generic/atomic: Use __always_inline for fallback wrappers
Quoted 10 lines · Peter Zijlstra
Quoted 9 lines · Paul E. McKenney
Quoted 8 lines · Peter Zijlstra
While the fallback wrappers aren't pure wrappers, they are trivial nonetheless, and the function they wrap should determine the final inlining policy.
For x86 tinyconfig we observe:
- vmlinux baseline: 1315988
- vmlinux with patch: 1315928 (-60 bytes)
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
Suggested-by Mark Rutland <[email protected]>Signed-off-by Marco Elver <[email protected]>Acked-by Mark Rutland <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>And this one and the previous one are also already in -tip, FYI.
That's where I found them ;-) Stole them from tip/locking/kcsan.
As long as the heist is official, then. ;-)
Thanx, Paul
Peter Zijlstra
maintainerPATCH v3 19/22 compiler: Simple READ/WRITE_ONCE() implementations
In reply to Peter ZijlstraBecause I need WRITE_ONCE_NOCHECK() and in anticipation of Will's READ_ONCE rewrite, provide __{READ,WRITE}_ONCE_SCALAR().
--- include/linux/compiler.h | 8 ++++++++ 1 file changed, 8 insertions(+)
include/linux/compiler.h +8 -0
@@ -289,6 +289,14 @@ unsigned long read_word_at_a_time(const __u.__val; \ }) +#define __READ_ONCE_SCALAR (x) \ + (*(const volatile typeof(x) *)&(x)) + +#define __WRITE_ONCE_SCALAR (x, val) \ +do { \ + *(volatile typeof(x) *)&(x) = val; \ +} while (0) +#endif /* __KERNEL__ */ /*
Peter Zijlstra
maintainerPATCH v3 20/22 locking/atomics: Flip fallbacks and instrumentation
In reply to Peter ZijlstraCurrently instrumentation of atomic primitives is done at the architecture level, while composites or fallbacks are provided at the generic level.
The result is that there are no uninstrumented variants of the fallbacks. Since there is now need of such (see the next patch), invert this ordering.
Doing this means moving the instrumentation into the generic code as well as having (for now) two variants of the fallbacks.
Notes:
- the various *cond_read* primitives are not proper fallbacks and got moved into linux/atomic.c. No arch_ variants are generated because the base primitives smp_cond_load*() are instrumented.
- once all architectures are moved over to arch_atomic_ we can remove one of the fallback variants and reclaim some 2300 lines.
- atomic_{read,set}*() are no longer double-instrumented
--- arch/arm64/include/asm/atomic.h | 6 arch/x86/include/asm/atomic.h | 17 arch/x86/include/asm/atomic64_32.h | 9 arch/x86/include/asm/atomic64_64.h | 15 include/linux/atomic-arch-fallback.h | 2291 +++++++++++++++++++++++++++ include/linux/atomic-fallback.h | 8 include/linux/atomic.h | 11 scripts/atomic/fallbacks/acquire | 4 scripts/atomic/fallbacks/add_negative | 6 scripts/atomic/fallbacks/add_unless | 6 scripts/atomic/fallbacks/andnot | 4 scripts/atomic/fallbacks/dec | 4 scripts/atomic/fallbacks/dec_and_test | 6 scripts/atomic/fallbacks/dec_if_positive | 6 scripts/atomic/fallbacks/dec_unless_positive | 6 scripts/atomic/fallbacks/fence | 4 scripts/atomic/fallbacks/fetch_add_unless | 8 scripts/atomic/fallbacks/inc | 4 scripts/atomic/fallbacks/inc_and_test | 6 scripts/atomic/fallbacks/inc_not_zero | 6 scripts/atomic/fallbacks/inc_unless_negative | 6 scripts/atomic/fallbacks/read_acquire | 2 scripts/atomic/fallbacks/release | 4 scripts/atomic/fallbacks/set_release | 2 scripts/atomic/fallbacks/sub_and_test | 6 scripts/atomic/fallbacks/try_cmpxchg | 4 scripts/atomic/gen-atomic-fallback.sh | 29 scripts/atomic/gen-atomics.sh | 5 28 files changed, 2403 insertions(+), 82 deletions(-)
arch/arm64/include/asm/atomic.h +3 -3
@@ -101,8 +101,8 @@ static inline long arch_atomic64_dec_if_#define ATOMIC_INIT (i) { (i) } -#define arch_atomic_read (v) READ_ONCE((v)->counter) -#define arch_atomic_set (v, i) WRITE_ONCE(((v)->counter), (i)) +#define arch_atomic_read (v) __READ_ONCE_SCALAR((v)->counter) +#define arch_atomic_set (v, i) __WRITE_ONCE_SCALAR(((v)->counter), (i))#define arch_atomic_add_return_relaxed arch_atomic_add_return_relaxed#define arch_atomic_add_return_acquire arch_atomic_add_return_acquire
@@ -225,6 +225,6 @@ static inline long arch_atomic64_dec_if_#define arch_atomic64_dec_if_positive arch_atomic64_dec_if_positive -#include <asm-generic/atomic-instrumented.h> +#define ARCH_ATOMIC #endif /* __ASM_ATOMIC_H */
arch/x86/include/asm/atomic.h +13 -4
@@ -28,7 +28,7 @@ static __always_inline int arch_atomic_r* Note for KASAN: we deliberately don't use READ_ONCE_NOCHECK() here, * it's non-inlined function that increases binary size and stack usage. */ -return READ_ONCE ((v)->counter); +return __READ_ONCE_SCALAR ((v)->counter); }/**
@@ -40,7 +40,7 @@ static __always_inline int arch_atomic_r*/ static __always_inline void arch_atomic_set(atomic_t *v, int i) { -WRITE_ONCE (v->counter, i); +__WRITE_ONCE_SCALAR (v->counter, i); }/**
@@ -166,6 +166,7 @@ static __always_inline int arch_atomic_a {return i +xadd (&v->counter, i); } +#define arch_atomic_add_return arch_atomic_add_return/** * arch_atomic_sub_return - subtract integer and return
@@ -178,32 +179,37 @@ static __always_inline int arch_atomic_s {return arch_atomic_add_return (-i, v); } +#define arch_atomic_sub_return arch_atomic_sub_return static __always_inline int arch_atomic_fetch_add(int i, atomic_t *v) {return xadd (&v->counter, i); } +#define arch_atomic_fetch_add arch_atomic_fetch_add static __always_inline int arch_atomic_fetch_sub(int i, atomic_t *v) {return xadd (&v->counter, -i); } +#define arch_atomic_fetch_sub arch_atomic_fetch_sub static __always_inline int arch_atomic_cmpxchg(atomic_t *v, int old, int new) {return arch_cmpxchg (&v->counter, old, new); } +#define arch_atomic_cmpxchg arch_atomic_cmpxchg -#define arch_atomic_try_cmpxchg arch_atomic_try_cmpxchg static __always_inline bool arch_atomic_try_cmpxchg(atomic_t *v, int *old, int new) {return try_cmpxchg (&v->counter, old, new); } +#define arch_atomic_try_cmpxchg arch_atomic_try_cmpxchgstatic inline int arch_atomic_xchg (atomic_t *v,int new) {return arch_xchg (&v->counter, new); } +#define arch_atomic_xchg arch_atomic_xchgstatic inline void arch_atomic_and (int i,atomic_t *v) {
@@ -221,6 +227,7 @@ static inline int arch_atomic_fetch_and(return val; } +#define arch_atomic_fetch_and arch_atomic_fetch_andstatic inline void arch_atomic_or (int i,atomic_t *v) {
@@ -238,6 +245,7 @@ static inline int arch_atomic_fetch_or(ireturn val; } +#define arch_atomic_fetch_or arch_atomic_fetch_orstatic inline void arch_atomic_xor (int i,atomic_t *v) {
@@ -255,6 +263,7 @@ static inline int arch_atomic_fetch_xor(return val; } +#define arch_atomic_fetch_xor arch_atomic_fetch_xor#ifdef CONFIG_X86_32 # include <asm/atomic64_32.h>
@@ -262,6 +271,6 @@ static inline int arch_atomic_fetch_xor(# include <asm/atomic64_64.h> #endif -#include <asm-generic/atomic-instrumented.h> +#define ARCH_ATOMIC #endif /* _ASM_X86_ATOMIC_H */
arch/x86/include/asm/atomic64_32.h +9 -0
@@ -75,6 +75,7 @@ static inline s64 arch_atomic64_cmpxchg( {return arch_cmpxchg64 (&v->counter, o, n); } +#define arch_atomic64_cmpxchg arch_atomic64_cmpxchg/** * arch_atomic64_xchg - xchg atomic64 variable
@@ -94,6 +95,7 @@ static inline s64 arch_atomic64_xchg(ato : "memory");return o; } +#define arch_atomic64_xchg arch_atomic64_xchg/** * arch_atomic64_set - set atomic64 variable
@@ -138,6 +140,7 @@ static inline s64 arch_atomic64_add_retu ASM_NO_INPUT_CLOBBER("memory"));return i; } +#define arch_atomic64_add_return arch_atomic64_add_return/* * Other variants with different arithmetic operators:
@@ -149,6 +152,7 @@ static inline s64 arch_atomic64_sub_retu ASM_NO_INPUT_CLOBBER("memory"));return i; } +#define arch_atomic64_sub_return arch_atomic64_sub_returnstatic inline s64 arch_atomic64_inc_return (atomic64_t *v) {
@@ -242,6 +246,7 @@ static inline int arch_atomic64_add_unle "S" (v) : "memory"); return (int)a; } +#define arch_atomic64_add_unless arch_atomic64_add_unlessstatic inline int arch_atomic64_inc_not_zero (atomic64_t *v) {
@@ -281,6 +286,7 @@ static inline s64 arch_atomic64_fetch_anreturn old; } +#define arch_atomic64_fetch_and arch_atomic64_fetch_andstatic inline void arch_atomic64_or (s64 i,atomic64_t *v) {
@@ -299,6 +305,7 @@ static inline s64 arch_atomic64_fetch_orreturn old; } +#define arch_atomic64_fetch_or arch_atomic64_fetch_orstatic inline void arch_atomic64_xor (s64 i,atomic64_t *v) {
@@ -317,6 +324,7 @@ static inline s64 arch_atomic64_fetch_xoreturn old; } +#define arch_atomic64_fetch_xor arch_atomic64_fetch_xorstatic inline s64 arch_atomic64_fetch_add (s64 i,atomic64_t *v) {
@@ -327,6 +335,7 @@ static inline s64 arch_atomic64_fetch_adreturn old; } +#define arch_atomic64_fetch_add arch_atomic64_fetch_add#define arch_atomic64_fetch_sub (i, v) arch_atomic64_fetch_add(-(i), (v))
arch/x86/include/asm/atomic64_64.h +12 -3
@@ -19,7 +19,7 @@*/ static inline s64 arch_atomic64_read (const atomic64_t *v) { -return READ_ONCE ((v)->counter); +return __READ_ONCE_SCALAR ((v)->counter); }/**
@@ -31,7 +31,7 @@ static inline s64 arch_atomic64_read(con*/ static inline void arch_atomic64_set (atomic64_t *v,s64 i) { -WRITE_ONCE (v->counter, i); +__WRITE_ONCE_SCALAR (v->counter, i); }/**
@@ -159,37 +159,43 @@ static __always_inline s64 arch_atomic64 {return i +xadd (&v->counter, i); } +#define arch_atomic64_add_return arch_atomic64_add_returnstatic inline s64 arch_atomic64_sub_return (s64 i,atomic64_t *v) {return arch_atomic64_add_return (-i, v); } +#define arch_atomic64_sub_return arch_atomic64_sub_returnstatic inline s64 arch_atomic64_fetch_add (s64 i,atomic64_t *v) {return xadd (&v->counter, i); } +#define arch_atomic64_fetch_add arch_atomic64_fetch_addstatic inline s64 arch_atomic64_fetch_sub (s64 i,atomic64_t *v) {return xadd (&v->counter, -i); } +#define arch_atomic64_fetch_sub arch_atomic64_fetch_substatic inline s64 arch_atomic64_cmpxchg (atomic64_t *v,s64 old,s64 new) {return arch_cmpxchg (&v->counter, old, new); } +#define arch_atomic64_cmpxchg arch_atomic64_cmpxchg -#define arch_atomic64_try_cmpxchg arch_atomic64_try_cmpxchg static __always_inline bool arch_atomic64_try_cmpxchg(atomic64_t *v, s64 *old, s64 new) {return try_cmpxchg (&v->counter, old, new); } +#define arch_atomic64_try_cmpxchg arch_atomic64_try_cmpxchgstatic inline s64 arch_atomic64_xchg (atomic64_t *v,s64 new) {return arch_xchg (&v->counter, new); } +#define arch_atomic64_xchg arch_atomic64_xchgstatic inline void arch_atomic64_and (s64 i,atomic64_t *v) {
@@ -207,6 +213,7 @@ static inline s64 arch_atomic64_fetch_an }while (!arch_atomic64_try_cmpxchg (v, &val, val & i));return val; } +#define arch_atomic64_fetch_and arch_atomic64_fetch_andstatic inline void arch_atomic64_or (s64 i,atomic64_t *v) {
@@ -224,6 +231,7 @@ static inline s64 arch_atomic64_fetch_or }while (!arch_atomic64_try_cmpxchg (v, &val, val | i));return val; } +#define arch_atomic64_fetch_or arch_atomic64_fetch_orstatic inline void arch_atomic64_xor (s64 i,atomic64_t *v) {
@@ -241,5 +249,6 @@ static inline s64 arch_atomic64_fetch_xo } while (!arch_atomic64_try_cmpxchg(v, &val, val ^ i));return val; } +#define arch_atomic64_fetch_xor arch_atomic64_fetch_xor#endif /* _ASM_X86_ATOMIC64_64_H */
include/linux/atomic-arch-fallback.h new file +2291 -0
2,291 lines not on this page · raw message
include/linux/atomic-fallback.h +1 -7
@@ -1180,9 +1180,6 @@ atomic_dec_if_positive(atomic_t *v)#define atomic_dec_if_positive atomic_dec_if_positive#endif -#define atomic_cond_read_acquire (v, c) smp_cond_load_acquire(&(v)->counter, (c)) -#define atomic_cond_read_relaxed (v, c) smp_cond_load_relaxed(&(v)->counter, (c)) -#ifdef CONFIG_GENERIC_ATOMIC64 #include <asm-generic/atomic64.h> #endif
@@ -2290,8 +2287,5 @@ atomic64_dec_if_positive(atomic64_t *v)#define atomic64_dec_if_positive atomic64_dec_if_positive#endif -#define atomic64_cond_read_acquire (v, c) smp_cond_load_acquire(&(v)->counter, (c)) -#define atomic64_cond_read_relaxed (v, c) smp_cond_load_relaxed(&(v)->counter, (c)) -#endif /* _LINUX_ATOMIC_FALLBACK_H */ -// baaf45f4c24ed88ceae58baca39d7fd80bb8101b +// 1fac0941c79bf0ae100723cc2ac9b94061f0b67a
include/linux/atomic.h +11 -0
@@ -25,6 +25,12 @@* See Documentation/memory-barriers.txt for ACQUIRE/RELEASE definitions. */ +#define atomic_cond_read_acquire (v, c) smp_cond_load_acquire(&(v)->counter, (c)) +#define atomic_cond_read_relaxed (v, c) smp_cond_load_relaxed(&(v)->counter, (c)) + +#define atomic64_cond_read_acquire (v, c) smp_cond_load_acquire(&(v)->counter, (c)) +#define atomic64_cond_read_relaxed (v, c) smp_cond_load_relaxed(&(v)->counter, (c)) +/* * The idea here is to build acquire/release variants by adding explicit * barriers on top of the relaxed variant. In the case where the relaxed
@@ -71,7 +77,12 @@ __ret; \ }) +#ifdef ARCH_ATOMIC +#include <linux/atomic-arch-fallback.h> +#include <asm-generic/atomic-instrumented.h> +#else #include <linux/atomic-fallback.h> +#endif #include <asm-generic/atomic-long.h>
scripts/atomic/fallbacks/acquire +2 -2
@@ -1,8 +1,8 @@ cat <<EOF static __always_inline ${ret} -${atomic}_${pfx}${name}${sfx}_acquire(${params}) +${arch}${atomic}_${pfx}${name}${sfx}_acquire(${params}) { - ${ret} ret = ${atomic}_${pfx}${name}${sfx}_relaxed(${args}); + ${ret} ret = ${arch}${atomic}_${pfx}${name}${sfx}_relaxed(${args}); __atomic_acquire_fence(); return ret; }
scripts/atomic/fallbacks/add_negative +3 -3
@@ -1,6 +1,6 @@ cat <<EOF /** - * ${atomic}_add_negative - add and test if negative + * ${arch}${atomic}_add_negative - add and test if negative * @i: integer value to add * @v: pointer of type ${atomic}_t *
@@ -9,8 +9,8 @@ cat <<EOF * result is greater than or equal to zero. */ static __always_inline bool -${atomic}_add_negative(${int} i, ${atomic}_t *v) +${arch}${atomic}_add_negative(${int} i, ${atomic}_t *v) { - return ${atomic}_add_return(i, v) < 0; + return ${arch}${atomic}_add_return(i, v) < 0; } EOF
scripts/atomic/fallbacks/add_unless +3 -3
@@ -1,6 +1,6 @@ cat << EOF /** - * ${atomic}_add_unless - add unless the number is already a given value + * ${arch}${atomic}_add_unless - add unless the number is already a given value * @v: pointer of type ${atomic}_t * @a: the amount to add to v... * @u: ...unless v is equal to u.
@@ -9,8 +9,8 @@ cat << EOF * Returns true if the addition was done. */ static __always_inline bool -${atomic}_add_unless(${atomic}_t *v, ${int} a, ${int} u) +${arch}${atomic}_add_unless(${atomic}_t *v, ${int} a, ${int} u) { - return ${atomic}_fetch_add_unless(v, a, u) != u; + return ${arch}${atomic}_fetch_add_unless(v, a, u) != u; } EOF
scripts/atomic/fallbacks/andnot +2 -2
@@ -1,7 +1,7 @@ cat <<EOF static __always_inline ${ret} -${atomic}_${pfx}andnot${sfx}${order}(${int} i, ${atomic}_t *v) +${arch}${atomic}_${pfx}andnot${sfx}${order}(${int} i, ${atomic}_t *v) { - ${retstmt}${atomic}_${pfx}and${sfx}${order}(~i, v); + ${retstmt}${arch}${atomic}_${pfx}and${sfx}${order}(~i, v); } EOF
scripts/atomic/fallbacks/dec +2 -2
@@ -1,7 +1,7 @@ cat <<EOF static __always_inline ${ret} -${atomic}_${pfx}dec${sfx}${order}(${atomic}_t *v) +${arch}${atomic}_${pfx}dec${sfx}${order}(${atomic}_t *v) { - ${retstmt}${atomic}_${pfx}sub${sfx}${order}(1, v); + ${retstmt}${arch}${atomic}_${pfx}sub${sfx}${order}(1, v); } EOF
scripts/atomic/fallbacks/dec_and_test +3 -3
@@ -1,6 +1,6 @@ cat <<EOF /** - * ${atomic}_dec_and_test - decrement and test + * ${arch}${atomic}_dec_and_test - decrement and test * @v: pointer of type ${atomic}_t * * Atomically decrements @v by 1 and
@@ -8,8 +8,8 @@ cat <<EOF * cases. */ static __always_inline bool -${atomic}_dec_and_test(${atomic}_t *v) +${arch}${atomic}_dec_and_test(${atomic}_t *v) { - return ${atomic}_dec_return(v) == 0; + return ${arch}${atomic}_dec_return(v) == 0; } EOF
scripts/atomic/fallbacks/dec_if_positive +3 -3
@@ -1,14 +1,14 @@ cat <<EOF static __always_inline ${ret} -${atomic}_dec_if_positive(${atomic}_t *v) +${arch}${atomic}_dec_if_positive(${atomic}_t *v) { - ${int} dec, c = ${atomic}_read(v); + ${int} dec, c = ${arch}${atomic}_read(v); do { dec = c - 1; if (unlikely(dec < 0)) break; - } while (!${atomic}_try_cmpxchg(v, &c, dec)); + } while (!${arch}${atomic}_try_cmpxchg(v, &c, dec)); return dec; }
scripts/atomic/fallbacks/dec_unless_positive +3 -3
@@ -1,13 +1,13 @@ cat <<EOF static __always_inline bool -${atomic}_dec_unless_positive(${atomic}_t *v) +${arch}${atomic}_dec_unless_positive(${atomic}_t *v) { - ${int} c = ${atomic}_read(v); + ${int} c = ${arch}${atomic}_read(v); do { if (unlikely(c > 0)) return false; - } while (!${atomic}_try_cmpxchg(v, &c, c - 1)); + } while (!${arch}${atomic}_try_cmpxchg(v, &c, c - 1)); return true; }
scripts/atomic/fallbacks/fence +2 -2
@@ -1,10 +1,10 @@ cat <<EOF static __always_inline ${ret} -${atomic}_${pfx}${name}${sfx}(${params}) +${arch}${atomic}_${pfx}${name}${sfx}(${params}) { ${ret} ret; __atomic_pre_full_fence(); - ret = ${atomic}_${pfx}${name}${sfx}_relaxed(${args}); + ret = ${arch}${atomic}_${pfx}${name}${sfx}_relaxed(${args}); __atomic_post_full_fence(); return ret; }
scripts/atomic/fallbacks/fetch_add_unless +4 -4
@@ -1,6 +1,6 @@ cat << EOF /** - * ${atomic}_fetch_add_unless - add unless the number is already a given value + * ${arch}${atomic}_fetch_add_unless - add unless the number is already a given value * @v: pointer of type ${atomic}_t * @a: the amount to add to v... * @u: ...unless v is equal to u.
@@ -9,14 +9,14 @@ cat << EOF * Returns original value of @v */ static __always_inline ${int} -${atomic}_fetch_add_unless(${atomic}_t *v, ${int} a, ${int} u) +${arch}${atomic}_fetch_add_unless(${atomic}_t *v, ${int} a, ${int} u) { - ${int} c = ${atomic}_read(v); + ${int} c = ${arch}${atomic}_read(v); do { if (unlikely(c == u)) break; - } while (!${atomic}_try_cmpxchg(v, &c, c + a)); + } while (!${arch}${atomic}_try_cmpxchg(v, &c, c + a)); return c; }
scripts/atomic/fallbacks/inc +2 -2
@@ -1,7 +1,7 @@ cat <<EOF static __always_inline ${ret} -${atomic}_${pfx}inc${sfx}${order}(${atomic}_t *v) +${arch}${atomic}_${pfx}inc${sfx}${order}(${atomic}_t *v) { - ${retstmt}${atomic}_${pfx}add${sfx}${order}(1, v); + ${retstmt}${arch}${atomic}_${pfx}add${sfx}${order}(1, v); } EOF
scripts/atomic/fallbacks/inc_and_test +3 -3
@@ -1,6 +1,6 @@ cat <<EOF /** - * ${atomic}_inc_and_test - increment and test + * ${arch}${atomic}_inc_and_test - increment and test * @v: pointer of type ${atomic}_t * * Atomically increments @v by 1
@@ -8,8 +8,8 @@ cat <<EOF * other cases. */ static __always_inline bool -${atomic}_inc_and_test(${atomic}_t *v) +${arch}${atomic}_inc_and_test(${atomic}_t *v) { - return ${atomic}_inc_return(v) == 0; + return ${arch}${atomic}_inc_return(v) == 0; } EOF
scripts/atomic/fallbacks/inc_not_zero +3 -3
@@ -1,14 +1,14 @@ cat <<EOF /** - * ${atomic}_inc_not_zero - increment unless the number is zero + * ${arch}${atomic}_inc_not_zero - increment unless the number is zero * @v: pointer of type ${atomic}_t * * Atomically increments @v by 1, if @v is non-zero. * Returns true if the increment was done. */ static __always_inline bool -${atomic}_inc_not_zero(${atomic}_t *v) +${arch}${atomic}_inc_not_zero(${atomic}_t *v) { - return ${atomic}_add_unless(v, 1, 0); + return ${arch}${atomic}_add_unless(v, 1, 0); } EOF
scripts/atomic/fallbacks/inc_unless_negative +3 -3
@@ -1,13 +1,13 @@ cat <<EOF static __always_inline bool -${atomic}_inc_unless_negative(${atomic}_t *v) +${arch}${atomic}_inc_unless_negative(${atomic}_t *v) { - ${int} c = ${atomic}_read(v); + ${int} c = ${arch}${atomic}_read(v); do { if (unlikely(c < 0)) return false; - } while (!${atomic}_try_cmpxchg(v, &c, c + 1)); + } while (!${arch}${atomic}_try_cmpxchg(v, &c, c + 1)); return true; }
scripts/atomic/fallbacks/read_acquire +1 -1
@@ -1,6 +1,6 @@ cat <<EOF static __always_inline ${ret} -${atomic}_read_acquire(const ${atomic}_t *v) +${arch}${atomic}_read_acquire(const ${atomic}_t *v) { return smp_load_acquire(&(v)->counter); }
scripts/atomic/fallbacks/release +2 -2
@@ -1,8 +1,8 @@ cat <<EOF static __always_inline ${ret} -${atomic}_${pfx}${name}${sfx}_release(${params}) +${arch}${atomic}_${pfx}${name}${sfx}_release(${params}) { __atomic_release_fence(); - ${retstmt}${atomic}_${pfx}${name}${sfx}_relaxed(${args}); + ${retstmt}${arch}${atomic}_${pfx}${name}${sfx}_relaxed(${args}); } EOF
scripts/atomic/fallbacks/set_release +1 -1
@@ -1,6 +1,6 @@ cat <<EOF static __always_inline void -${atomic}_set_release(${atomic}_t *v, ${int} i) +${arch}${atomic}_set_release(${atomic}_t *v, ${int} i) { smp_store_release(&(v)->counter, i); }
scripts/atomic/fallbacks/sub_and_test +3 -3
@@ -1,6 +1,6 @@ cat <<EOF /** - * ${atomic}_sub_and_test - subtract value from variable and test result + * ${arch}${atomic}_sub_and_test - subtract value from variable and test result * @i: integer value to subtract * @v: pointer of type ${atomic}_t *
@@ -9,8 +9,8 @@ cat <<EOF * other cases. */ static __always_inline bool -${atomic}_sub_and_test(${int} i, ${atomic}_t *v) +${arch}${atomic}_sub_and_test(${int} i, ${atomic}_t *v) { - return ${atomic}_sub_return(i, v) == 0; + return ${arch}${atomic}_sub_return(i, v) == 0; } EOF
scripts/atomic/fallbacks/try_cmpxchg +2 -2
@@ -1,9 +1,9 @@ cat <<EOF static __always_inline bool -${atomic}_try_cmpxchg${order}(${atomic}_t *v, ${int} *old, ${int} new) +${arch}${atomic}_try_cmpxchg${order}(${atomic}_t *v, ${int} *old, ${int} new) { ${int} r, o = *old; - r = ${atomic}_cmpxchg${order}(v, o, new); + r = ${arch}${atomic}_cmpxchg${order}(v, o, new); if (unlikely(r != o)) *old = r; return likely(r == o);
scripts/atomic/gen-atomic-fallback.sh +13 -16
@@ -2,10 +2,11 @@ # SPDX-License-Identifier: GPL-2.0 ATOMICDIR=$(dirname $0) +ARCH=$2 . ${ATOMICDIR}/atomic-tbl.sh -#gen_template_fallback(template, meta, pfx, name, sfx, order, atomic, int, args...) +#gen_template_fallback(template, meta, pfx, name, sfx, order, arch, atomic, int, args...) gen_template_fallback() { local template="$1"; shift
@@ -14,10 +15,11 @@ gen_template_fallback() local name="$1"; shift local sfx="$1"; shift local order="$1"; shift + local arch="$1"; shift local atomic="$1"; shift local int="$1"; shift - local atomicname="${atomic}_${pfx}${name}${sfx}${order}" + local atomicname="${arch}${atomic}_${pfx}${name}${sfx}${order}" local ret="$(gen_ret_type "${meta}" "${int}")" local retstmt="$(gen_ret_stmt "${meta}")"
@@ -32,7 +34,7 @@ gen_template_fallback() fi } -#gen_proto_fallback(meta, pfx, name, sfx, order, atomic, int, args...) +#gen_proto_fallback(meta, pfx, name, sfx, order, arch, atomic, int, args...) gen_proto_fallback() { local meta="$1"; shift
@@ -56,16 +58,17 @@ cat << EOF EOF } -#gen_proto_order_variants(meta, pfx, name, sfx, atomic, int, args...) +#gen_proto_order_variants(meta, pfx, name, sfx, arch, atomic, int, args...) gen_proto_order_variants() { local meta="$1"; shift local pfx="$1"; shift local name="$1"; shift local sfx="$1"; shift - local atomic="$1" + local arch="$1" + local atomic="$2" - local basename="${atomic}_${pfx}${name}${sfx}" + local basename="${arch}${atomic}_${pfx}${name}${sfx}" local template="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")"
@@ -94,7 +97,7 @@ gen_proto_order_variants() gen_basic_fallbacks "${basename}" if [ ! -z "${template}" ]; then - printf "#endif /* ${atomic}_${pfx}${name}${sfx} */\n\n" + printf "#endif /* ${arch}${atomic}_${pfx}${name}${sfx} */\n\n" gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@"
@@ -153,18 +156,15 @@ cat << EOF EOF -for xchg in "xchg" "cmpxchg" "cmpxchg64"; do +for xchg in "${ARCH}xchg" "${ARCH}cmpxchg" "${ARCH}cmpxchg64"; do gen_xchg_fallbacks "${xchg}" done grep '^[a-z]' "$1" | while read name meta args; do - gen_proto "${meta}" "${name}" "atomic" "int" ${args} + gen_proto "${meta}" "${name}" "${ARCH}" "atomic" "int" ${args} done cat <<EOF -#define atomic_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c)) -#define atomic_cond_read_relaxed(v, c) smp_cond_load_relaxed(&(v)->counter, (c)) - #ifdef CONFIG_GENERIC_ATOMIC64 #include <asm-generic/atomic64.h> #endif
@@ -172,12 +172,9 @@ cat <<EOF EOF grep '^[a-z]' "$1" | while read name meta args; do - gen_proto "${meta}" "${name}" "atomic64" "s64" ${args} + gen_proto "${meta}" "${name}" "${ARCH}" "atomic64" "s64" ${args} done cat <<EOF -#define atomic64_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c)) -#define atomic64_cond_read_relaxed(v, c) smp_cond_load_relaxed(&(v)->counter, (c)) - #endif /* _LINUX_ATOMIC_FALLBACK_H */ EOF
scripts/atomic/gen-atomics.sh +3 -2
@@ -10,10 +10,11 @@ LINUXDIR=${ATOMICDIR}/../.. cat <<EOF | gen-atomic-instrumented.sh asm-generic/atomic-instrumented.h gen-atomic-long.sh asm-generic/atomic-long.h +gen-atomic-fallback.sh linux/atomic-arch-fallback.h arch_ gen-atomic-fallback.sh linux/atomic-fallback.h EOF -while read script header; do - /bin/sh ${ATOMICDIR}/${script} ${ATOMICTBL} > ${LINUXDIR}/include/${header} +while read script header args; do + /bin/sh ${ATOMICDIR}/${script} ${ATOMICTBL} ${args} > ${LINUXDIR}/include/${header} HASH="$(sha1sum ${LINUXDIR}/include/${header})" HASH="${HASH%% *}" printf "// %s\n" "${HASH}" >> ${LINUXDIR}/include/${header}
Peter Zijlstra
maintainerPATCH v3 21/22 x86/int3: Avoid atomic instrumentation
In reply to Peter ZijlstraUse arch_atomic_*() and READ_ONCE_NOCHECK() to ensure nothing untoward creeps in and ruins things.
That is; this is the INT3 text poke handler, strictly limit the code that runs in it, lest we inadvertenly hit yet another INT3.
--- arch/x86/kernel/alternative.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/x86/kernel/alternative.c +3 -3
@@ -960,9 +960,9 @@ static struct bp_patching_desc *bp_desc;static __always_inline struct bp_patching_desc *try_get_desc(struct bp_patching_desc **descp) { -struct bp_patching_desc *desc =READ_ONCE (*descp);/* rcu_dereference */ +struct bp_patching_desc *desc =READ_ONCE_NOCHECK (*descp);/* rcu_dereference */ -if (!desc || !atomic_inc_not_zero (&desc->refs)) +if (!desc || !arch_atomic_inc_not_zero (&desc->refs))return NULL ;return desc;
@@ -971,7 +971,7 @@ struct bp_patching_desc *try_get_desc(st static __always_inline void put_desc(struct bp_patching_desc *desc) {smp_mb__before_atomic (); -atomic_dec (&desc->refs); +arch_atomic_dec (&desc->refs); } static __always_inline void *text_poke_addr(struct text_poke_loc *tp)
Peter Zijlstra
maintainerPATCH v3 22/22 x86/int3: Ensure that poke_int3_handler() is not sanitized
In reply to Peter ZijlstraIn order to ensure poke_int3_handler() is completely self contained -- we call this while we're modifying other text, imagine the fun of hitting another INT3 -- ensure that everything is without sanitize crud.
--- arch/x86/kernel/alternative.c | 4 ++-- arch/x86/kernel/traps.c | 2 +- include/linux/compiler-clang.h | 7 +++++++ include/linux/compiler-gcc.h | 6 ++++++ include/linux/compiler.h | 5 +++++ include/linux/compiler_attributes.h | 1 + lib/bsearch.c | 2 +- 7 files changed, 23 insertions(+), 4 deletions(-)
arch/x86/kernel/alternative.c +2 -2
@@ -979,7 +979,7 @@ static __always_inline void *text_poke_areturn _stext + tp->rel_addr; } -static int notrace patch_cmp(const void *key, const void *elt) +static int notrace __no_sanitize patch_cmp(const void *key, const void *elt) {struct text_poke_loc *tp = (struct text_poke_loc *) elt;
@@ -991,7 +991,7 @@ static int notrace patch_cmp(const void }NOKPROBE_SYMBOL (patch_cmp); -int notrace poke_int3_handler(struct pt_regs *regs) +int notrace __no_sanitize poke_int3_handler(struct pt_regs *regs) {struct bp_patching_desc *desc;struct text_poke_loc *tp;
arch/x86/kernel/traps.c +1 -1
@@ -496,7 +496,7 @@ dotraplinkage void do_general_protection }NOKPROBE_SYMBOL (do_general_protection); -dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code) +dotraplinkage void notrace __no_sanitize do_int3(struct pt_regs *regs, long error_code) {if (poke_int3_handler (regs))return ;
include/linux/compiler-clang.h +7 -0
@@ -24,6 +24,13 @@#define __no_sanitize_address#endif +#if __has_feature (undefined_sanitizer) +#define __no_sanitize_undefined \ + __atribute__((no_sanitize("undefined"))) +#else +#define __no_sanitize_undefined +#endif +/* * Not all versions of clang implement the the type-generic versions * of the builtin overflow checkers. Fortunately, clang implements
include/linux/compiler-gcc.h +6 -0
@@ -145,6 +145,12 @@#define __no_sanitize_address#endif +#if __has_attribute (__no_sanitize_undefined__) +#define __no_sanitize_undefined __attribute__((no_sanitize_undefined)) +#else +#define __no_sanitize_undefined +#endif +#if GCC_VERSION >=50100 #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1#endif
include/linux/compiler.h +5 -0
@@ -199,6 +199,7 @@ void __read_once_size(const volatile voi __READ_ONCE_SIZE; } +#define __no_kasan __no_sanitize_address#ifdef CONFIG_KASAN /* * We can't declare function 'inline' because __no_sanitize_address confilcts
@@ -274,6 +275,10 @@ static __always_inline void __write_once*/ #define READ_ONCE_NOCHECK (x) __READ_ONCE(x, 0) +#define __no_ubsan __no_sanitize_undefined + +#define __no_sanitize __no_kasan __no_ubsan +static __no_kasan_or_inline unsigned long read_word_at_a_time (const void *addr) {
include/linux/compiler_attributes.h +1 -0
@@ -41,6 +41,7 @@# define __GCC4_has_attribute___nonstring__ 0# define __GCC4_has_attribute___no_sanitize_address__ (__GNUC_MINOR__ >= 8)# define __GCC4_has_attribute___fallthrough__ 0 +# define __GCC4_has_attribute___no_sanitize_undefined__ (__GNUC_MINOR__ >= 9)#endif /*
lib/bsearch.c +1 -1
@@ -28,7 +28,7 @@* the key and elements in the array are of the same type, you can use * the same comparison function for both sort() and bsearch(). */ -void *bsearch (const void *key,const void *base,size_t num,size_t size, +void __no_sanitize *bsearch(const void *key, const void *base, size_t num, size_t size,cmp_func_t cmp) {const char *pivot;
Re: [PATCH v3 22/22] x86/int3: Ensure that poke_int3_handler() is not sanitized
Quoted 5 lines · Peter Zijlstra
In order to ensure
poke_int3_handler()is completely self contained -- we call this while we're modifying other text, imagine the fun of hitting another INT3 -- ensure that everything is without sanitize crud.
+kasan-dev
Hi Peter,
How do we hit another INT3 here? Does the code do out-of-bounds/use-after-free writes?
Debugging later silent memory corruption may be no less fun :)
Not sanitizing bsearch entirely is a bit unfortunate. We won't find any bugs in it when called from other sites too.
It may deserve a comment at least. Tomorrow I may want to remove __no_sanitize, just because sanitizing more is better, and no int3 test will fail to stop me from doing that...
It's quite fragile. Tomorrow poke_int3_handler handler calls more of fewer functions, and both ways it's not detected by anything. And if we ignore all by one function, it is still not helpful, right? Depending on failure cause/mode, using kasan_disable/enable_current may be a better option.
Quoted 120 lines
Cc Dmitry Vyukov <[email protected]>Cc Andrey Ryabinin <[email protected]>Reported-by Thomas Gleixner <[email protected]>Signed-off-by Peter Zijlstra (Intel) <[email protected]>--- arch/x86/kernel/alternative.c | 4 ++-- arch/x86/kernel/traps.c | 2 +- include/linux/compiler-clang.h | 7 +++++++ include/linux/compiler-gcc.h | 6 ++++++ include/linux/compiler.h | 5 +++++ include/linux/compiler_attributes.h | 1 + lib/bsearch.c | 2 +- 7 files changed, 23 insertions(+), 4 deletions(-)arch/x86/kernel/alternative.c +2
-2@@ -979,7 +979,7 @@ static __always_inline void *text_poke_areturn _stext + tp->rel_addr; } -static int notrace patch_cmp(const void *key, const void *elt) +static int notrace __no_sanitize patch_cmp(const void *key, const void *elt) {struct text_poke_loc *tp = (struct text_poke_loc *) elt;@@ -991,7 +991,7 @@ static int notrace patch_cmp(const void }NOKPROBE_SYMBOL (patch_cmp); -int notrace poke_int3_handler(struct pt_regs *regs) +int notrace __no_sanitize poke_int3_handler(struct pt_regs *regs) {struct bp_patching_desc *desc;struct text_poke_loc *tp;arch/x86/kernel/traps.c +1
-1@@ -496,7 +496,7 @@ dotraplinkage void do_general_protection }NOKPROBE_SYMBOL (do_general_protection); -dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code) +dotraplinkage void notrace __no_sanitize do_int3(struct pt_regs *regs, long error_code) {if (poke_int3_handler (regs))return ;include/linux/compiler-clang.h +7
-0@@ -24,6 +24,13 @@#define __no_sanitize_address#endif +#if __has_feature (undefined_sanitizer) +#define __no_sanitize_undefined \ + __atribute__((no_sanitize("undefined"))) +#else +#define __no_sanitize_undefined +#endif +/* * Not all versions of clang implement the the type-generic versions * of the builtin overflow checkers. Fortunately, clang implements include/linux/compiler-gcc.h +6
-0@@ -145,6 +145,12 @@#define __no_sanitize_address#endif +#if __has_attribute (__no_sanitize_undefined__) +#define __no_sanitize_undefined __attribute__((no_sanitize_undefined)) +#else +#define __no_sanitize_undefined +#endif +#if GCC_VERSION >=50100 #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1#endif include/linux/compiler.h +5
-0@@ -199,6 +199,7 @@ void __read_once_size(const volatile voi __READ_ONCE_SIZE; } +#define __no_kasan __no_sanitize_address#ifdef CONFIG_KASAN /* * We can't declare function 'inline' because __no_sanitize_address confilcts @@ -274,6 +275,10 @@ static __always_inline void __write_once*/ #define READ_ONCE_NOCHECK (x) __READ_ONCE(x, 0) +#define __no_ubsan __no_sanitize_undefined + +#define __no_sanitize __no_kasan __no_ubsan +static __no_kasan_or_inline unsigned long read_word_at_a_time (const void *addr) {include/linux/compiler_attributes.h +1
-0@@ -41,6 +41,7 @@# define __GCC4_has_attribute___nonstring__ 0# define __GCC4_has_attribute___no_sanitize_address__ (__GNUC_MINOR__ >= 8)# define __GCC4_has_attribute___fallthrough__ 0 +# define __GCC4_has_attribute___no_sanitize_undefined__ (__GNUC_MINOR__ >= 9)#endif /* lib/bsearch.c +1
-1@@ -28,7 +28,7 @@* the key and elements in the array are of the same type, you can use * the same comparison function for both sort() and bsearch(). */ -void *bsearch (const void *key,const void *base,size_t num,size_t size, +void __no_sanitize *bsearch(const void *key, const void *base, size_t num, size_t size,cmp_func_t cmp) {const char *pivot;
Peter Zijlstra
maintainerRe: [PATCH v3 22/22] x86/int3: Ensure that poke_int3_handler() is not sanitized
Quoted 7 lines · Dmitry Vyukov
Quoted 5 lines · Peter Zijlstra
In order to ensure
poke_int3_handler()is completely self contained -- we call this while we're modifying other text, imagine the fun of hitting another INT3 -- ensure that everything is without sanitize crud.
Quoted 5 lines
+kasan-dev
Hi Peter,
How do we hit another INT3 here?
INT3 is mostly the result of either kprobes (someone sticks a kprobe in the middle of *SAN) or self modifying text stuff (jump_labels, ftrace and soon static_call).
Quoted 3 lines
Does the code do
out-of-bounds/use-after-free writes?
Debugging later silent memory corruption may be no less fun :)
It all stinks, debugging a recursive exception is also not fun.
Quoted 2 lines
Not sanitizing bsearch entirely is a bit unfortunate. We won't find any bugs in it when called from other sites too.
Agreed.
Quoted 3 lines
It may deserve a comment at least. Tomorrow I may want to remove
__no_sanitize, just because sanitizing more is better, and no int3 test will fail to stop me from doing that...
If only I actually had a test-case for this :/
Quoted 2 lines
It's quite fragile. Tomorrow
poke_int3_handlerhandler calls more of fewer functions, and both ways it's not detected by anything.
Yes; not having tools for this is pretty annoying. In 0/n I asked Dan if smatch could do at least the normal tracing stuff, the compiler instrumentation bits are going to be far more difficult because smatch doesn't work at that level :/
(I actually have
Quoted 3 lines
And if we ignore all by one function, it is still not helpful, right? Depending on failure cause/mode, using kasan_disable/enable_current may be a better option.
kasan_disable_current() could mostly work; but only covers kasan, not ubsan or kcsan. It then also relies on kasan_disable_current() itself being notrace as well as all instrumentation functions itself (which I think is currently true because of mm/kasan/Makefile stripping CC_FLAGS_FTRACE).
But what stops someone from sticking a kprobe or #DB before you check that variable?
By inlining everything in poke_int3_handler() (except bsearch :/) we can mark the whole function off limits to everything and call it a day. That simplicity has been the guiding principle so far.
Alternatively we can provide an __always_inline variant of bsearch().
Peter Zijlstra
maintainerRe: [PATCH v3 22/22] x86/int3: Ensure that poke_int3_handler() is not sanitized
Quoted 9 lines · Peter Zijlstra
Quoted 2 lines
It's quite fragile. Tomorrow
poke_int3_handlerhandler calls more of fewer functions, and both ways it's not detected by anything.Yes; not having tools for this is pretty annoying. In 0/n I asked Dan if smatch could do at least the normal tracing stuff, the compiler instrumentation bits are going to be far more difficult because smatch doesn't work at that level :/
(I actually have
... and I stopped typing ...
I think I mean to say something like: ... more changes to poke_int3_handler() pending, but they're all quite simple).
Peter Zijlstra
maintainerRe: [PATCH v3 22/22] x86/int3: Ensure that poke_int3_handler() is not sanitized
In reply to Peter ZijlstraQuoted 5 lines · Peter Zijlstra
By inlining everything in
poke_int3_handler()(except bsearch :/) we can mark the whole function off limits to everything and call it a day. That simplicity has been the guiding principle so far.Alternatively we can provide an
__always_inlinevariant ofbsearch().
This reduces the __no_sanitize usage to just the exception entry (do_int3) and the critical function: poke_int3_handler().
Is this more acceptible?
arch/x86/kernel/alternative.c +4 -5
@@ -979,7 +979,7 @@ static __always_inline void *text_poke_areturn _stext + tp->rel_addr; } -static int notrace __no_sanitize patch_cmp(const void *key, const void *elt) +static __always_inline int patch_cmp(const void *key, const void *elt) {struct text_poke_loc *tp = (struct text_poke_loc *) elt;
@@ -989,7 +989,6 @@ static int notrace __no_sanitize patch_creturn 1 ;return 0 ; } -NOKPROBE_SYMBOL (patch_cmp); int notrace __no_sanitize poke_int3_handler(struct pt_regs *regs) {
@@ -1024,9 +1023,9 @@ int notrace __no_sanitize poke_int3_hand* Skip the binary search if there is a single member in the vector. */ if (unlikely (desc->nr_entries >1 )) { - tp =bsearch (ip, desc->vec, desc->nr_entries, -sizeof (struct text_poke_loc ), - patch_cmp); + tp =__bsearch (ip, desc->vec, desc->nr_entries, +sizeof (struct text_poke_loc ), + patch_cmp);if (!tp) goto out_put; }else {
include/linux/bsearch.h +24 -2
@@ -4,7 +4,29 @@#include <linux/types.h> -void *bsearch (const void *key,const void *base,size_t num,size_t size, -cmp_func_t cmp); +static __always_inline +void *__bsearch(const void *key, const void *base, size_t num, size_t size, cmp_func_t cmp) +{ +const char *pivot; +int result; + +while (num >0 ) { + pivot = base + (num >>1 ) * size; + result =cmp (key, pivot); + +if (result ==0 ) +return (void *)pivot; + +if (result >0 ) { + base = pivot + size; + num--; + } + num >>=1 ; + } + +return NULL ; +} + +extern void *bsearch (const void *key,const void *base,size_t num,size_t size,cmp_func_t cmp);#endif /* _LINUX_BSEARCH_H */
lib/bsearch.c +2 -20
@@ -28,27 +28,9 @@* the key and elements in the array are of the same type, you can use * the same comparison function for both sort() and bsearch(). */ -void __no_sanitize *bsearch(const void *key, const void *base, size_t num, size_t size, -cmp_func_t cmp) +void *bsearch (const void *key,const void *base,size_t num,size_t size,cmp_func_t cmp) { -const char *pivot; -int result; - -while (num >0 ) { - pivot = base + (num >>1 ) * size; - result =cmp (key, pivot); - -if (result ==0 ) -return (void *)pivot; - -if (result >0 ) { - base = pivot + size; - num--; - } - num >>=1 ; - } - -return NULL ; +__bsearch (key, base, num, size, cmp); }EXPORT_SYMBOL (bsearch);NOKPROBE_SYMBOL (bsearch);
Dmitry Vyukov
Acked-byRe: [PATCH v3 22/22] x86/int3: Ensure that poke_int3_handler() is not sanitized
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Peter Zijlstra
By inlining everything in
poke_int3_handler()(except bsearch :/) we can mark the whole function off limits to everything and call it a day. That simplicity has been the guiding principle so far.
Quoted 6 lines
Quoted 1 line
Alternatively we can provide an
__always_inlinevariant ofbsearch().This reduces the
__no_sanitizeusage to just the exception entry (do_int3) and the critical function:poke_int3_handler().Is this more acceptible?
Let's say it's more acceptable.
I guess there is no ideal solution here.
Just a straw man proposal: expected number of elements is large enough to make bsearch profitable, right? I see 1 is a common case, but the other case has multiple entries.
Quoted 98 lines
arch/x86/kernel/alternative.c +4
-5@@ -979,7 +979,7 @@ static __always_inline void *text_poke_areturn _stext + tp->rel_addr; } -static int notrace __no_sanitize patch_cmp(const void *key, const void *elt) +static __always_inline int patch_cmp(const void *key, const void *elt) {struct text_poke_loc *tp = (struct text_poke_loc *) elt;@@ -989,7 +989,6 @@ static int notrace __no_sanitize patch_creturn 1 ;return 0 ; } -NOKPROBE_SYMBOL (patch_cmp); int notrace __no_sanitize poke_int3_handler(struct pt_regs *regs) {@@ -1024,9 +1023,9 @@ int notrace __no_sanitize poke_int3_hand* Skip the binary search if there is a single member in the vector. */ if (unlikely (desc->nr_entries >1 )) { - tp =bsearch (ip, desc->vec, desc->nr_entries, -sizeof (struct text_poke_loc ), - patch_cmp); + tp =__bsearch (ip, desc->vec, desc->nr_entries, +sizeof (struct text_poke_loc ), + patch_cmp);if (!tp) goto out_put; }else {include/linux/bsearch.h +24
-2@@ -4,7 +4,29 @@#include <linux/types.h> -void *bsearch (const void *key,const void *base,size_t num,size_t size, -cmp_func_t cmp); +static __always_inline +void *__bsearch(const void *key, const void *base, size_t num, size_t size, cmp_func_t cmp) +{ +const char *pivot; +int result; + +while (num >0 ) { + pivot = base + (num >>1 ) * size; + result =cmp (key, pivot); + +if (result ==0 ) +return (void *)pivot; + +if (result >0 ) { + base = pivot + size; + num--; + } + num >>=1 ; + } + +return NULL ; +} + +extern void *bsearch (const void *key,const void *base,size_t num,size_t size,cmp_func_t cmp);#endif /* _LINUX_BSEARCH_H */ lib/bsearch.c +2
-20@@ -28,27 +28,9 @@* the key and elements in the array are of the same type, you can use * the same comparison function for both sort() and bsearch(). */ -void __no_sanitize *bsearch(const void *key, const void *base, size_t num, size_t size, -cmp_func_t cmp) +void *bsearch (const void *key,const void *base,size_t num,size_t size,cmp_func_t cmp) { -const char *pivot; -int result; - -while (num >0 ) { - pivot = base + (num >>1 ) * size; - result =cmp (key, pivot); - -if (result ==0 ) -return (void *)pivot; - -if (result >0 ) { - base = pivot + size; - num--; - } - num >>=1 ; - } - -return NULL ; +__bsearch (key, base, num, size, cmp); }EXPORT_SYMBOL (bsearch);NOKPROBE_SYMBOL (bsearch);
Peter Zijlstra
maintainerRe: [PATCH v3 22/22] x86/int3: Ensure that poke_int3_handler() is not sanitized
Quoted 10 lines · Dmitry Vyukov
Quoted 9 lines · Peter Zijlstra
Quoted 5 lines · Peter Zijlstra
By inlining everything in
poke_int3_handler()(except bsearch :/) we can mark the whole function off limits to everything and call it a day. That simplicity has been the guiding principle so far.Alternatively we can provide an
__always_inlinevariant ofbsearch().
Quoted 8 lines
Quoted 4 lines
This reduces the
__no_sanitizeusage to just the exception entry (do_int3) and the critical function:poke_int3_handler().Is this more acceptible?
Let's say it's more acceptable.
Acked-by Dmitry Vyukov <[email protected]>
Thanks, I'll go make it happen.
Quoted 5 lines
I guess there is no ideal solution here.
Just a straw man proposal: expected number of elements is large enough to make bsearch profitable, right? I see 1 is a common case, but the other case has multiple entries.
Latency was the consideration; the linear search would dramatically increase the runtime of the exception.
The current limit is 256 entries and we're hitting that quite often.
(we can trivially increase, but nobody has been able to show significant benefits for that -- as of yet)
Re: [PATCH v3 22/22] x86/int3: Ensure that poke_int3_handler() is not sanitized
Quoted 29 lines · Peter Zijlstra
Quoted 10 lines · Dmitry Vyukov
Quoted 9 lines · Peter Zijlstra
Quoted 5 lines · Peter Zijlstra
By inlining everything in
poke_int3_handler()(except bsearch :/) we can mark the whole function off limits to everything and call it a day. That simplicity has been the guiding principle so far.Alternatively we can provide an
__always_inlinevariant ofbsearch().Quoted 8 lines
Quoted 4 lines
This reduces the
__no_sanitizeusage to just the exception entry (do_int3) and the critical function:poke_int3_handler().Is this more acceptible?
Let's say it's more acceptable.
Acked-by Dmitry Vyukov <[email protected]>Thanks, I'll go make it happen.
Quoted 5 lines
I guess there is no ideal solution here.
Just a straw man proposal: expected number of elements is large enough to make bsearch profitable, right? I see 1 is a common case, but the other case has multiple entries.
Quoted 7 lines
Latency was the consideration; the linear search would dramatically increase the runtime of the exception.
The current limit is 256 entries and we're hitting that quite often.
(we can trivially increase, but nobody has been able to show significant benefits for that -- as of yet)
I see. Thanks for explaining. Just wanted to check because inlining a linear search would free us from all these unpleasant problems.