Patch "sched/preempt: Fix cond_resched_lock() and cond_resched_softirq()" has been added to the 4.2-stable tree
Subsystems (4)
This is a note to let you know that I've just added the patch titled
sched/preempt: Fix cond_resched_lock() and cond_resched_softirq()
to the 4.2-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
sched-preempt-fix-cond_resched_lock-and-cond_resched_softirq.patch
and it can be found in the queue-4.2 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
fe32d3cd5e8eb0f82e459763374aa80797023403Mon Sep 17 00:00:00 2001
From: Konstantin Khlebnikov <[email protected]>
Date: Wed, 15 Jul 2015 12:52:04 +0300
Subject: sched/preempt: Fix cond_resched_lock() and cond_resched_softirq()
From: Konstantin Khlebnikov <[email protected]>
commit fe32d3cd5e8eb0f82e459763374aa80797023403 upstream.
These functions check should_resched() before unlocking spinlock/bh-enable:preempt_count always non-zero => should_resched() always returns false. cond_resched_lock() worked iff spin_needbreak is set.
This patch adds argument "preempt_offset" to should_resched().
preempt_count offset constants for that:
PREEMPT_DISABLE_OFFSET - offset after preempt_disable() PREEMPT_LOCK_OFFSET - offset after spin_lock() SOFTIRQ_DISABLE_OFFSET - offset after local_bh_distable() SOFTIRQ_LOCK_OFFSET - offset after spin_lock_bh()
--- arch/x86/include/asm/preempt.h | 4 ++-- include/asm-generic/preempt.h | 5 +++-- include/linux/preempt.h | 19 ++++++++++++++----- include/linux/sched.h | 6 ------ kernel/sched/core.c | 6 +++--- 5 files changed, 22 insertions(+), 18 deletions(-)
arch/x86/include/asm/preempt.h +2 -2
@@ -90,9 +90,9 @@ static __always_inline bool __preempt_co/* * Returns true when we need to resched and can (barring IRQ state). */ -static __always_inline bool should_resched(void) +static __always_inline bool should_resched(int preempt_offset) { -return unlikely (!raw_cpu_read_4 (__preempt_count)); +return unlikely (raw_cpu_read_4 (__preempt_count) == preempt_offset); }#ifdef CONFIG_PREEMPT
include/asm-generic/preempt.h +3 -2
@@ -71,9 +71,10 @@ static __always_inline bool __preempt_co/* * Returns true when we need to resched and can (barring IRQ state). */ -static __always_inline bool should_resched(void) +static __always_inline bool should_resched(int preempt_offset) { -return unlikely (!preempt_count () &&tif_need_resched ()); +return unlikely (preempt_count () == preempt_offset && +tif_need_resched ()); }#ifdef CONFIG_PREEMPT
include/linux/preempt.h +14 -5
@@ -84,13 +84,21 @@*/ #define in_nmi () (preempt_count() & NMI_MASK) +/* +* The preempt_count offset after preempt_disable(); +*/ #if defined(CONFIG_PREEMPT_COUNT ) -# define PREEMPT_DISABLE_OFFSET 1 +# define PREEMPT_DISABLE_OFFSET PREEMPT_OFFSET#else -# define PREEMPT_DISABLE_OFFSET 0 +# define PREEMPT_DISABLE_OFFSET 0#endif /* +* The preempt_count offset after spin_lock() +*/ +#define PREEMPT_LOCK_OFFSET PREEMPT_DISABLE_OFFSET + +/* * The preempt_count offset needed for things like: * * spin_lock_bh()
@@ -103,7 +111,7 @@* * Work as expected. */ -#define SOFTIRQ_LOCK_OFFSET (SOFTIRQ_DISABLE_OFFSET + PREEMPT_DISABLE_OFFSET) +#define SOFTIRQ_LOCK_OFFSET (SOFTIRQ_DISABLE_OFFSET + PREEMPT_LOCK_OFFSET)/* * Are we running in atomic context? WARNING: this macro cannot
@@ -124,7 +132,8 @@#if defined(CONFIG_DEBUG_PREEMPT ) || defined(CONFIG_PREEMPT_TRACER )extern void preempt_count_add (int val);extern void preempt_count_sub (int val); -#define preempt_count_dec_and_test () ({ preempt_count_sub(1); should_resched(); }) +#define preempt_count_dec_and_test () \ + ({ preempt_count_sub(1); should_resched(0); })#else #define preempt_count_add (val) __preempt_count_add(val)#define preempt_count_sub (val) __preempt_count_sub(val)
@@ -184,7 +193,7 @@ do { \#define preempt_check_resched () \ do { \ - if (should_resched()) \ + if (should_resched(0)) \ __preempt_schedule(); \ } while (0)
include/linux/sched.h +0 -6
@@ -2909,12 +2909,6 @@ extern int _cond_resched(void);extern int __cond_resched_lock (spinlock_t *lock); -#ifdef CONFIG_PREEMPT_COUNT -#define PREEMPT_LOCK_OFFSET PREEMPT_OFFSET -#else -#define PREEMPT_LOCK_OFFSET 0 -#endif -#define cond_resched_lock (lock) ({ \ ___might_sleep(__FILE__, __LINE__, PREEMPT_LOCK_OFFSET);\ __cond_resched_lock(lock); \
kernel/sched/core.c +3 -3
@@ -4499,7 +4499,7 @@ SYSCALL_DEFINE0(sched_yield) int __sched _cond_resched(void) { -if (should_resched ()) { +if (should_resched (0 )) {preempt_schedule_common ();return 1 ; }
@@ -4517,7 +4517,7 @@ EXPORT_SYMBOL(_cond_resched);*/ int __cond_resched_lock (spinlock_t *lock) { -int resched =should_resched (); +int resched =should_resched (PREEMPT_LOCK_OFFSET );int ret =0 ;lockdep_assert_held (lock);
@@ -4539,7 +4539,7 @@ int __sched __cond_resched_softirq(void) {BUG_ON (!in_softirq ()); -if (should_resched ()) { +if (should_resched (SOFTIRQ_DISABLE_OFFSET )) {local_bh_enable ();preempt_schedule_common ();local_bh_disable ();
Patches currently in stable-queue which might be from [email protected] are
queue-4.2/sched-preempt-fix-cond_resched_lock-and-cond_resched_softirq.patch