aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-13 18:37:57 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-13 18:37:57 -0400
commitf8acc450e10dbe7996220bac5459ee9c14a82a6a (patch)
tree48bbad2c7bc8223fbd721b5e71e5b1c4ba395864 /kernel
parent505608d2b9f3ab9e3ea0fd1b89b1cc560b91a7b5 (diff)
parent971ee28cbd1ccd87b3164facd9359a534c1d2892 (diff)
Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull scheduler fix from Thomas Gleixner: "Fix a potential deadlock versus hrtimers" * 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: sched: Fix HRTICK
Diffstat (limited to 'kernel')
-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;