aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2013-06-28 05:18:53 -0400
committerIngo Molnar <mingo@kernel.org>2013-07-12 07:52:58 -0400
commit971ee28cbd1ccd87b3164facd9359a534c1d2892 (patch)
treed5d9bcbe6f9c8cb5da70e305b25eefc3e1a25008
parent9903883f1dd6e86f286b7bfa6e4b423f98c1cd9e (diff)
sched: Fix HRTICK
David reported that the HRTICK sched feature was borken; which was enough motivation for me to finally fix it ;-) We should not allow hrtimer code to do softirq wakeups while holding scheduler locks. The hrtimer code only needs this when we accidentally try to program an expired time. We don't much care about those anyway since we have the regular tick to fall back to. Reported-by: David Ahern <dsahern@gmail.com> Tested-by: David Ahern <dsahern@gmail.com> Signed-off-by: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/20130628091853.GE29209@dyad.programming.kicks-ass.net Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--kernel/sched/core.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 9b1f2e533b95..0d8eb4525e76 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -370,13 +370,6 @@ static struct rq *this_rq_lock(void)
370#ifdef CONFIG_SCHED_HRTICK 370#ifdef CONFIG_SCHED_HRTICK
371/* 371/*
372 * Use HR-timers to deliver accurate preemption points. 372 * Use HR-timers to deliver accurate preemption points.
373 *
374 * Its all a bit involved since we cannot program an hrt while holding the
375 * rq->lock. So what we do is store a state in in rq->hrtick_* and ask for a
376 * reschedule event.
377 *
378 * When we get rescheduled we reprogram the hrtick_timer outside of the
379 * rq->lock.
380 */ 373 */
381 374
382static void hrtick_clear(struct rq *rq) 375static void hrtick_clear(struct rq *rq)
@@ -404,6 +397,15 @@ static enum hrtimer_restart hrtick(struct hrtimer *timer)
404} 397}
405 398
406#ifdef CONFIG_SMP 399#ifdef CONFIG_SMP
400
401static int __hrtick_restart(struct rq *rq)
402{
403 struct hrtimer *timer = &rq->hrtick_timer;
404 ktime_t time = hrtimer_get_softexpires(timer);
405
406 return __hrtimer_start_range_ns(timer, time, 0, HRTIMER_MODE_ABS_PINNED, 0);
407}
408
407/* 409/*
408 * called from hardirq (IPI) context 410 * called from hardirq (IPI) context
409 */ 411 */
@@ -412,7 +414,7 @@ static void __hrtick_start(void *arg)
412 struct rq *rq = arg; 414 struct rq *rq = arg;
413 415
414 raw_spin_lock(&rq->lock); 416 raw_spin_lock(&rq->lock);
415 hrtimer_restart(&rq->hrtick_timer); 417 __hrtick_restart(rq);
416 rq->hrtick_csd_pending = 0; 418 rq->hrtick_csd_pending = 0;
417 raw_spin_unlock(&rq->lock); 419 raw_spin_unlock(&rq->lock);
418} 420}
@@ -430,7 +432,7 @@ void hrtick_start(struct rq *rq, u64 delay)
430 hrtimer_set_expires(timer, time); 432 hrtimer_set_expires(timer, time);
431 433
432 if (rq == this_rq()) { 434 if (rq == this_rq()) {
433 hrtimer_restart(timer); 435 __hrtick_restart(rq);
434 } else if (!rq->hrtick_csd_pending) { 436 } else if (!rq->hrtick_csd_pending) {
435 __smp_call_function_single(cpu_of(rq), &rq->hrtick_csd, 0); 437 __smp_call_function_single(cpu_of(rq), &rq->hrtick_csd, 0);
436 rq->hrtick_csd_pending = 1; 438 rq->hrtick_csd_pending = 1;