summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/0006_sched_make_rcu_nest_depth_distinct_in___might_resched.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/0006_sched_make_rcu_nest_depth_distinct_in___might_resched.patch')
-rw-r--r--debian/patches-rt/0006_sched_make_rcu_nest_depth_distinct_in___might_resched.patch124
1 files changed, 124 insertions, 0 deletions
diff --git a/debian/patches-rt/0006_sched_make_rcu_nest_depth_distinct_in___might_resched.patch b/debian/patches-rt/0006_sched_make_rcu_nest_depth_distinct_in___might_resched.patch
new file mode 100644
index 000000000..1aa6fab12
--- /dev/null
+++ b/debian/patches-rt/0006_sched_make_rcu_nest_depth_distinct_in___might_resched.patch
@@ -0,0 +1,124 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Subject: sched: Make RCU nest depth distinct in __might_resched()
+Date: Thu, 23 Sep 2021 18:54:43 +0200
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/5.15/older/patches-5.15.3-rt21.tar.xz
+
+For !RT kernels RCU nest depth in __might_resched() is always expected to
+be 0, but on RT kernels it can be non zero while the preempt count is
+expected to be always 0.
+
+Instead of playing magic games in interpreting the 'preempt_offset'
+argument, rename it to 'offsets' and use the lower 8 bits for the expected
+preempt count, allow to hand in the expected RCU nest depth in the upper
+bits and adopt the __might_resched() code and related checks and printks.
+
+The affected call sites are updated in subsequent steps.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20210923165358.243232823@linutronix.de
+---
+ include/linux/kernel.h | 4 ++--
+ include/linux/sched.h | 3 +++
+ kernel/sched/core.c | 28 ++++++++++++++++------------
+ 3 files changed, 21 insertions(+), 14 deletions(-)
+
+--- a/include/linux/kernel.h
++++ b/include/linux/kernel.h
+@@ -111,7 +111,7 @@ static __always_inline void might_resche
+ #endif /* CONFIG_PREEMPT_* */
+
+ #ifdef CONFIG_DEBUG_ATOMIC_SLEEP
+-extern void __might_resched(const char *file, int line, int preempt_offset);
++extern void __might_resched(const char *file, int line, unsigned int offsets);
+ extern void __might_sleep(const char *file, int line);
+ extern void __cant_sleep(const char *file, int line, int preempt_offset);
+ extern void __cant_migrate(const char *file, int line);
+@@ -169,7 +169,7 @@ extern void __cant_migrate(const char *f
+ # define non_block_end() WARN_ON(current->non_block_count-- == 0)
+ #else
+ static inline void __might_resched(const char *file, int line,
+- int preempt_offset) { }
++ unsigned int offsets) { }
+ static inline void __might_sleep(const char *file, int line) { }
+ # define might_sleep() do { might_resched(); } while (0)
+ # define cant_sleep() do { } while (0)
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -2057,6 +2057,9 @@ extern int __cond_resched_lock(spinlock_
+ extern int __cond_resched_rwlock_read(rwlock_t *lock);
+ extern int __cond_resched_rwlock_write(rwlock_t *lock);
+
++#define MIGHT_RESCHED_RCU_SHIFT 8
++#define MIGHT_RESCHED_PREEMPT_MASK ((1U << MIGHT_RESCHED_RCU_SHIFT) - 1)
++
+ #define cond_resched_lock(lock) ({ \
+ __might_resched(__FILE__, __LINE__, PREEMPT_LOCK_OFFSET); \
+ __cond_resched_lock(lock); \
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -9468,12 +9468,6 @@ void __init sched_init(void)
+ }
+
+ #ifdef CONFIG_DEBUG_ATOMIC_SLEEP
+-static inline int preempt_count_equals(int preempt_offset)
+-{
+- int nested = preempt_count() + rcu_preempt_depth();
+-
+- return (nested == preempt_offset);
+-}
+
+ void __might_sleep(const char *file, int line)
+ {
+@@ -9505,7 +9499,16 @@ static void print_preempt_disable_ip(int
+ print_ip_sym(KERN_ERR, ip);
+ }
+
+-void __might_resched(const char *file, int line, int preempt_offset)
++static inline bool resched_offsets_ok(unsigned int offsets)
++{
++ unsigned int nested = preempt_count();
++
++ nested += rcu_preempt_depth() << MIGHT_RESCHED_RCU_SHIFT;
++
++ return nested == offsets;
++}
++
++void __might_resched(const char *file, int line, unsigned int offsets)
+ {
+ /* Ratelimiting timestamp: */
+ static unsigned long prev_jiffy;
+@@ -9515,7 +9518,7 @@ void __might_resched(const char *file, i
+ /* WARN_ON_ONCE() by default, no rate limit required: */
+ rcu_sleep_check();
+
+- if ((preempt_count_equals(preempt_offset) && !irqs_disabled() &&
++ if ((resched_offsets_ok(offsets) && !irqs_disabled() &&
+ !is_idle_task(current) && !current->non_block_count) ||
+ system_state == SYSTEM_BOOTING || system_state > SYSTEM_RUNNING ||
+ oops_in_progress)
+@@ -9534,11 +9537,11 @@ void __might_resched(const char *file, i
+ in_atomic(), irqs_disabled(), current->non_block_count,
+ current->pid, current->comm);
+ pr_err("preempt_count: %x, expected: %x\n", preempt_count(),
+- preempt_offset);
++ offsets & MIGHT_RESCHED_PREEMPT_MASK);
+
+ if (IS_ENABLED(CONFIG_PREEMPT_RCU)) {
+- pr_err("RCU nest depth: %d, expected: 0\n",
+- rcu_preempt_depth());
++ pr_err("RCU nest depth: %d, expected: %u\n",
++ rcu_preempt_depth(), offsets >> MIGHT_RESCHED_RCU_SHIFT);
+ }
+
+ if (task_stack_end_corrupted(current))
+@@ -9548,7 +9551,8 @@ void __might_resched(const char *file, i
+ if (irqs_disabled())
+ print_irqtrace_events(current);
+
+- print_preempt_disable_ip(preempt_offset, preempt_disable_ip);
++ print_preempt_disable_ip(offsets & MIGHT_RESCHED_PREEMPT_MASK,
++ preempt_disable_ip);
+
+ dump_stack();
+ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);