From: Con Kolivas <kernel@kolivas.org>

This patch addresses the problem of tasks that preempt their children when
they're forking, wasting cpu cycles until they get demoted to a priority
where they no longer preempt their child.  Although this has been said to be
a design flaw in the applications, it can cause sustained periods of
starvation due to this coding problem, and the more I looked, the more
examples I found of this happening.

Tasks now cannot preempt their own children.  This speeds up the startup of
child applications (eg pgp signed email).

This change has allowed tasks to stay at higher priority for much longer so
the sleep avg decay of high credit tasks has been changed to match the rate
of rise during periods of sleep (which I wanted to do originally but was
limited by the first problem).  This makes for much more sustained
interactivity at extreme loads, and much less X jerkiness.



 kernel/sched.c |   16 ++++++++++------
 1 files changed, 10 insertions(+), 6 deletions(-)

diff -puN kernel/sched.c~o15int kernel/sched.c
--- 25/kernel/sched.c~o15int	2003-08-30 15:42:04.000000000 -0700
+++ 25-akpm/kernel/sched.c	2003-08-30 15:42:04.000000000 -0700
@@ -620,8 +620,13 @@ repeat_lock_task:
 				__activate_task(p, rq);
 			else {
 				activate_task(p, rq);
-				if (TASK_PREEMPTS_CURR(p, rq))
-					resched_task(rq->curr);
+				/*
+				 * Parents are not allowed to preempt their
+				 * children
+				 */
+				if (TASK_PREEMPTS_CURR(p, rq) &&
+					p != rq->curr->parent)
+						resched_task(rq->curr);
 			}
 			success = 1;
 		}
@@ -1124,7 +1129,7 @@ static inline void pull_task(runqueue_t 
 	 * Note that idle threads have a prio of MAX_PRIO, for this test
 	 * to be always true for them.
 	 */
-	if (TASK_PREEMPTS_CURR(p, this_rq))
+	if (TASK_PREEMPTS_CURR(p, this_rq) && p != this_rq->curr->parent)
 		set_need_resched();
 }
 
@@ -1498,9 +1503,8 @@ need_resched:
 	 * priority bonus
 	 */
 	if (HIGH_CREDIT(prev))
-		run_time /= (MAX_BONUS + 1 -
-			(NS_TO_JIFFIES(prev->sleep_avg) * MAX_BONUS /
-			MAX_SLEEP_AVG));
+		run_time /= ((NS_TO_JIFFIES(prev->sleep_avg) * MAX_BONUS /
+				MAX_SLEEP_AVG) ? : 1);
 
 	spin_lock_irq(&rq->lock);
 

_