diff options
Diffstat (limited to 'debian/patches-rt/0003-time-Allow-to-preempt-after-a-callback.patch')
-rw-r--r-- | debian/patches-rt/0003-time-Allow-to-preempt-after-a-callback.patch | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/debian/patches-rt/0003-time-Allow-to-preempt-after-a-callback.patch b/debian/patches-rt/0003-time-Allow-to-preempt-after-a-callback.patch new file mode 100644 index 0000000000..7ede7d6ae5 --- /dev/null +++ b/debian/patches-rt/0003-time-Allow-to-preempt-after-a-callback.patch @@ -0,0 +1,47 @@ +From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +Date: Fri, 4 Aug 2023 13:30:39 +0200 +Subject: [PATCH 3/3] time: Allow to preempt after a callback. +Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz + +The TIMER_SOFTIRQ handler invokes timer callbacks of the expired timers. +Before each invocation the timer_base::lock is dropped. The only lock +that is still held is the timer_base::expiry_lock and the per-CPU +bh-lock as part of local_bh_disable(). The former is released as part +of lock up prevention if the timer is preempted by the caller which is +waiting for its completion. + +Both locks are already released as part of timer_sync_wait_running(). +This can be extended by also releasing in bh-lock. The timer core does +not rely on any state that is serialized by the bh-lock. The timer +callback expects the bh-state to be serialized by the lock but there is +no need to keep state synchronized while invoking multiple callbacks. + +Preempt handling softirqs and release all locks after a timer invocation +if the current has inherited priority. + +Link: https://lore.kernel.org/r/20230804113039.419794-4-bigeasy@linutronix.de +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + kernel/time/timer.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/kernel/time/timer.c ++++ b/kernel/time/timer.c +@@ -1470,9 +1470,16 @@ static inline void timer_base_unlock_exp + */ + static void timer_sync_wait_running(struct timer_base *base) + { +- if (atomic_read(&base->timer_waiters)) { ++ bool need_preempt; ++ ++ need_preempt = task_is_pi_boosted(current); ++ if (need_preempt || atomic_read(&base->timer_waiters)) { + raw_spin_unlock_irq(&base->lock); + spin_unlock(&base->expiry_lock); ++ ++ if (need_preempt) ++ softirq_preempt(); ++ + spin_lock(&base->expiry_lock); + raw_spin_lock_irq(&base->lock); + } |