diff options
Diffstat (limited to 'kernel/sched.c')
| -rw-r--r-- | kernel/sched.c | 23 | 
1 files changed, 17 insertions, 6 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 49d2fa7b687..3c2a54f70ff 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -71,6 +71,7 @@  #include <linux/debugfs.h>  #include <linux/ctype.h>  #include <linux/ftrace.h> +#include <linux/slab.h>  #include <asm/tlb.h>  #include <asm/irq_regs.h> @@ -322,6 +323,15 @@ static inline struct task_group *task_group(struct task_struct *p)  /* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */  static inline void set_task_rq(struct task_struct *p, unsigned int cpu)  { +	/* +	 * Strictly speaking this rcu_read_lock() is not needed since the +	 * task_group is tied to the cgroup, which in turn can never go away +	 * as long as there are tasks attached to it. +	 * +	 * However since task_group() uses task_subsys_state() which is an +	 * rcu_dereference() user, this quiets CONFIG_PROVE_RCU. +	 */ +	rcu_read_lock();  #ifdef CONFIG_FAIR_GROUP_SCHED  	p->se.cfs_rq = task_group(p)->cfs_rq[cpu];  	p->se.parent = task_group(p)->se[cpu]; @@ -331,6 +341,7 @@ static inline void set_task_rq(struct task_struct *p, unsigned int cpu)  	p->rt.rt_rq  = task_group(p)->rt_rq[cpu];  	p->rt.parent = task_group(p)->rt_se[cpu];  #endif +	rcu_read_unlock();  }  #else @@ -3779,7 +3790,7 @@ int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner)  	 * the mutex owner just released it and exited.  	 */  	if (probe_kernel_address(&owner->cpu, cpu)) -		goto out; +		return 0;  #else  	cpu = owner->cpu;  #endif @@ -3789,14 +3800,14 @@ int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner)  	 * the cpu field may no longer be valid.  	 */  	if (cpu >= nr_cpumask_bits) -		goto out; +		return 0;  	/*  	 * We need to validate that we can do a  	 * get_cpu() and that we have the percpu area.  	 */  	if (!cpu_online(cpu)) -		goto out; +		return 0;  	rq = cpu_rq(cpu); @@ -3815,7 +3826,7 @@ int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner)  		cpu_relax();  	} -out: +  	return 1;  }  #endif @@ -4902,7 +4913,7 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,  	int ret;  	cpumask_var_t mask; -	if (len < nr_cpu_ids) +	if ((len * BITS_PER_BYTE) < nr_cpu_ids)  		return -EINVAL;  	if (len & (sizeof(unsigned long)-1))  		return -EINVAL; @@ -5387,7 +5398,7 @@ int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask)  		get_task_struct(mt);  		task_rq_unlock(rq, &flags); -		wake_up_process(rq->migration_thread); +		wake_up_process(mt);  		put_task_struct(mt);  		wait_for_completion(&req.done);  		tlb_migrate_finish(p->mm);  |