summaryrefslogtreecommitdiff
path: root/kernel/hrtimer.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2014-05-07 13:39:22 +0200
committerIngo Molnar <mingo@kernel.org>2014-05-07 13:39:22 +0200
commit37b16beaa92860c378273ccdcc2ccb22c6cee047 (patch)
tree4fc7f879c32d11d318f411dbe128d080ed8478f9 /kernel/hrtimer.c
parent3e46d21285577a8c9e4c37f9b1002e567c440b28 (diff)
parenta4b4f11b2783ec678cccb4ce7e4ce9665aa04a24 (diff)
Merge branch 'perf/urgent' into perf/core, to avoid conflicts
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/hrtimer.c')
-rw-r--r--kernel/hrtimer.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 53d26829cd4d..d10eba8089d1 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -234,6 +234,11 @@ again:
goto again;
}
timer->base = new_base;
+ } else {
+ if (cpu != this_cpu && hrtimer_check_target(timer, new_base)) {
+ cpu = this_cpu;
+ goto again;
+ }
}
return new_base;
}
@@ -569,6 +574,23 @@ hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal)
cpu_base->expires_next.tv64 = expires_next.tv64;
+ /*
+ * If a hang was detected in the last timer interrupt then we
+ * leave the hang delay active in the hardware. We want the
+ * system to make progress. That also prevents the following
+ * scenario:
+ * T1 expires 50ms from now
+ * T2 expires 5s from now
+ *
+ * T1 is removed, so this code is called and would reprogram
+ * the hardware to 5s from now. Any hrtimer_start after that
+ * will not reprogram the hardware due to hang_detected being
+ * set. So we'd effectivly block all timers until the T2 event
+ * fires.
+ */
+ if (cpu_base->hang_detected)
+ return;
+
if (cpu_base->expires_next.tv64 != KTIME_MAX)
tick_program_event(cpu_base->expires_next, 1);
}