diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-07-03 13:29:34 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-04-10 00:19:07 (GMT) |
commit | 00417c7d809cc169dabef50a51ea4912ac74c9d1 (patch) | |
tree | cdb0c8dde7a601cac9acbbdb42feb66eccd6b78d /kernel/hrtimer.c | |
parent | 3a522ffe61ee80adcc78f2fd25bae737a04b9b4c (diff) | |
download | linux-fsl-qoriq-00417c7d809cc169dabef50a51ea4912ac74c9d1.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.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 7c4ee68..86adf2b 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -871,6 +871,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 * @@ -1123,7 +1149,7 @@ int hrtimer_cancel(struct hrtimer *timer) if (ret >= 0) return ret; - cpu_relax(); + hrtimer_wait_for_timer(timer); } } EXPORT_SYMBOL_GPL(hrtimer_cancel); @@ -1533,6 +1559,8 @@ void hrtimer_run_queues(void) } raw_spin_unlock(&cpu_base->lock); } + + wake_up_timer_waiters(cpu_base); } /* @@ -1693,6 +1721,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 |