Index: MM-2.6.16/kernel/sched_spa_ws.c =================================================================== --- MM-2.6.16.orig/kernel/sched_spa_ws.c 2006-01-26 12:21:50.000000000 +1100 +++ MM-2.6.16/kernel/sched_spa_ws.c 2006-01-29 10:00:21.000000000 +1100 @@ -45,12 +45,20 @@ static unsigned int initial_ia_bonus = D #define LSHARES_AVG_ALPHA ((1 << LSHARES_AVG_OFFSET) - 2) #define LSHARES_AVG_INCR(a) ((a) << 1) #define LSHARES_AVG_REAL(s) ((s) << LSHARES_AVG_OFFSET) -#define LSHARES_AVG_ONE LSAHRES_AVG_REAL(1UL) +#define LSHARES_AVG_ONE LSHARES_AVG_REAL(1UL) #define LSHARES_AVG_MUL(a, b) (((a) * (b)) >> LSHARES_AVG_OFFSET) static unsigned int max_fairness_bonus = DEF_MAX_FAIRNESS_BONUS; -#define FAIRNESS_BONUS_OFFSET 8 +#define FAIRNESS_BONUS_OFFSET 5 +#define FAIRNESS_ALPHA ((1UL << FAIRNESS_BONUS_OFFSET) - 2) +#define FAIRNESS_ALPHA_COMPL 2 + +static inline int fairness_bonus(const struct task_struct *p) +{ + return (p->sdu.spa.auxilary_bonus * max_fairness_bonus) >> + FAIRNESS_BONUS_OFFSET; +} static DEFINE_PER_CPU(unsigned long, rq_avg_lshares); @@ -124,7 +132,7 @@ static inline void zero_interactive_bonu static inline int bonuses(const struct task_struct *p) { - return current_ia_bonus_rnd(p) + p->sdu.spa.auxilary_bonus; + return current_ia_bonus_rnd(p) + fairness_bonus(p); } static int spa_ws_effective_prio(const struct task_struct *p) @@ -161,65 +169,22 @@ static void spa_ws_fork(struct task_stru p->sdu.spa.interactive_bonus <<= IA_BONUS_OFFSET; } -static inline unsigned int map_ratio(unsigned long long a, - unsigned long long b, - unsigned int range) -{ - a *= range; - -#if BITS_PER_LONG < 64 - /* - * Assume that there's no 64 bit divide available - */ - if (a < b) - return 0; - /* - * Scale down until b less than 32 bits so that we can do - * a divide using do_div() - */ - while (b > ULONG_MAX) { a >>= 1; b >>= 1; } - - (void)do_div(a, (unsigned long)b); - - return a; -#else - return a / b; -#endif -} - static void spa_ws_reassess_fairness_bonus(struct task_struct *p) { - unsigned long long expected_delay, adjusted_delay; - unsigned long long avg_lshares; - unsigned long pshares; - - p->sdu.spa.auxilary_bonus = 0; - if (max_fairness_bonus == 0) - return; + unsigned long long expected_delay; + unsigned long long wanr; /* weighted average number running */ - pshares = LSHARES_AVG_REAL(p->sdu.spa.eb_shares); - avg_lshares = per_cpu(rq_avg_lshares, task_cpu(p)); - if (avg_lshares <= pshares) + wanr = per_cpu(rq_avg_lshares, task_cpu(p)) / p->sdu.spa.eb_shares; + if (wanr <= LSHARES_AVG_ONE) expected_delay = 0; - else { - expected_delay = p->sdu.spa.avg_cpu_per_cycle * - (avg_lshares - pshares); - (void)do_div(expected_delay, pshares); - } - - /* - * No delay means no bonus, but - * NB this test also avoids a possible divide by zero error if - * cpu is also zero and negative bonuses - */ - if (p->sdu.spa.avg_delay_per_cycle <= expected_delay) - return; - - adjusted_delay = p->sdu.spa.avg_delay_per_cycle - expected_delay; - p->sdu.spa.auxilary_bonus = - map_ratio(adjusted_delay, - adjusted_delay + p->sdu.spa.avg_cpu_per_cycle, - max_fairness_bonus); + else + expected_delay = LSHARES_AVG_MUL(p->sdu.spa.avg_cpu_per_cycle, + (wanr - LSHARES_AVG_ONE)); + + p->sdu.spa.auxilary_bonus *= FAIRNESS_ALPHA; + p->sdu.spa.auxilary_bonus >>= FAIRNESS_BONUS_OFFSET; + if (p->sdu.spa.avg_delay_per_cycle > expected_delay) + p->sdu.spa.auxilary_bonus += FAIRNESS_ALPHA_COMPL; } static inline int spa_ws_eligible(struct task_struct *p)