[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <1164193062.7925.72.camel@Homer.simpson.net>
Date: Wed, 22 Nov 2006 11:57:42 +0100
From: Mike Galbraith <efault@....de>
To: LKML <linux-kernel@...r.kernel.org>
Cc: Christian <christiand59@....de>, Lee Revell <rlrevell@...-job.com>,
Ingo Molnar <mingo@...e.hu>
Subject: [rfc patch] Re: Sluggish system responsiveness on I/O
Greetings,
Problem: If X or one of it's clients gets into a position where it
can't get it's work done and go to sleep, no sleep means no priority
boost. The consequence is terrible interactivity. Our sleep based
interactivity heuristics are very good, but not perfect.
Solution: The simple patch belows acknowledges this shortcoming in
scheduler interactivity heuristics by making a(nother) concession to the
real world - it adds the complement of class SCHED_BATCH to the
scheduler. While SCHED_BATCH tasks are never interactive, tasks which
are class SCHED_INTERACTIVE will always have interactive status, as will
any tasks they awaken (excluding in_interrupt()). The awakened task
will only have it's sleep_avg adjusted, it will not change class.
Setting X to SCHED_INTERACTIVE obviously cures the situation where X
can't get to sleep often enough. It also cures a scenario which
demonstrates the client problem very well here: start xmms, enable it's
G-FORCE visualization, and stretch it out large enough that it eats
massive cpu and then start a modest parallel kernel build. The very
hungry, but nonetheless definitely interactive (while I'm watching;)
G-FORCE visualization has no chance of producing decent output. Set X
to SCHED_INTERACTIVE, and presto, G-FORCE becomes a happy camper.
Setting X won't help if a threaded interactive application has it's cpu
hog component awakened by one of it's threads. The application would
either have to be started as SCHED_INTERACTIVE by the user, or modified
to set interactive threads to SCHED_INTERACTIVE during startup.
It also won't eliminate hiccups that can happen when the anti-starvation
logic kicks in on an overloaded box.
I've attached a modified userland tool (which was posted here a few
years ago, I didn't write it) to allow setting SCHED_INTERACTIVE if
anyone wants to try this out on their favorite interactivity problem.
(Hi Christian;)
Suggestions for a solution that doesn't include adding yet another
scheduling class would be most welcome.
--- linux-2.6.19-rc6/include/linux/sched.h.org 2006-11-21 09:08:31.000000000 +0100
+++ linux-2.6.19-rc6/include/linux/sched.h 2006-11-21 11:34:15.000000000 +0100
@@ -34,6 +34,7 @@
#define SCHED_FIFO 1
#define SCHED_RR 2
#define SCHED_BATCH 3
+#define SCHED_INTERACTIVE 4
#ifdef __KERNEL__
@@ -505,7 +506,7 @@ struct signal_struct {
#define rt_prio(prio) unlikely((prio) < MAX_RT_PRIO)
#define rt_task(p) rt_prio((p)->prio)
#define batch_task(p) (unlikely((p)->policy == SCHED_BATCH))
-#define is_rt_policy(p) ((p) != SCHED_NORMAL && (p) != SCHED_BATCH)
+#define is_rt_policy(p) ((p) == SCHED_RR || (p) == SCHED_FIFO)
#define has_rt_policy(p) unlikely(is_rt_policy((p)->policy))
/*
--- linux-2.6.19-rc6/kernel/sched.c.org 2006-11-16 10:02:26.000000000 +0100
+++ linux-2.6.19-rc6/kernel/sched.c 2006-11-22 09:01:35.000000000 +0100
@@ -921,6 +921,14 @@ static int recalc_task_prio(struct task_
p->sleep_avg += sleep_time;
}
+ /*
+ * If a task of class SCHED_INTERACTIVE awakens another,
+ * that task should also be considered interactive despite
+ * heavy cpu usage.
+ */
+ if (!in_interrupt() && current->policy == SCHED_INTERACTIVE &&
+ p->sleep_avg < ceiling)
+ p->sleep_avg = ceiling;
if (p->sleep_avg > NS_MAX_SLEEP_AVG)
p->sleep_avg = NS_MAX_SLEEP_AVG;
}
@@ -3091,6 +3099,13 @@ void scheduler_tick(void)
goto out_unlock;
}
if (!--p->time_slice) {
+ if (p->policy == SCHED_INTERACTIVE) {
+ unsigned long floor = INTERACTIVE_SLEEP(p);
+ if (floor > NS_MAX_SLEEP_AVG)
+ floor = NS_MAX_SLEEP_AVG;
+ if (p->sleep_avg < floor)
+ p->sleep_avg = floor;
+ }
dequeue_task(p, rq->active);
set_tsk_need_resched(p);
p->prio = effective_prio(p);
@@ -4117,7 +4132,8 @@ recheck:
if (policy < 0)
policy = oldpolicy = p->policy;
else if (policy != SCHED_FIFO && policy != SCHED_RR &&
- policy != SCHED_NORMAL && policy != SCHED_BATCH)
+ policy != SCHED_NORMAL && policy != SCHED_BATCH &&
+ policy != SCHED_INTERACTIVE)
return -EINVAL;
/*
* Valid priorities for SCHED_FIFO and SCHED_RR are
@@ -4663,6 +4679,7 @@ asmlinkage long sys_sched_get_priority_m
break;
case SCHED_NORMAL:
case SCHED_BATCH:
+ case SCHED_INTERACTIVE:
ret = 0;
break;
}
@@ -4687,6 +4704,7 @@ asmlinkage long sys_sched_get_priority_m
break;
case SCHED_NORMAL:
case SCHED_BATCH:
+ case SCHED_INTERACTIVE:
ret = 0;
}
return ret;
View attachment "schedctl.c" of type "text/x-csrc" (10236 bytes)
Powered by blists - more mailing lists