Commit 72d2854d authored by Con Kolivas's avatar Con Kolivas Committed by Linus Torvalds

[PATCH] sched: fix interactive ceiling code

The relationship between INTERACTIVE_SLEEP and the ceiling is not perfect
and not explicit enough.  The sleep boost is not supposed to be any larger
than without this code and the comment is not clear enough about what
exactly it does, just the reason it does it.  Fix it.

There is a ceiling to the priority beyond which tasks that only ever sleep
for very long periods cannot surpass.  Fix it.

Prevent the on-runqueue bonus logic from defeating the idle sleep logic.

Opportunity to micro-optimise.
Signed-off-by: default avatarCon Kolivas <kernel@kolivas.org>
Signed-off-by: default avatarMike Galbraith <efault@gmx.de>
Acked-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarKen Chen <kenneth.w.chen@intel.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent d444886e
...@@ -686,33 +686,35 @@ static inline void __activate_idle_task(task_t *p, runqueue_t *rq) ...@@ -686,33 +686,35 @@ static inline void __activate_idle_task(task_t *p, runqueue_t *rq)
static int recalc_task_prio(task_t *p, unsigned long long now) static int recalc_task_prio(task_t *p, unsigned long long now)
{ {
/* Caller must always ensure 'now >= p->timestamp' */ /* Caller must always ensure 'now >= p->timestamp' */
unsigned long long __sleep_time = now - p->timestamp; unsigned long sleep_time = now - p->timestamp;
unsigned long sleep_time;
if (batch_task(p)) if (batch_task(p))
sleep_time = 0; sleep_time = 0;
else {
if (__sleep_time > NS_MAX_SLEEP_AVG)
sleep_time = NS_MAX_SLEEP_AVG;
else
sleep_time = (unsigned long)__sleep_time;
}
if (likely(sleep_time > 0)) { if (likely(sleep_time > 0)) {
/* /*
* User tasks that sleep a long time are categorised as * This ceiling is set to the lowest priority that would allow
* idle. They will only have their sleep_avg increased to a * a task to be reinserted into the active array on timeslice
* level that makes them just interactive priority to stay * completion.
* active yet prevent them suddenly becoming cpu hogs and
* starving other processes.
*/ */
if (p->mm && sleep_time > INTERACTIVE_SLEEP(p)) { unsigned long ceiling = INTERACTIVE_SLEEP(p);
unsigned long ceiling;
ceiling = JIFFIES_TO_NS(MAX_SLEEP_AVG - if (p->mm && sleep_time > ceiling && p->sleep_avg < ceiling) {
DEF_TIMESLICE); /*
if (p->sleep_avg < ceiling) * Prevents user tasks from achieving best priority
p->sleep_avg = ceiling; * with one single large enough sleep.
*/
p->sleep_avg = ceiling;
/*
* Using INTERACTIVE_SLEEP() as a ceiling places a
* nice(0) task 1ms sleep away from promotion, and
* gives it 700ms to round-robin with no chance of
* being demoted. This is more than generous, so
* mark this sleep as non-interactive to prevent the
* on-runqueue bonus logic from intervening should
* this task not receive cpu immediately.
*/
p->sleep_type = SLEEP_NONINTERACTIVE;
} else { } else {
/* /*
* Tasks waking from uninterruptible sleep are * Tasks waking from uninterruptible sleep are
...@@ -720,12 +722,12 @@ static int recalc_task_prio(task_t *p, unsigned long long now) ...@@ -720,12 +722,12 @@ static int recalc_task_prio(task_t *p, unsigned long long now)
* are likely to be waiting on I/O * are likely to be waiting on I/O
*/ */
if (p->sleep_type == SLEEP_NONINTERACTIVE && p->mm) { if (p->sleep_type == SLEEP_NONINTERACTIVE && p->mm) {
if (p->sleep_avg >= INTERACTIVE_SLEEP(p)) if (p->sleep_avg >= ceiling)
sleep_time = 0; sleep_time = 0;
else if (p->sleep_avg + sleep_time >= else if (p->sleep_avg + sleep_time >=
INTERACTIVE_SLEEP(p)) { ceiling) {
p->sleep_avg = INTERACTIVE_SLEEP(p); p->sleep_avg = ceiling;
sleep_time = 0; sleep_time = 0;
} }
} }
...@@ -739,9 +741,9 @@ static int recalc_task_prio(task_t *p, unsigned long long now) ...@@ -739,9 +741,9 @@ static int recalc_task_prio(task_t *p, unsigned long long now)
*/ */
p->sleep_avg += sleep_time; p->sleep_avg += sleep_time;
if (p->sleep_avg > NS_MAX_SLEEP_AVG)
p->sleep_avg = NS_MAX_SLEEP_AVG;
} }
if (p->sleep_avg > NS_MAX_SLEEP_AVG)
p->sleep_avg = NS_MAX_SLEEP_AVG;
} }
return effective_prio(p); return effective_prio(p);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment