diff options
author | Frederic Weisbecker <frederic@kernel.org> | 2019-08-20 09:12:23 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2019-08-20 16:05:46 -0400 |
commit | 0bee3b601b77dbe7981b5474ae8758d6bf60177a (patch) | |
tree | bb5c920be193be0a68973d54969868b680e8ab9f | |
parent | ec8f954a40da8cd3d159713b608e901f0cd909a9 (diff) |
hrtimer: Improve comments on handling priority inversion against softirq kthread
The handling of a priority inversion between timer cancelling and a a not
well defined possible preemption of softirq kthread is not very clear.
Especially in the posix timers side it's unclear why there is a specific RT
wait callback.
All the nice explanations can be found in the initial changelog of
f61eff83cec9 (hrtimer: Prepare support for PREEMPT_RT").
Extract the detailed informations from there and put it into comments.
Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190820132656.GC2093@lenoir
-rw-r--r-- | kernel/time/hrtimer.c | 14 | ||||
-rw-r--r-- | kernel/time/posix-timers.c | 6 |
2 files changed, 16 insertions, 4 deletions
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 499122752649..833353732554 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c | |||
@@ -1201,10 +1201,16 @@ static void hrtimer_sync_wait_running(struct hrtimer_cpu_base *cpu_base, | |||
1201 | * deletion of a timer failed because the timer callback function was | 1201 | * deletion of a timer failed because the timer callback function was |
1202 | * running. | 1202 | * running. |
1203 | * | 1203 | * |
1204 | * This prevents priority inversion, if the softirq thread on a remote CPU | 1204 | * This prevents priority inversion: if the soft irq thread is preempted |
1205 | * got preempted, and it prevents a life lock when the task which tries to | 1205 | * in the middle of a timer callback, then calling del_timer_sync() can |
1206 | * delete a timer preempted the softirq thread running the timer callback | 1206 | * lead to two issues: |
1207 | * function. | 1207 | * |
1208 | * - If the caller is on a remote CPU then it has to spin wait for the timer | ||
1209 | * handler to complete. This can result in unbound priority inversion. | ||
1210 | * | ||
1211 | * - If the caller originates from the task which preempted the timer | ||
1212 | * handler on the same CPU, then spin waiting for the timer handler to | ||
1213 | * complete is never going to end. | ||
1208 | */ | 1214 | */ |
1209 | void hrtimer_cancel_wait_running(const struct hrtimer *timer) | 1215 | void hrtimer_cancel_wait_running(const struct hrtimer *timer) |
1210 | { | 1216 | { |
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 9e377830cc10..0ec5b7a1d769 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c | |||
@@ -810,6 +810,12 @@ static void common_timer_wait_running(struct k_itimer *timer) | |||
810 | hrtimer_cancel_wait_running(&timer->it.real.timer); | 810 | hrtimer_cancel_wait_running(&timer->it.real.timer); |
811 | } | 811 | } |
812 | 812 | ||
813 | /* | ||
814 | * On PREEMPT_RT this prevent priority inversion against softirq kthread in | ||
815 | * case it gets preempted while executing a timer callback. See comments in | ||
816 | * hrtimer_cancel_wait_running. For PREEMPT_RT=n this just results in a | ||
817 | * cpu_relax(). | ||
818 | */ | ||
813 | static struct k_itimer *timer_wait_running(struct k_itimer *timer, | 819 | static struct k_itimer *timer_wait_running(struct k_itimer *timer, |
814 | unsigned long *flags) | 820 | unsigned long *flags) |
815 | { | 821 | { |