summaryrefslogtreecommitdiff
path: root/kernel/hrtimer.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-07-03 13:29:34 (GMT)
committerScott Wood <scottwood@freescale.com>2015-02-13 22:20:29 (GMT)
commit23cc486c86a6b1963dcb98c8dbf0bbb50b3563e3 (patch)
tree9c8732f20e23fb089eeb54a363cb41e8680a8505 /kernel/hrtimer.c
parent6cb009abe8ec043594c04c33210f1a819d662b62 (diff)
downloadlinux-fsl-qoriq-23cc486c86a6b1963dcb98c8dbf0bbb50b3563e3.tar.xz
hrtimers: prepare full preemption
Make cancellation of a running callback in softirq context safe against preemption. Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/hrtimer.c')
-rw-r--r--kernel/hrtimer.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 85b02c5..f797502 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -893,6 +893,32 @@ u64 hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval)
}
EXPORT_SYMBOL_GPL(hrtimer_forward);
+#ifdef CONFIG_PREEMPT_RT_BASE
+# define wake_up_timer_waiters(b) wake_up(&(b)->wait)
+
+/**
+ * hrtimer_wait_for_timer - Wait for a running timer
+ *
+ * @timer: timer to wait for
+ *
+ * The function waits in case the timers callback function is
+ * currently executed on the waitqueue of the timer base. The
+ * waitqueue is woken up after the timer callback function has
+ * finished execution.
+ */
+void hrtimer_wait_for_timer(const struct hrtimer *timer)
+{
+ struct hrtimer_clock_base *base = timer->base;
+
+ if (base && base->cpu_base && !hrtimer_hres_active(base->cpu_base))
+ wait_event(base->cpu_base->wait,
+ !(timer->state & HRTIMER_STATE_CALLBACK));
+}
+
+#else
+# define wake_up_timer_waiters(b) do { } while (0)
+#endif
+
/*
* enqueue_hrtimer - internal function to (re)start a timer
*
@@ -1145,7 +1171,7 @@ int hrtimer_cancel(struct hrtimer *timer)
if (ret >= 0)
return ret;
- cpu_relax();
+ hrtimer_wait_for_timer(timer);
}
}
EXPORT_SYMBOL_GPL(hrtimer_cancel);
@@ -1555,6 +1581,8 @@ void hrtimer_run_queues(void)
}
raw_spin_unlock(&cpu_base->lock);
}
+
+ wake_up_timer_waiters(cpu_base);
}
/*
@@ -1715,6 +1743,9 @@ static void init_hrtimers_cpu(int cpu)
}
hrtimer_init_hres(cpu_base);
+#ifdef CONFIG_PREEMPT_RT_BASE
+ init_waitqueue_head(&cpu_base->wait);
+#endif
}
#ifdef CONFIG_HOTPLUG_CPU