blob: 16604462ef90bd2fb23c4b00b135b12c5339fe4d [file] [log] [blame]
Allen Martinfc468d82016-11-15 17:57:52 -08001From 0ee4fd72ca45b88431b1c7a6f70d7aa836af8645 Mon Sep 17 00:00:00 2001
Allen Martin685e0f82016-07-26 19:34:29 -07002From: Thomas Gleixner <tglx@linutronix.de>
3Date: Fri, 3 Jul 2009 08:44:31 -0500
Allen Martinfc468d82016-11-15 17:57:52 -08004Subject: [PATCH 083/351] hrtimer: Fixup hrtimer callback changes for
Allen Martin685e0f82016-07-26 19:34:29 -07005 preempt-rt
6X-NVConfidentiality: public
7
8In preempt-rt we can not call the callbacks which take sleeping locks
9from the timer interrupt context.
10
11Bring back the softirq split for now, until we fixed the signal
12delivery problem for real.
13
14Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
15Signed-off-by: Ingo Molnar <mingo@elte.hu>
Allen Martin685e0f82016-07-26 19:34:29 -070016---
Allen Martinfc468d82016-11-15 17:57:52 -080017 include/linux/hrtimer.h | 4 ++
Allen Martin685e0f82016-07-26 19:34:29 -070018 kernel/sched/core.c | 1 +
19 kernel/sched/rt.c | 1 +
Allen Martinfc468d82016-11-15 17:57:52 -080020 kernel/time/hrtimer.c | 142 +++++++++++++++++++++++++++++++++++++++++++----
Allen Martin685e0f82016-07-26 19:34:29 -070021 kernel/time/tick-sched.c | 1 +
22 kernel/watchdog.c | 1 +
Allen Martinfc468d82016-11-15 17:57:52 -080023 6 files changed, 139 insertions(+), 11 deletions(-)
Allen Martin685e0f82016-07-26 19:34:29 -070024
25diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
Allen Martinfc468d82016-11-15 17:57:52 -080026index d5e22d72537b..6f78ca13ffdf 100644
Allen Martin685e0f82016-07-26 19:34:29 -070027--- a/include/linux/hrtimer.h
28+++ b/include/linux/hrtimer.h
Allen Martinfc468d82016-11-15 17:57:52 -080029@@ -103,6 +103,8 @@ struct hrtimer {
Allen Martin685e0f82016-07-26 19:34:29 -070030 enum hrtimer_restart (*function)(struct hrtimer *);
31 struct hrtimer_clock_base *base;
32 u8 state;
33+ struct list_head cb_entry;
34+ int irqsafe;
35 #ifdef CONFIG_MISSED_TIMER_OFFSETS_HIST
36 ktime_t praecox;
37 #endif
Allen Martinfc468d82016-11-15 17:57:52 -080038@@ -143,6 +145,7 @@ struct hrtimer_clock_base {
Allen Martin685e0f82016-07-26 19:34:29 -070039 int index;
40 clockid_t clockid;
41 struct timerqueue_head active;
42+ struct list_head expired;
43 ktime_t (*get_time)(void);
44 ktime_t offset;
45 } __attribute__((__aligned__(HRTIMER_CLOCK_BASE_ALIGN)));
Allen Martinfc468d82016-11-15 17:57:52 -080046@@ -186,6 +189,7 @@ struct hrtimer_cpu_base {
Allen Martin685e0f82016-07-26 19:34:29 -070047 raw_spinlock_t lock;
48 seqcount_t seq;
49 struct hrtimer *running;
50+ struct hrtimer *running_soft;
51 unsigned int cpu;
52 unsigned int active_bases;
53 unsigned int clock_was_set_seq;
54diff --git a/kernel/sched/core.c b/kernel/sched/core.c
Allen Martinfc468d82016-11-15 17:57:52 -080055index 7892c1ebe893..f014ae1d81e0 100644
Allen Martin685e0f82016-07-26 19:34:29 -070056--- a/kernel/sched/core.c
57+++ b/kernel/sched/core.c
58@@ -439,6 +439,7 @@ static void init_rq_hrtick(struct rq *rq)
59
60 hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
61 rq->hrtick_timer.function = hrtick;
62+ rq->hrtick_timer.irqsafe = 1;
63 }
64 #else /* CONFIG_SCHED_HRTICK */
65 static inline void hrtick_clear(struct rq *rq)
66diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
Allen Martinfc468d82016-11-15 17:57:52 -080067index 6a839a4c8e13..55e0b4b9c8d9 100644
Allen Martin685e0f82016-07-26 19:34:29 -070068--- a/kernel/sched/rt.c
69+++ b/kernel/sched/rt.c
70@@ -47,6 +47,7 @@ void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime)
71
72 hrtimer_init(&rt_b->rt_period_timer,
73 CLOCK_MONOTONIC, HRTIMER_MODE_REL);
74+ rt_b->rt_period_timer.irqsafe = 1;
75 rt_b->rt_period_timer.function = sched_rt_period_timer;
76 }
77
78diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
Allen Martinfc468d82016-11-15 17:57:52 -080079index a7c365d33ff5..3c194dd6ebfb 100644
Allen Martin685e0f82016-07-26 19:34:29 -070080--- a/kernel/time/hrtimer.c
81+++ b/kernel/time/hrtimer.c
82@@ -730,11 +730,8 @@ static inline int hrtimer_is_hres_enabled(void) { return 0; }
83 static inline void hrtimer_switch_to_hres(void) { }
84 static inline void
85 hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { }
86-static inline int hrtimer_reprogram(struct hrtimer *timer,
87- struct hrtimer_clock_base *base)
88-{
89- return 0;
90-}
91+static inline void hrtimer_reprogram(struct hrtimer *timer,
92+ struct hrtimer_clock_base *base) { }
93 static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) { }
94 static inline void retrigger_next_event(void *arg) { }
95
96@@ -883,7 +880,7 @@ void hrtimer_wait_for_timer(const struct hrtimer *timer)
97 {
98 struct hrtimer_clock_base *base = timer->base;
99
100- if (base && base->cpu_base && !hrtimer_hres_active())
101+ if (base && base->cpu_base && !timer->irqsafe)
102 wait_event(base->cpu_base->wait,
103 !(hrtimer_callback_running(timer)));
104 }
105@@ -933,6 +930,11 @@ static void __remove_hrtimer(struct hrtimer *timer,
106 if (!(state & HRTIMER_STATE_ENQUEUED))
107 return;
108
109+ if (unlikely(!list_empty(&timer->cb_entry))) {
110+ list_del_init(&timer->cb_entry);
111+ return;
112+ }
113+
114 if (!timerqueue_del(&base->active, &timer->node))
115 cpu_base->active_bases &= ~(1 << base->index);
116
117@@ -1173,6 +1175,7 @@ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
118
119 base = hrtimer_clockid_to_base(clock_id);
120 timer->base = &cpu_base->clock_base[base];
121+ INIT_LIST_HEAD(&timer->cb_entry);
122 timerqueue_init(&timer->node);
123
124 #ifdef CONFIG_TIMER_STATS
125@@ -1213,6 +1216,7 @@ bool hrtimer_active(const struct hrtimer *timer)
126 seq = raw_read_seqcount_begin(&cpu_base->seq);
127
128 if (timer->state != HRTIMER_STATE_INACTIVE ||
129+ cpu_base->running_soft == timer ||
130 cpu_base->running == timer)
131 return true;
132
Allen Martinfc468d82016-11-15 17:57:52 -0800133@@ -1311,10 +1315,111 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base,
Allen Martin685e0f82016-07-26 19:34:29 -0700134 cpu_base->running = NULL;
135 }
136
137+#ifdef CONFIG_PREEMPT_RT_BASE
138+static void hrtimer_rt_reprogram(int restart, struct hrtimer *timer,
139+ struct hrtimer_clock_base *base)
140+{
141+ int leftmost;
142+
143+ if (restart != HRTIMER_NORESTART &&
144+ !(timer->state & HRTIMER_STATE_ENQUEUED)) {
145+
146+ leftmost = enqueue_hrtimer(timer, base);
147+ if (!leftmost)
148+ return;
149+#ifdef CONFIG_HIGH_RES_TIMERS
150+ if (!hrtimer_is_hres_active(timer)) {
151+ /*
152+ * Kick to reschedule the next tick to handle the new timer
153+ * on dynticks target.
154+ */
155+ if (base->cpu_base->nohz_active)
156+ wake_up_nohz_cpu(base->cpu_base->cpu);
157+ } else {
158+
159+ hrtimer_reprogram(timer, base);
160+ }
161+#endif
162+ }
163+}
164+
165+/*
166+ * The changes in mainline which removed the callback modes from
167+ * hrtimer are not yet working with -rt. The non wakeup_process()
168+ * based callbacks which involve sleeping locks need to be treated
169+ * seperately.
170+ */
171+static void hrtimer_rt_run_pending(void)
172+{
173+ enum hrtimer_restart (*fn)(struct hrtimer *);
174+ struct hrtimer_cpu_base *cpu_base;
175+ struct hrtimer_clock_base *base;
176+ struct hrtimer *timer;
177+ int index, restart;
178+
179+ local_irq_disable();
180+ cpu_base = &per_cpu(hrtimer_bases, smp_processor_id());
181+
182+ raw_spin_lock(&cpu_base->lock);
183+
184+ for (index = 0; index < HRTIMER_MAX_CLOCK_BASES; index++) {
185+ base = &cpu_base->clock_base[index];
186+
187+ while (!list_empty(&base->expired)) {
188+ timer = list_first_entry(&base->expired,
189+ struct hrtimer, cb_entry);
190+
191+ /*
192+ * Same as the above __run_hrtimer function
193+ * just we run with interrupts enabled.
194+ */
195+ debug_deactivate(timer);
196+ cpu_base->running_soft = timer;
197+ raw_write_seqcount_barrier(&cpu_base->seq);
198+
199+ __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE, 0);
200+ timer_stats_account_hrtimer(timer);
201+ fn = timer->function;
202+
203+ raw_spin_unlock_irq(&cpu_base->lock);
204+ restart = fn(timer);
205+ raw_spin_lock_irq(&cpu_base->lock);
206+
207+ hrtimer_rt_reprogram(restart, timer, base);
208+ raw_write_seqcount_barrier(&cpu_base->seq);
209+
210+ WARN_ON_ONCE(cpu_base->running_soft != timer);
211+ cpu_base->running_soft = NULL;
212+ }
213+ }
214+
215+ raw_spin_unlock_irq(&cpu_base->lock);
216+
217+ wake_up_timer_waiters(cpu_base);
218+}
219+
220+static int hrtimer_rt_defer(struct hrtimer *timer)
221+{
222+ if (timer->irqsafe)
223+ return 0;
224+
225+ __remove_hrtimer(timer, timer->base, timer->state, 0);
226+ list_add_tail(&timer->cb_entry, &timer->base->expired);
227+ return 1;
228+}
229+
230+#else
231+
232+static inline int hrtimer_rt_defer(struct hrtimer *timer) { return 0; }
233+
234+#endif
235+
Allen Martinfc468d82016-11-15 17:57:52 -0800236+
Allen Martin685e0f82016-07-26 19:34:29 -0700237 static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now)
238 {
239 struct hrtimer_clock_base *base = cpu_base->clock_base;
240 unsigned int active = cpu_base->active_bases;
241+ int raise = 0;
242
243 for (; active; base++, active >>= 1) {
244 struct timerqueue_node *node;
Allen Martinfc468d82016-11-15 17:57:52 -0800245@@ -1354,15 +1459,20 @@ static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now)
Allen Martin685e0f82016-07-26 19:34:29 -0700246 if (basenow.tv64 < hrtimer_get_softexpires_tv64(timer))
247 break;
248
249- __run_hrtimer(cpu_base, base, timer, &basenow);
Allen Martinfc468d82016-11-15 17:57:52 -0800250+ if (!hrtimer_rt_defer(timer))
251+ __run_hrtimer(cpu_base, base, timer, &basenow);
252+ else
253+ raise = 1;
Allen Martin685e0f82016-07-26 19:34:29 -0700254 }
255 }
256+ if (raise)
257+ raise_softirq_irqoff(HRTIMER_SOFTIRQ);
258 }
259
Allen Martinfc468d82016-11-15 17:57:52 -0800260-#ifdef CONFIG_HIGH_RES_TIMERS
261-
262 static enum hrtimer_restart hrtimer_wakeup(struct hrtimer *timer);
263
264+#ifdef CONFIG_HIGH_RES_TIMERS
265+
266 /*
267 * High resolution timer interrupt
268 * Called with interrupts disabled
269@@ -1500,8 +1610,6 @@ void hrtimer_run_queues(void)
Allen Martin685e0f82016-07-26 19:34:29 -0700270 now = hrtimer_update_base(cpu_base);
271 __hrtimer_run_queues(cpu_base, now);
272 raw_spin_unlock(&cpu_base->lock);
273-
274- wake_up_timer_waiters(cpu_base);
275 }
276
277 /*
Allen Martinfc468d82016-11-15 17:57:52 -0800278@@ -1523,6 +1631,7 @@ static enum hrtimer_restart hrtimer_wakeup(struct hrtimer *timer)
Allen Martin685e0f82016-07-26 19:34:29 -0700279 void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task)
280 {
281 sl->timer.function = hrtimer_wakeup;
282+ sl->timer.irqsafe = 1;
283 sl->task = task;
284 }
285 EXPORT_SYMBOL_GPL(hrtimer_init_sleeper);
Allen Martinfc468d82016-11-15 17:57:52 -0800286@@ -1657,6 +1766,7 @@ static void init_hrtimers_cpu(int cpu)
Allen Martin685e0f82016-07-26 19:34:29 -0700287 for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
288 cpu_base->clock_base[i].cpu_base = cpu_base;
289 timerqueue_init_head(&cpu_base->clock_base[i].active);
290+ INIT_LIST_HEAD(&cpu_base->clock_base[i].expired);
291 }
292
293 cpu_base->cpu = cpu;
Allen Martinfc468d82016-11-15 17:57:52 -0800294@@ -1761,11 +1871,21 @@ static struct notifier_block hrtimers_nb = {
Allen Martin685e0f82016-07-26 19:34:29 -0700295 .notifier_call = hrtimer_cpu_notify,
296 };
297
298+#ifdef CONFIG_PREEMPT_RT_BASE
299+static void run_hrtimer_softirq(struct softirq_action *h)
300+{
301+ hrtimer_rt_run_pending();
302+}
303+#endif
304+
305 void __init hrtimers_init(void)
306 {
307 hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE,
308 (void *)(long)smp_processor_id());
309 register_cpu_notifier(&hrtimers_nb);
310+#ifdef CONFIG_PREEMPT_RT_BASE
311+ open_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq);
312+#endif
313 }
314
315 /**
316diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
317index 9579f7985093..f92ba9983ab9 100644
318--- a/kernel/time/tick-sched.c
319+++ b/kernel/time/tick-sched.c
320@@ -1105,6 +1105,7 @@ void tick_setup_sched_timer(void)
321 * Emulate tick processing via per-CPU hrtimers:
322 */
323 hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
324+ ts->sched_timer.irqsafe = 1;
325 ts->sched_timer.function = tick_sched_timer;
326
327 /* Get the next period (per cpu) */
328diff --git a/kernel/watchdog.c b/kernel/watchdog.c
Allen Martinfc468d82016-11-15 17:57:52 -0800329index 0d180c9f3d5f..88b20a01af23 100644
Allen Martin685e0f82016-07-26 19:34:29 -0700330--- a/kernel/watchdog.c
331+++ b/kernel/watchdog.c
332@@ -585,6 +585,7 @@ static void watchdog_enable(unsigned int cpu)
333 /* kick off the timer for the hardlockup detector */
334 hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
335 hrtimer->function = watchdog_timer_fn;
336+ hrtimer->irqsafe = 1;
337
338 /* Enable the perf event */
339 watchdog_nmi_enable(cpu);
340--
Allen Martinfc468d82016-11-15 17:57:52 -08003412.10.1
Allen Martin685e0f82016-07-26 19:34:29 -0700342