Index: linux-2.6.30-bfs/kernel/sched_bfs.c =================================================================== --- linux-2.6.30-bfs.orig/kernel/sched_bfs.c 2009-09-05 12:30:46.121952586 +1000 +++ linux-2.6.30-bfs/kernel/sched_bfs.c 2009-09-05 13:55:59.078645925 +1000 @@ -1393,7 +1393,9 @@ * Bank in p->sched_time the ns elapsed since the last tick or switch. * CPU scheduler quota accounting is also performed here in microseconds. * The value returned from sched_clock() occasionally gives bogus values so - * some sanity checking is required. + * some sanity checking is required. Time is supposed to be banked all the + * time so default to half a tick to make up for when sched_clock reverts + * to just returning jiffies, and for hardware that can't do tsc. */ static void update_cpu_clock(struct task_struct *p, struct rq *rq, unsigned long long now, @@ -1408,8 +1410,8 @@ */ if (time_diff > JIFFIES_TO_NS(2)) time_diff = JIFFIES_TO_NS(2); - else if (time_diff < 0) - time_diff = 0; + else if (time_diff <= 0) + time_diff = JIFFIES_TO_NS(1) / 2; } else { /* * Called from context_switch there should be less than one @@ -1417,8 +1419,8 @@ */ if (time_diff > JIFFIES_TO_NS(1)) time_diff = JIFFIES_TO_NS(1); - else if(time_diff < 0) - time_diff = 0; + else if (time_diff <= 0) + time_diff = JIFFIES_TO_NS(1) / 2; } /* time_slice accounting is done in usecs to avoid overflow on 32bit */ if (p != rq->idle && p->policy != SCHED_FIFO) @@ -1842,17 +1844,18 @@ } /* - * SCHED_IDLEPRIO tasks still have a deadline set, but equal to nice +19 for - * when they're scheduled as SCHED_NORMAL tasks. + * SCHED_IDLEPRIO tasks still have a deadline set, but offset by to nice +19. + * This allows nice levels to work between IDLEPRIO tasks and gives a + * deadline longer than nice +19 for when they're scheduled as SCHED_NORMAL + * tasks. */ static inline void time_slice_expired(struct task_struct *p) { reset_first_time_slice(p); p->time_slice = timeslice(); + p->deadline = jiffies + prio_deadline_diff(p); if (idleprio_task(p)) - p->deadline = jiffies + longest_deadline(); - else - p->deadline = jiffies + prio_deadline_diff(p); + p->deadline += longest_deadline(); } static inline void check_deadline(struct task_struct *p) @@ -1904,7 +1907,7 @@ goto out; } - long_deadline = shortest_deadline = longest_deadline() + 1; + long_deadline = shortest_deadline = longest_deadline() * 2 + 1; list_for_each_entry(p, queue, run_list) { unsigned long deadline_diff; /* Make sure cpu affinity is ok */ @@ -1913,8 +1916,8 @@ deadline_diff = p->deadline - jiffies; - /* Check for jiffy wrap! */ - if (unlikely(deadline_diff > long_deadline)) + /* Normalise all old deadlines and cope with jiffy wrap. */ + if (deadline_diff > long_deadline) deadline_diff = 0; /* Select the earliest deadline task now */ @@ -2713,7 +2716,7 @@ * * This is the priority value as seen by users in /proc. * RT tasks are offset by -100. Normal tasks are centered - * around 1, value goes from 0 to +40. + * around 1, value goes from 0 to +80. */ int task_prio(const struct task_struct *p) { @@ -2724,7 +2727,7 @@ goto out; delta = (p->deadline - jiffies) * 200 / prio_ratios[39]; - if (delta > 40 || delta < 0) + if (delta > 80 || delta < 0) delta = 0; prio += delta; out: