diff options
Diffstat (limited to 'kernel/sched/fair.c')
| -rw-r--r-- | kernel/sched/fair.c | 37 | 
1 files changed, 26 insertions, 11 deletions
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index c219bf8d704..96e2b18b628 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2052,7 +2052,7 @@ static void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b)  	hrtimer_cancel(&cfs_b->slack_timer);  } -void unthrottle_offline_cfs_rqs(struct rq *rq) +static void unthrottle_offline_cfs_rqs(struct rq *rq)  {  	struct cfs_rq *cfs_rq; @@ -2106,7 +2106,7 @@ static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg)  	return NULL;  }  static inline void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {} -void unthrottle_offline_cfs_rqs(struct rq *rq) {} +static inline void unthrottle_offline_cfs_rqs(struct rq *rq) {}  #endif /* CONFIG_CFS_BANDWIDTH */ @@ -2637,6 +2637,8 @@ static int select_idle_sibling(struct task_struct *p, int target)  	int cpu = smp_processor_id();  	int prev_cpu = task_cpu(p);  	struct sched_domain *sd; +	struct sched_group *sg; +	int i;  	/*  	 * If the task is going to be woken-up on this cpu and if it is @@ -2653,17 +2655,29 @@ static int select_idle_sibling(struct task_struct *p, int target)  		return prev_cpu;  	/* -	 * Otherwise, check assigned siblings to find an elegible idle cpu. +	 * Otherwise, iterate the domains and find an elegible idle cpu.  	 */  	sd = rcu_dereference(per_cpu(sd_llc, target)); -  	for_each_lower_domain(sd) { -		if (!cpumask_test_cpu(sd->idle_buddy, tsk_cpus_allowed(p))) -			continue; -		if (idle_cpu(sd->idle_buddy)) -			return sd->idle_buddy; -	} +		sg = sd->groups; +		do { +			if (!cpumask_intersects(sched_group_cpus(sg), +						tsk_cpus_allowed(p))) +				goto next; +			for_each_cpu(i, sched_group_cpus(sg)) { +				if (!idle_cpu(i)) +					goto next; +			} + +			target = cpumask_first_and(sched_group_cpus(sg), +					tsk_cpus_allowed(p)); +			goto done; +next: +			sg = sg->next; +		} while (sg != sd->groups); +	} +done:  	return target;  } @@ -3658,7 +3672,6 @@ fix_small_capacity(struct sched_domain *sd, struct sched_group *group)   * @group: sched_group whose statistics are to be updated.   * @load_idx: Load index of sched_domain of this_cpu for load calc.   * @local_group: Does group contain this_cpu. - * @cpus: Set of cpus considered for load balancing.   * @balance: Should we balance.   * @sgs: variable to hold the statistics for this group.   */ @@ -3805,7 +3818,6 @@ static bool update_sd_pick_busiest(struct lb_env *env,  /**   * update_sd_lb_stats - Update sched_domain's statistics for load balancing.   * @env: The load balancing environment. - * @cpus: Set of cpus considered for load balancing.   * @balance: Should we balance.   * @sds: variable to hold the statistics for this sched_domain.   */ @@ -4956,6 +4968,9 @@ static void rq_online_fair(struct rq *rq)  static void rq_offline_fair(struct rq *rq)  {  	update_sysctl(); + +	/* Ensure any throttled groups are reachable by pick_next_task */ +	unthrottle_offline_cfs_rqs(rq);  }  #endif /* CONFIG_SMP */  |