Re: [RFC RESEND v10 02/14] preempt: Introduce __preempt_count_{sub, add}_return()
From: Heiko Carstens <hca@linux.ibm.com>
Date: 2025-05-28 06:38:02
Also in:
linux-arch, linux-s390, lkml, rust-for-linux
On Tue, May 27, 2025 at 06:21:43PM -0400, Lyude Paul wrote:
From: Boqun Feng <redacted>
In order to use preempt_count() to tracking the interrupt disable
nesting level, __preempt_count_{add,sub}_return() are introduced, as
their name suggest, these primitives return the new value of the
preempt_count() after changing it. The following example shows the usage
of it in local_interrupt_disable():
// increase the HARDIRQ_DISABLE bit
new_count = __preempt_count_add_return(HARDIRQ_DISABLE_OFFSET);
// if it's the first-time increment, then disable the interrupt
// at hardware level.
if (new_count & HARDIRQ_DISABLE_MASK == HARDIRQ_DISABLE_OFFSET) {
local_irq_save(flags);
raw_cpu_write(local_interrupt_disable_state.flags, flags);
}
Having these primitives will avoid a read of preempt_count() after
changing preempt_count() on certain architectures.
Signed-off-by: Boqun Feng <redacted>
---
V10:
* Add commit message I forgot
* Rebase against latest pcpu_hot changes
Signed-off-by: Lyude Paul <lyude@redhat.com>
---
arch/arm64/include/asm/preempt.h | 18 ++++++++++++++++++
arch/s390/include/asm/preempt.h | 19 +++++++++++++++++++
arch/x86/include/asm/preempt.h | 10 ++++++++++
include/asm-generic/preempt.h | 14 ++++++++++++++
4 files changed, 61 insertions(+)...
quoted hunk
diff --git a/arch/s390/include/asm/preempt.h b/arch/s390/include/asm/preempt.h index 6ccd033acfe52..67a6e265e9fff 100644 --- a/arch/s390/include/asm/preempt.h +++ b/arch/s390/include/asm/preempt.h@@ -98,6 +98,25 @@ static __always_inline bool should_resched(int preempt_offset) return unlikely(READ_ONCE(get_lowcore()->preempt_count) == preempt_offset); } +static __always_inline int __preempt_count_add_return(int val) +{ + /* + * With some obscure config options and CONFIG_PROFILE_ALL_BRANCHES + * enabled, gcc 12 fails to handle __builtin_constant_p(). + */ + if (!IS_ENABLED(CONFIG_PROFILE_ALL_BRANCHES)) { + if (__builtin_constant_p(val) && (val >= -128) && (val <= 127)) { + return val + __atomic_add_const(val, &get_lowcore()->preempt_count); + } + } + return val + __atomic_add(val, &get_lowcore()->preempt_count); +}
This is still wrong and needs to be changed to:
static __always_inline int __preempt_count_add_return(int val)
{
return val + __atomic_add(val, &get_lowcore()->preempt_count);
}