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>2014-04-10 00:19:07 (GMT)
commit00417c7d809cc169dabef50a51ea4912ac74c9d1 (patch)
treecdb0c8dde7a601cac9acbbdb42feb66eccd6b78d /kernel/hrtimer.c
parent3a522ffe61ee80adcc78f2fd25bae737a04b9b4c (diff)
downloadlinux-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.c33
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