higher scheduler load resolution
Linus,
Please pull the latest sched-core-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git sched-core-for-linus
This is something that came a bit late so i kept separate and under observation
- but i think it's good and ready for v2.6.40. This change allows better balancing for larger amounts of cgroups (on 64-bit systems) - we were running out of resolution.
Thanks,
Ingo
------------------>
Nikhil Rao (3):
sched: Cleanup set_load_weight()
sched: Introduce SCHED_POWER_SCALE to scale cpu_power calculations
sched: Increase SCHED_LOAD_SCALE resolution
include/linux/sched.h | 34 ++++++++++++++++++++++++++----- kernel/sched.c | 39 +++++++++++++++++++++++++----------- kernel/sched_fair.c | 52 +++++++++++++++++++++++++----------------------- 3 files changed, 82 insertions(+), 43 deletions(-)
include/linux/sched.h +28 -6
@@ -788,17 +788,39 @@ enum cpu_idle_type { };/* -* sched-domains (multiprocessor balancing) declarations: +* Increase resolution of nice-level calculations for 64-bit architectures. +* The extra resolution improves shares distribution and load balancing of +* low-weight task groups (eg. nice +19 on an autogroup), deeper taskgroup +* hierarchies, especially on larger systems. This is not a user-visible change +* and does not change the user-interface for setting shares/weights. +* +* We increase resolution only if we have enough bits to allow this increased +* resolution (i.e. BITS_PER_LONG > 32). The costs for increasing resolution +* when BITS_PER_LONG <= 32 are pretty high and the returns do not justify the +* increased costs. */ +#if BITS_PER_LONG >32 +# define SCHED_LOAD_RESOLUTION 10 +# define scale_load (w) ((w) << SCHED_LOAD_RESOLUTION) +# define scale_load_down (w) ((w) >> SCHED_LOAD_RESOLUTION) +#else +# define SCHED_LOAD_RESOLUTION 0 +# define scale_load (w) (w) +# define scale_load_down (w) (w) +#endif -/* -* Increase resolution of nice-level calculations: -*/ -#define SCHED_LOAD_SHIFT 10 +#define SCHED_LOAD_SHIFT (10 + SCHED_LOAD_RESOLUTION)#define SCHED_LOAD_SCALE (1L << SCHED_LOAD_SHIFT) -#define SCHED_LOAD_SCALE_FUZZ SCHED_LOAD_SCALE +/* +* Increase resolution of cpu_power calculations +*/ +#define SCHED_POWER_SHIFT 10 +#define SCHED_POWER_SCALE (1L << SCHED_POWER_SHIFT) +/* +* sched-domains (multiprocessor balancing) declarations: +*/ #ifdef CONFIG_SMP #define SD_LOAD_BALANCE 0x0001/* Do load balancing on this domain. */ #define SD_BALANCE_NEWIDLE 0x0002/* Balance when about to become idle */
kernel/sched.c +27 -12
@@ -293,7 +293,7 @@ static DEFINE_SPINLOCK(task_group_lock);* limitation from this.) */ #define MIN_SHARES 2 -#define MAX_SHARES (1UL << 18) +#define MAX_SHARES (1UL << (18 + SCHED_LOAD_RESOLUTION))static int root_task_group_load =ROOT_TASK_GROUP_LOAD ;#endif
@@ -1330,13 +1330,25 @@ calc_delta_mine(unsigned long delta_exec, unsigned long weight, {u64 tmp; - tmp = (u64 )delta_exec * weight; +/* +* weight can be less than 2^SCHED_LOAD_RESOLUTION for task group sched +* entities since MIN_SHARES = 2. Treat weight as 1 if less than +* 2^SCHED_LOAD_RESOLUTION. +*/ +if (likely (weight > (1UL <<SCHED_LOAD_RESOLUTION ))) + tmp = (u64 )delta_exec *scale_load_down (weight); +else + tmp = (u64 )delta_exec;if (!lw->inv_weight) { -if (BITS_PER_LONG >32 &&unlikely (lw->weight >=WMULT_CONST )) +unsigned long w =scale_load_down (lw->weight); + +if (BITS_PER_LONG >32 &&unlikely (w >=WMULT_CONST )) lw->inv_weight =1 ; +else if (unlikely (!w)) + lw->inv_weight =WMULT_CONST ;else - lw->inv_weight =WMULT_CONST / lw->weight; + lw->inv_weight =WMULT_CONST / w; }/*
@@ -1778,17 +1790,20 @@ static void dec_nr_running(struct rq *rq)static void set_load_weight (struct task_struct *p) { +int prio = p->static_prio -MAX_RT_PRIO ; +struct load_weight *load = &p->se.load; +/* * SCHED_IDLE tasks get minimal weight: */ if (p->policy ==SCHED_IDLE ) { - p->se.load.weight =WEIGHT_IDLEPRIO ; - p->se.load.inv_weight =WMULT_IDLEPRIO ; + load->weight =scale_load (WEIGHT_IDLEPRIO ); + load->inv_weight =WMULT_IDLEPRIO ;return ; } - p->se.load.weight = prio_to_weight[p->static_prio -MAX_RT_PRIO ]; - p->se.load.inv_weight = prio_to_wmult[p->static_prio -MAX_RT_PRIO ]; + load->weight =scale_load (prio_to_weight[prio]); + load->inv_weight = prio_to_wmult[prio]; }static void enqueue_task (struct rq *rq,struct task_struct *p,int flags)
@@ -6527,7 +6542,7 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,cpulist_scnprintf (str,sizeof (str),sched_group_cpus (group));printk (KERN_CONT " %s" , str); -if (group->cpu_power !=SCHED_LOAD_SCALE ) { +if (group->cpu_power !=SCHED_POWER_SCALE ) {printk (KERN_CONT " (cpu_power = %d)" , group->cpu_power); }
@@ -7902,7 +7917,7 @@ void __init sched_init(void)#ifdef CONFIG_SMP rq->sd =NULL ; rq->rd =NULL ; - rq->cpu_power =SCHED_LOAD_SCALE ; + rq->cpu_power =SCHED_POWER_SCALE ; rq->post_schedule =0 ; rq->active_balance =0 ; rq->next_balance = jiffies;
@@ -8806,14 +8821,14 @@ cpu_cgroup_exit(struct cgroup_subsys *ss, struct cgroup *cgrp,static int cpu_shares_write_u64 (struct cgroup *cgrp,struct cftype *cftype,u64 shareval) { -return sched_group_set_shares (cgroup_tg (cgrp), shareval); +return sched_group_set_shares (cgroup_tg (cgrp),scale_load (shareval)); }static u64 cpu_shares_read_u64 (struct cgroup *cgrp,struct cftype *cft) {struct task_group *tg =cgroup_tg (cgrp); -return (u64 ) tg->shares; +return (u64 )scale_load_down (tg->shares); }#endif /* CONFIG_FAIR_GROUP_SCHED */
kernel/sched_fair.c +27 -25
177 lines not on this page · raw message