sched/core: Rework rq->clock update skips
The original purpose of rq::skip_clock_update was to avoid 'costly' clock updates for back to back wakeup-preempt pairs. The big problem with it has always been that the rq variable is unaware of the context and causes indiscrimiate clock skips. Rework the entire thing and create a sense of context by only allowing schedule() to skip clock updates. (XXX can we measure the cost of the added store?) By ensuring only schedule can ever skip an update, we guarantee we're never more than 1 tick behind on the update. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: umgwanakikbuti@gmail.com Link: http://lkml.kernel.org/r/20150105103554.432381549@infradead.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:

committed by
Ingo Molnar

parent
cebde6d681
commit
9edfbfed3f
@@ -119,7 +119,9 @@ void update_rq_clock(struct rq *rq)
|
||||
{
|
||||
s64 delta;
|
||||
|
||||
if (rq->skip_clock_update > 0)
|
||||
lockdep_assert_held(&rq->lock);
|
||||
|
||||
if (rq->clock_skip_update & RQCF_ACT_SKIP)
|
||||
return;
|
||||
|
||||
delta = sched_clock_cpu(cpu_of(rq)) - rq->clock;
|
||||
@@ -1046,7 +1048,7 @@ void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags)
|
||||
* this case, we can save a useless back to back clock update.
|
||||
*/
|
||||
if (task_on_rq_queued(rq->curr) && test_tsk_need_resched(rq->curr))
|
||||
rq->skip_clock_update = 1;
|
||||
rq_clock_skip_update(rq, true);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
@@ -2779,6 +2781,8 @@ need_resched:
|
||||
smp_mb__before_spinlock();
|
||||
raw_spin_lock_irq(&rq->lock);
|
||||
|
||||
rq->clock_skip_update <<= 1; /* promote REQ to ACT */
|
||||
|
||||
switch_count = &prev->nivcsw;
|
||||
if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
|
||||
if (unlikely(signal_pending_state(prev->state, prev))) {
|
||||
@@ -2803,13 +2807,13 @@ need_resched:
|
||||
switch_count = &prev->nvcsw;
|
||||
}
|
||||
|
||||
if (task_on_rq_queued(prev) || rq->skip_clock_update < 0)
|
||||
if (task_on_rq_queued(prev))
|
||||
update_rq_clock(rq);
|
||||
|
||||
next = pick_next_task(rq, prev);
|
||||
clear_tsk_need_resched(prev);
|
||||
clear_preempt_need_resched();
|
||||
rq->skip_clock_update = 0;
|
||||
rq->clock_skip_update = 0;
|
||||
|
||||
if (likely(prev != next)) {
|
||||
rq->nr_switches++;
|
||||
|
Reference in New Issue
Block a user