Patch "sched/preempt: Fix cond_resched_lock() and cond_resched_softirq()" has been added to the 3.14-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 3.14-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-3.14 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 | 5 +++-- include/linux/preempt_mask.h | 14 +++++++++++--- include/linux/sched.h | 6 ------ kernel/sched/core.c | 6 +++--- 6 files changed, 22 insertions(+), 18 deletions(-)
arch/x86/include/asm/preempt.h +2 -2
@@ -105,9 +105,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 (!__this_cpu_read_4 (__preempt_count)); +return unlikely (__this_cpu_read_4 (__preempt_count) == preempt_offset); }#ifdef CONFIG_PREEMPT
include/asm-generic/preempt.h +3 -2
@@ -74,9 +74,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 +3 -2
@@ -22,7 +22,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)
@@ -61,7 +62,7 @@ do { \#define preempt_check_resched () \ do { \ - if (should_resched()) \ + if (should_resched(0)) \ __preempt_schedule(); \ } while (0)
include/linux/preempt_mask.h +11 -3
@@ -71,13 +71,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()
@@ -90,7 +98,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
include/linux/sched.h +0 -6
@@ -2647,12 +2647,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
@@ -4113,7 +4113,7 @@ static void __cond_resched(void) int __sched _cond_resched(void) { -if (should_resched ()) { +if (should_resched (0 )) {__cond_resched ();return 1 ; }
@@ -4131,7 +4131,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);
@@ -4153,7 +4153,7 @@ int __sched __cond_resched_softirq(void) {BUG_ON (!in_softirq ()); -if (should_resched ()) { +if (should_resched (SOFTIRQ_DISABLE_OFFSET )) {local_bh_enable ();__cond_resched ();local_bh_disable ();
Patches currently in stable-queue which might be from [email protected] are
queue-3.14/sched-preempt-fix-cond_resched_lock-and-cond_resched_softirq.patch