diff options
Diffstat (limited to 'kernel/sched/core.c')
| -rw-r--r-- | kernel/sched/core.c | 62 | 
1 files changed, 46 insertions, 16 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index e3ccc13c4caa..9c1629c90b2d 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1263,29 +1263,59 @@ EXPORT_SYMBOL_GPL(kick_process);   */  static int select_fallback_rq(int cpu, struct task_struct *p)  { -	int dest_cpu;  	const struct cpumask *nodemask = cpumask_of_node(cpu_to_node(cpu)); +	enum { cpuset, possible, fail } state = cpuset; +	int dest_cpu;  	/* Look for allowed, online CPU in same node. */ -	for_each_cpu_and(dest_cpu, nodemask, cpu_active_mask) +	for_each_cpu_mask(dest_cpu, *nodemask) { +		if (!cpu_online(dest_cpu)) +			continue; +		if (!cpu_active(dest_cpu)) +			continue;  		if (cpumask_test_cpu(dest_cpu, tsk_cpus_allowed(p)))  			return dest_cpu; +	} -	/* Any allowed, online CPU? */ -	dest_cpu = cpumask_any_and(tsk_cpus_allowed(p), cpu_active_mask); -	if (dest_cpu < nr_cpu_ids) -		return dest_cpu; +	for (;;) { +		/* Any allowed, online CPU? */ +		for_each_cpu_mask(dest_cpu, *tsk_cpus_allowed(p)) { +			if (!cpu_online(dest_cpu)) +				continue; +			if (!cpu_active(dest_cpu)) +				continue; +			goto out; +		} -	/* No more Mr. Nice Guy. */ -	dest_cpu = cpuset_cpus_allowed_fallback(p); -	/* -	 * Don't tell them about moving exiting tasks or -	 * kernel threads (both mm NULL), since they never -	 * leave kernel. -	 */ -	if (p->mm && printk_ratelimit()) { -		printk_sched("process %d (%s) no longer affine to cpu%d\n", -				task_pid_nr(p), p->comm, cpu); +		switch (state) { +		case cpuset: +			/* No more Mr. Nice Guy. */ +			cpuset_cpus_allowed_fallback(p); +			state = possible; +			break; + +		case possible: +			do_set_cpus_allowed(p, cpu_possible_mask); +			state = fail; +			break; + +		case fail: +			BUG(); +			break; +		} +	} + +out: +	if (state != cpuset) { +		/* +		 * Don't tell them about moving exiting tasks or +		 * kernel threads (both mm NULL), since they never +		 * leave kernel. +		 */ +		if (p->mm && printk_ratelimit()) { +			printk_sched("process %d (%s) no longer affine to cpu%d\n", +					task_pid_nr(p), p->comm, cpu); +		}  	}  	return dest_cpu;  |