scheduler: Make tuning knobs global variables This patch replaces all #define "tuning knobs" in the scheduler with global variables that can be later manipulated by a genetic library plugin for the scheduler. Signed-off-by: Brandon Philips --- kernel/sched.c | 106 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 40 deletions(-) Index: linux-gl/kernel/sched.c =================================================================== --- linux-gl.orig/kernel/sched.c +++ linux-gl/kernel/sched.c @@ -87,18 +87,31 @@ * default timeslice is 100 msecs, maximum timeslice is 800 msecs. * Timeslices get refilled after they expire. */ -#define MIN_TIMESLICE max(5 * HZ / 1000, 1) -#define DEF_TIMESLICE (100 * HZ / 1000) -#define ON_RUNQUEUE_WEIGHT 30 -#define CHILD_PENALTY 95 -#define PARENT_PENALTY 100 -#define EXIT_WEIGHT 3 -#define PRIO_BONUS_RATIO 25 -#define MAX_BONUS (MAX_USER_PRIO * PRIO_BONUS_RATIO / 100) -#define INTERACTIVE_DELTA 2 -#define MAX_SLEEP_AVG (DEF_TIMESLICE * MAX_BONUS) -#define STARVATION_LIMIT (MAX_SLEEP_AVG) -#define NS_MAX_SLEEP_AVG (JIFFIES_TO_NS(MAX_SLEEP_AVG)) +#define DEFAULT_MIN_TIMESLICE max(5 * HZ / 1000, 1) +#define DEFAULT_DEF_TIMESLICE (100 * HZ / 1000) +#define DEFAULT_ON_RUNQUEUE_WEIGHT 30 +#define DEFAULT_CHILD_PENALTY 95 +#define DEFAULT_PARENT_PENALTY 100 +#define DEFAULT_EXIT_WEIGHT 3 +#define DEFAULT_PRIO_BONUS_RATIO 25 +#define DEFAULT_MAX_BONUS (MAX_USER_PRIO * DEFAULT_PRIO_BONUS_RATIO / 100) +#define DEFAULT_INTERACTIVE_DELTA 2 +#define DEFAULT_MAX_SLEEP_AVG (DEFAULT_DEF_TIMESLICE * DEFAULT_MAX_BONUS) +#define DEFAULT_STARVATION_LIMIT (DEFAULT_MAX_SLEEP_AVG) +#define DEFAULT_NS_MAX_SLEEP_AVG (JIFFIES_TO_NS(DEFAULT_MAX_SLEEP_AVG)) + +unsigned long min_timeslice; +unsigned long def_timeslice; +unsigned long on_runqueue_weight; +unsigned long child_penalty; +unsigned long parent_penalty; +unsigned long exit_weight; +unsigned long prio_bonus_ratio; +unsigned long max_bonus; +unsigned long interactive_delta; +unsigned long max_sleep_avg; +unsigned long starvation_limit; +unsigned long ns_max_sleep_avg; /* * If a task is 'interactive' then we reinsert it in the active @@ -108,7 +121,7 @@ * * This part scales the interactivity limit depending on niceness. * - * We scale it linearly, offset by the INTERACTIVE_DELTA delta. + * We scale it linearly, offset by the interactive_delta delta. * Here are a few examples of different nice levels: * * TASK_INTERACTIVE(-20): [1,1,1,1,1,1,1,1,1,0,0] @@ -129,33 +142,33 @@ */ #define CURRENT_BONUS(p) \ - (NS_TO_JIFFIES((p)->sleep_avg) * MAX_BONUS / \ - MAX_SLEEP_AVG) + (NS_TO_JIFFIES((p)->sleep_avg) * max_bonus / \ + max_sleep_avg) #define GRANULARITY (10 * HZ / 1000 ? : 1) #ifdef CONFIG_SMP #define TIMESLICE_GRANULARITY(p) (GRANULARITY * \ - (1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)) * \ + (1 << (((max_bonus - CURRENT_BONUS(p)) ? : 1) - 1)) * \ num_online_cpus()) #else #define TIMESLICE_GRANULARITY(p) (GRANULARITY * \ - (1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1))) + (1 << (((max_bonus - CURRENT_BONUS(p)) ? : 1) - 1))) #endif #define SCALE(v1,v1_max,v2_max) \ (v1) * (v2_max) / (v1_max) #define DELTA(p) \ - (SCALE(TASK_NICE(p) + 20, 40, MAX_BONUS) - 20 * MAX_BONUS / 40 + \ - INTERACTIVE_DELTA) + (SCALE(TASK_NICE(p) + 20, 40, max_bonus) - 20 * max_bonus / 40 + \ + interactive_delta) #define TASK_INTERACTIVE(p) \ ((p)->prio <= (p)->static_prio - DELTA(p)) #define INTERACTIVE_SLEEP(p) \ - (JIFFIES_TO_NS(MAX_SLEEP_AVG * \ - (MAX_BONUS / 2 + DELTA((p)) + 1) / MAX_BONUS - 1)) + (JIFFIES_TO_NS(max_sleep_avg * \ + (max_bonus / 2 + DELTA((p)) + 1) / max_bonus - 1)) #define TASK_PREEMPTS_CURR(p, rq) \ ((p)->prio < (rq)->curr->prio) @@ -170,14 +183,14 @@ */ #define SCALE_PRIO(x, prio) \ - max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE) + max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), min_timeslice) static unsigned int static_prio_timeslice(int static_prio) { if (static_prio < NICE_TO_PRIO(0)) - return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio); + return SCALE_PRIO(def_timeslice * 4, static_prio); else - return SCALE_PRIO(DEF_TIMESLICE, static_prio); + return SCALE_PRIO(def_timeslice, static_prio); } static inline unsigned int task_timeslice(struct task_struct *p) @@ -699,7 +712,7 @@ enqueue_task_head(struct task_struct *p, * __normal_prio - return the priority that is based on the static * priority but is modified by bonuses/penalties. * - * We scale the actual sleep average [0 .... MAX_SLEEP_AVG] + * We scale the actual sleep average [0 .... max_sleep_avg] * into the -5 ... 0 ... +5 bonus/penalty range. * * We use 25% of the full 0...39 priority range so that: @@ -714,7 +727,7 @@ static inline int __normal_prio(struct t { int bonus, prio; - bonus = CURRENT_BONUS(p) - MAX_BONUS / 2; + bonus = CURRENT_BONUS(p) - max_bonus / 2; prio = p->static_prio - bonus; if (prio < MAX_RT_PRIO) @@ -738,7 +751,7 @@ static inline int __normal_prio(struct t * If static_prio_timeslice() is ever changed to break this assumption then * this code will need modification */ -#define TIME_SLICE_NICE_ZERO DEF_TIMESLICE +#define TIME_SLICE_NICE_ZERO def_timeslice #define LOAD_WEIGHT(lp) \ (((lp) * SCHED_LOAD_SCALE) / TIME_SLICE_NICE_ZERO) #define PRIO_TO_LOAD_WEIGHT(prio) \ @@ -911,8 +924,8 @@ static int recalc_task_prio(struct task_ 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); @@ -1620,7 +1633,7 @@ void fastcall wake_up_new_task(struct ta * (current) is done further down, under its lock. */ p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) * - CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS); + child_penalty / 100 * max_sleep_avg / max_bonus); p->prio = effective_prio(p); @@ -1673,7 +1686,7 @@ void fastcall wake_up_new_task(struct ta this_rq = task_rq_lock(current, &flags); } current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) * - PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS); + parent_penalty / 100 * max_sleep_avg / max_bonus); task_rq_unlock(this_rq, &flags); } @@ -1703,8 +1716,8 @@ void fastcall sched_exit(struct task_str } if (p->sleep_avg < p->parent->sleep_avg) p->parent->sleep_avg = p->parent->sleep_avg / - (EXIT_WEIGHT + 1) * EXIT_WEIGHT + p->sleep_avg / - (EXIT_WEIGHT + 1); + (exit_weight + 1) * exit_weight + p->sleep_avg / + (exit_weight + 1); task_rq_unlock(rq, &flags); } @@ -2898,9 +2911,9 @@ static inline int expired_starving(struc { if (rq->curr->static_prio > rq->best_expired_prio) return 1; - if (!STARVATION_LIMIT || !rq->expired_timestamp) + if (!starvation_limit || !rq->expired_timestamp) return 0; - if (jiffies - rq->expired_timestamp > STARVATION_LIMIT * rq->nr_running) + if (jiffies - rq->expired_timestamp > starvation_limit * rq->nr_running) return 1; return 0; } @@ -3183,8 +3196,8 @@ dependent_sleeper(int this_cpu, struct r * With real time tasks we run non-rt tasks only * per_cpu_gain% of the time. */ - if ((jiffies % DEF_TIMESLICE) > - (sd->per_cpu_gain * DEF_TIMESLICE / 100)) + if ((jiffies % def_timeslice) > + (sd->per_cpu_gain * def_timeslice / 100)) ret = 1; } else { if (smt_curr->static_prio < p->static_prio && @@ -3296,12 +3309,12 @@ need_resched_nonpreemptible: schedstat_inc(rq, sched_cnt); now = sched_clock(); - if (likely((long long)(now - prev->timestamp) < NS_MAX_SLEEP_AVG)) { + if (likely((long long)(now - prev->timestamp) < ns_max_sleep_avg)) { run_time = now - prev->timestamp; if (unlikely((long long)(now - prev->timestamp) < 0)) run_time = 0; } else - run_time = NS_MAX_SLEEP_AVG; + run_time = ns_max_sleep_avg; /* * Tasks charged proportionately less run_time at high sleep_avg to @@ -3361,7 +3374,7 @@ need_resched_nonpreemptible: delta = 0; if (next->sleep_type == SLEEP_INTERACTIVE) - delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128; + delta = delta * (on_runqueue_weight * 128 / 100) / 128; array = next->array; new_prio = recalc_task_prio(next, next->timestamp + delta); @@ -6731,6 +6744,19 @@ void __init sched_init(void) { int i, j, k; + min_timeslice = DEFAULT_MIN_TIMESLICE; + def_timeslice = DEFAULT_DEF_TIMESLICE; + on_runqueue_weight = DEFAULT_ON_RUNQUEUE_WEIGHT; + child_penalty = DEFAULT_CHILD_PENALTY; + parent_penalty = DEFAULT_PARENT_PENALTY; + exit_weight = DEFAULT_EXIT_WEIGHT; + prio_bonus_ratio = DEFAULT_PRIO_BONUS_RATIO; + max_bonus = DEFAULT_MAX_BONUS; + interactive_delta = DEFAULT_INTERACTIVE_DELTA; + max_sleep_avg = DEFAULT_MAX_SLEEP_AVG; + starvation_limit = DEFAULT_STARVATION_LIMIT; + ns_max_sleep_avg = DEFAULT_NS_MAX_SLEEP_AVG; + for_each_possible_cpu(i) { struct prio_array *array; struct rq *rq;