Commit f88708af7a43f1765b520f0fd9d8717ce77417e3

Authored by Luca Abeni
Committed by Greg Kroah-Hartman
1 parent fbbd9c2a84

sched/deadline: Avoid double-accounting in case of missed deadlines

commit 269ad8015a6b2bb1cf9e684da4921eb6fa0a0c88 upstream.

The dl_runtime_exceeded() function is supposed to ckeck if
a SCHED_DEADLINE task must be throttled, by checking if its
current runtime is <= 0. However, it also checks if the
scheduling deadline has been missed (the current time is
larger than the current scheduling deadline), further
decreasing the runtime if this happens.
This "double accounting" is wrong:

- In case of partitioned scheduling (or single CPU), this
  happens if task_tick_dl() has been called later than expected
  (due to small HZ values). In this case, the current runtime is
  also negative, and replenish_dl_entity() can take care of the
  deadline miss by recharging the current runtime to a value smaller
  than dl_runtime

- In case of global scheduling on multiple CPUs, scheduling
  deadlines can be missed even if the task did not consume more
  runtime than expected, hence penalizing the task is wrong

This patch fix this problem by throttling a SCHED_DEADLINE task
only when its runtime becomes negative, and not modifying the runtime

Signed-off-by: Luca Abeni <luca.abeni@unitn.it>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Juri Lelli <juri.lelli@gmail.com>
Cc: Dario Faggioli <raistlin@linux.it>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: http://lkml.kernel.org/r/1418813432-20797-3-git-send-email-luca.abeni@unitn.it
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 1 changed file with 1 additions and 18 deletions Side-by-side Diff

kernel/sched/deadline.c
... ... @@ -575,24 +575,7 @@
575 575 static
576 576 int dl_runtime_exceeded(struct rq *rq, struct sched_dl_entity *dl_se)
577 577 {
578   - int dmiss = dl_time_before(dl_se->deadline, rq_clock(rq));
579   - int rorun = dl_se->runtime <= 0;
580   -
581   - if (!rorun && !dmiss)
582   - return 0;
583   -
584   - /*
585   - * If we are beyond our current deadline and we are still
586   - * executing, then we have already used some of the runtime of
587   - * the next instance. Thus, if we do not account that, we are
588   - * stealing bandwidth from the system at each deadline miss!
589   - */
590   - if (dmiss) {
591   - dl_se->runtime = rorun ? dl_se->runtime : 0;
592   - dl_se->runtime -= rq_clock(rq) - dl_se->deadline;
593   - }
594   -
595   - return 1;
  578 + return (dl_se->runtime <= 0);
596 579 }
597 580  
598 581 extern bool sched_rt_bandwidth_account(struct rt_rq *rt_rq);