summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/0100-hrtimer-by-timers-by-default-into-the-softirq-contex.patch
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--debian/patches-rt/0100-hrtimer-by-timers-by-default-into-the-softirq-contex.patch237
1 files changed, 237 insertions, 0 deletions
diff --git a/debian/patches-rt/0100-hrtimer-by-timers-by-default-into-the-softirq-contex.patch b/debian/patches-rt/0100-hrtimer-by-timers-by-default-into-the-softirq-contex.patch
new file mode 100644
index 000000000..1b924bac1
--- /dev/null
+++ b/debian/patches-rt/0100-hrtimer-by-timers-by-default-into-the-softirq-contex.patch
@@ -0,0 +1,237 @@
+From 8a7e45b02f567fa32754c24195d5c0d095069685 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 3 Jul 2009 08:44:31 -0500
+Subject: [PATCH 100/347] hrtimer: by timers by default into the softirq
+ context
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/older/patches-4.19.246-rt110.tar.xz
+
+We can't have hrtimers callbacks running in hardirq context on RT. Therefore
+the timers are deferred to the softirq context by default.
+There are few timers which expect to be run in hardirq context even on RT.
+Those are:
+- very short running where low latency is critical (kvm lapic)
+- timers which take raw locks and need run in hard-irq context (perf, sched)
+- wake up related timer (kernel side of clock_nanosleep() and so on)
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ arch/x86/kvm/lapic.c | 2 +-
+ include/linux/hrtimer.h | 6 ++++++
+ kernel/events/core.c | 4 ++--
+ kernel/sched/core.c | 2 +-
+ kernel/sched/deadline.c | 2 +-
+ kernel/sched/fair.c | 4 ++--
+ kernel/sched/rt.c | 4 ++--
+ kernel/time/hrtimer.c | 21 +++++++++++++++++++--
+ kernel/time/tick-broadcast-hrtimer.c | 2 +-
+ kernel/time/tick-sched.c | 2 +-
+ kernel/watchdog.c | 2 +-
+ 11 files changed, 37 insertions(+), 14 deletions(-)
+
+diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
+index 89d07312e58c..037dbe04fda2 100644
+--- a/arch/x86/kvm/lapic.c
++++ b/arch/x86/kvm/lapic.c
+@@ -2258,7 +2258,7 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu)
+ apic->vcpu = vcpu;
+
+ hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
+- HRTIMER_MODE_ABS_PINNED);
++ HRTIMER_MODE_ABS_PINNED_HARD);
+ apic->lapic_timer.timer.function = apic_timer_fn;
+
+ /*
+diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
+index 8714f1a37d84..082147c07831 100644
+--- a/include/linux/hrtimer.h
++++ b/include/linux/hrtimer.h
+@@ -42,6 +42,7 @@ enum hrtimer_mode {
+ HRTIMER_MODE_REL = 0x01,
+ HRTIMER_MODE_PINNED = 0x02,
+ HRTIMER_MODE_SOFT = 0x04,
++ HRTIMER_MODE_HARD = 0x08,
+
+ HRTIMER_MODE_ABS_PINNED = HRTIMER_MODE_ABS | HRTIMER_MODE_PINNED,
+ HRTIMER_MODE_REL_PINNED = HRTIMER_MODE_REL | HRTIMER_MODE_PINNED,
+@@ -52,6 +53,11 @@ enum hrtimer_mode {
+ HRTIMER_MODE_ABS_PINNED_SOFT = HRTIMER_MODE_ABS_PINNED | HRTIMER_MODE_SOFT,
+ HRTIMER_MODE_REL_PINNED_SOFT = HRTIMER_MODE_REL_PINNED | HRTIMER_MODE_SOFT,
+
++ HRTIMER_MODE_ABS_HARD = HRTIMER_MODE_ABS | HRTIMER_MODE_HARD,
++ HRTIMER_MODE_REL_HARD = HRTIMER_MODE_REL | HRTIMER_MODE_HARD,
++
++ HRTIMER_MODE_ABS_PINNED_HARD = HRTIMER_MODE_ABS_PINNED | HRTIMER_MODE_HARD,
++ HRTIMER_MODE_REL_PINNED_HARD = HRTIMER_MODE_REL_PINNED | HRTIMER_MODE_HARD,
+ };
+
+ /*
+diff --git a/kernel/events/core.c b/kernel/events/core.c
+index 88dd1398ae88..7f2441f671d3 100644
+--- a/kernel/events/core.c
++++ b/kernel/events/core.c
+@@ -1108,7 +1108,7 @@ static void __perf_mux_hrtimer_init(struct perf_cpu_context *cpuctx, int cpu)
+ cpuctx->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * interval);
+
+ raw_spin_lock_init(&cpuctx->hrtimer_lock);
+- hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
++ hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED_HARD);
+ timer->function = perf_mux_hrtimer_handler;
+ }
+
+@@ -9311,7 +9311,7 @@ static void perf_swevent_init_hrtimer(struct perf_event *event)
+ if (!is_sampling_event(event))
+ return;
+
+- hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
+ hwc->hrtimer.function = perf_swevent_hrtimer;
+
+ /*
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index 3c5999476609..0f949b7738fd 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -315,7 +315,7 @@ static void hrtick_rq_init(struct rq *rq)
+ rq->hrtick_csd.info = rq;
+ #endif
+
+- hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
+ rq->hrtick_timer.function = hrtick;
+ }
+ #else /* CONFIG_SCHED_HRTICK */
+diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
+index 95ebbb2074c7..1a285367081c 100644
+--- a/kernel/sched/deadline.c
++++ b/kernel/sched/deadline.c
+@@ -1086,7 +1086,7 @@ void init_dl_task_timer(struct sched_dl_entity *dl_se)
+ {
+ struct hrtimer *timer = &dl_se->dl_timer;
+
+- hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
+ timer->function = dl_task_timer;
+ }
+
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index 16940416d526..d804b5443bb9 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -4951,9 +4951,9 @@ void init_cfs_bandwidth(struct cfs_bandwidth *cfs_b)
+ cfs_b->period = ns_to_ktime(default_cfs_period());
+
+ INIT_LIST_HEAD(&cfs_b->throttled_cfs_rq);
+- hrtimer_init(&cfs_b->period_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
++ hrtimer_init(&cfs_b->period_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED_HARD);
+ cfs_b->period_timer.function = sched_cfs_period_timer;
+- hrtimer_init(&cfs_b->slack_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ hrtimer_init(&cfs_b->slack_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
+ cfs_b->slack_timer.function = sched_cfs_slack_timer;
+ cfs_b->distribute_running = 0;
+ }
+diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
+index 52b55144d8ad..a2f2c6c91e05 100644
+--- a/kernel/sched/rt.c
++++ b/kernel/sched/rt.c
+@@ -45,8 +45,8 @@ void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime)
+
+ raw_spin_lock_init(&rt_b->rt_runtime_lock);
+
+- hrtimer_init(&rt_b->rt_period_timer,
+- CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ hrtimer_init(&rt_b->rt_period_timer, CLOCK_MONOTONIC,
++ HRTIMER_MODE_REL_HARD);
+ rt_b->rt_period_timer.function = sched_rt_period_timer;
+ }
+
+diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
+index 8bbde17325c7..e947f3b344ac 100644
+--- a/kernel/time/hrtimer.c
++++ b/kernel/time/hrtimer.c
+@@ -1202,7 +1202,9 @@ void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
+ * Check whether the HRTIMER_MODE_SOFT bit and hrtimer.is_soft
+ * match.
+ */
++#ifndef CONFIG_PREEMPT_RT_BASE
+ WARN_ON_ONCE(!(mode & HRTIMER_MODE_SOFT) ^ !timer->is_soft);
++#endif
+
+ base = lock_hrtimer_base(timer, &flags);
+
+@@ -1362,10 +1364,17 @@ static inline int hrtimer_clockid_to_base(clockid_t clock_id)
+ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
+ enum hrtimer_mode mode)
+ {
+- bool softtimer = !!(mode & HRTIMER_MODE_SOFT);
+- int base = softtimer ? HRTIMER_MAX_CLOCK_BASES / 2 : 0;
++ bool softtimer;
++ int base;
+ struct hrtimer_cpu_base *cpu_base;
+
++ softtimer = !!(mode & HRTIMER_MODE_SOFT);
++#ifdef CONFIG_PREEMPT_RT_FULL
++ if (!softtimer && !(mode & HRTIMER_MODE_HARD))
++ softtimer = true;
++#endif
++ base = softtimer ? HRTIMER_MAX_CLOCK_BASES / 2 : 0;
++
+ memset(timer, 0, sizeof(struct hrtimer));
+
+ cpu_base = raw_cpu_ptr(&hrtimer_bases);
+@@ -1748,6 +1757,14 @@ static void __hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
+ enum hrtimer_mode mode,
+ struct task_struct *task)
+ {
++#ifdef CONFIG_PREEMPT_RT_FULL
++ if (!(mode & (HRTIMER_MODE_SOFT | HRTIMER_MODE_HARD))) {
++ if (task_is_realtime(current) || system_state != SYSTEM_RUNNING)
++ mode |= HRTIMER_MODE_HARD;
++ else
++ mode |= HRTIMER_MODE_SOFT;
++ }
++#endif
+ __hrtimer_init(&sl->timer, clock_id, mode);
+ sl->timer.function = hrtimer_wakeup;
+ sl->task = task;
+diff --git a/kernel/time/tick-broadcast-hrtimer.c b/kernel/time/tick-broadcast-hrtimer.c
+index a836efd34589..c50e8f3262de 100644
+--- a/kernel/time/tick-broadcast-hrtimer.c
++++ b/kernel/time/tick-broadcast-hrtimer.c
+@@ -107,7 +107,7 @@ static enum hrtimer_restart bc_handler(struct hrtimer *t)
+
+ void tick_setup_hrtimer_broadcast(void)
+ {
+- hrtimer_init(&bctimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
++ hrtimer_init(&bctimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD);
+ bctimer.function = bc_handler;
+ clockevents_register_device(&ce_broadcast_hrtimer);
+ }
+diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
+index e774a49176cc..012bc81879bf 100644
+--- a/kernel/time/tick-sched.c
++++ b/kernel/time/tick-sched.c
+@@ -1314,7 +1314,7 @@ void tick_setup_sched_timer(void)
+ /*
+ * Emulate tick processing via per-CPU hrtimers:
+ */
+- hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
++ hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD);
+ ts->sched_timer.function = tick_sched_timer;
+
+ /* Get the next period (per-CPU) */
+diff --git a/kernel/watchdog.c b/kernel/watchdog.c
+index 6d60701dc636..328620fe85f6 100644
+--- a/kernel/watchdog.c
++++ b/kernel/watchdog.c
+@@ -485,7 +485,7 @@ static void watchdog_enable(unsigned int cpu)
+ * Start the timer first to prevent the NMI watchdog triggering
+ * before the timer has a chance to fire.
+ */
+- hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
+ hrtimer->function = watchdog_timer_fn;
+ hrtimer_start(hrtimer, ns_to_ktime(sample_period),
+ HRTIMER_MODE_REL_PINNED);
+--
+2.36.1
+