mirror of
https://github.com/torvalds/linux.git
synced 2026-09-14 16:10:02 +02:00
preempt: Introduce __preempt_count_{sub,add}_return()
In order to use preempt_count() to track the interrupt disable nesting
level, __preempt_count_{add,sub}_return() are introduced, as their names
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);
}
Having these primitives will avoid a read of preempt_count() after
changing preempt_count() on certain architectures.
Signed-off-by: Boqun Feng <boqun@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Heiko Carstens <hca@linux.ibm.com> # s390
Link: https://patch.msgid.link/20260804161447.84806-4-boqun@kernel.org
This commit is contained in:
parent
9634d860ac
commit
4ad87eee54
|
|
@ -55,6 +55,26 @@ static inline void __preempt_count_sub(int val)
|
|||
WRITE_ONCE(current_thread_info()->preempt.count, pc);
|
||||
}
|
||||
|
||||
static inline int __preempt_count_add_return(int val)
|
||||
{
|
||||
u32 pc = READ_ONCE(current_thread_info()->preempt.count);
|
||||
|
||||
pc += val;
|
||||
WRITE_ONCE(current_thread_info()->preempt.count, pc);
|
||||
|
||||
return pc;
|
||||
}
|
||||
|
||||
static inline int __preempt_count_sub_return(int val)
|
||||
{
|
||||
u32 pc = READ_ONCE(current_thread_info()->preempt.count);
|
||||
|
||||
pc -= val;
|
||||
WRITE_ONCE(current_thread_info()->preempt.count, pc);
|
||||
|
||||
return pc;
|
||||
}
|
||||
|
||||
static inline bool __preempt_count_dec_and_test(void)
|
||||
{
|
||||
struct thread_info *ti = current_thread_info();
|
||||
|
|
|
|||
|
|
@ -139,6 +139,16 @@ 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)
|
||||
{
|
||||
return val + __atomic_add(val, &get_lowcore()->preempt_count);
|
||||
}
|
||||
|
||||
static __always_inline int __preempt_count_sub_return(int val)
|
||||
{
|
||||
return __preempt_count_add_return(-val);
|
||||
}
|
||||
|
||||
#define init_task_preempt_count(p) do { } while (0)
|
||||
/* Deferred to CPU bringup time */
|
||||
#define init_idle_preempt_count(p, cpu) do { } while (0)
|
||||
|
|
|
|||
|
|
@ -85,6 +85,16 @@ static __always_inline void __preempt_count_sub(int val)
|
|||
raw_cpu_add_4(__preempt_count, -val);
|
||||
}
|
||||
|
||||
static __always_inline int __preempt_count_add_return(int val)
|
||||
{
|
||||
return raw_cpu_add_return_4(__preempt_count, val);
|
||||
}
|
||||
|
||||
static __always_inline int __preempt_count_sub_return(int val)
|
||||
{
|
||||
return raw_cpu_add_return_4(__preempt_count, -val);
|
||||
}
|
||||
|
||||
/*
|
||||
* Because we keep PREEMPT_NEED_RESCHED set when we do _not_ need to reschedule
|
||||
* a decrement which hits zero means we have no preempt_count and should
|
||||
|
|
|
|||
|
|
@ -59,6 +59,20 @@ static __always_inline void __preempt_count_sub(int val)
|
|||
*preempt_count_ptr() -= val;
|
||||
}
|
||||
|
||||
static __always_inline int __preempt_count_add_return(int val)
|
||||
{
|
||||
*preempt_count_ptr() += val;
|
||||
|
||||
return *preempt_count_ptr();
|
||||
}
|
||||
|
||||
static __always_inline int __preempt_count_sub_return(int val)
|
||||
{
|
||||
*preempt_count_ptr() -= val;
|
||||
|
||||
return *preempt_count_ptr();
|
||||
}
|
||||
|
||||
static __always_inline bool __preempt_count_dec_and_test(void)
|
||||
{
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user