diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2010-05-10 11:59:37 +0200 | 
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2010-05-10 14:20:42 +0200 | 
| commit | dbb6be6d5e974c42bbecd183effaa0df69e1dd8b (patch) | |
| tree | 5735cb47e70853d057a9881dd0ce44b83e88fa63 /kernel/sched.c | |
| parent | 6a867a395558a7f882d041783e4cdea6744ca2bf (diff) | |
| parent | b57f95a38233a2e73b679bea4a5453a1cc2a1cc9 (diff) | |
| download | olio-linux-3.10-dbb6be6d5e974c42bbecd183effaa0df69e1dd8b.tar.xz olio-linux-3.10-dbb6be6d5e974c42bbecd183effaa0df69e1dd8b.zip  | |
Merge branch 'linus' into timers/core
Reason: Further posix_cpu_timer patches depend on mainline changes
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/sched.c')
| -rw-r--r-- | kernel/sched.c | 33 | 
1 files changed, 24 insertions, 9 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 9ab3cd7858d..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 @@ -2650,7 +2661,7 @@ void wake_up_new_task(struct task_struct *p, unsigned long clone_flags)  {  	unsigned long flags;  	struct rq *rq; -	int cpu = get_cpu(); +	int cpu __maybe_unused = get_cpu();  #ifdef CONFIG_SMP  	/* @@ -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,9 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,  	int ret;  	cpumask_var_t mask; -	if (len < cpumask_size()) +	if ((len * BITS_PER_BYTE) < nr_cpu_ids) +		return -EINVAL; +	if (len & (sizeof(unsigned long)-1))  		return -EINVAL;  	if (!alloc_cpumask_var(&mask, GFP_KERNEL)) @@ -4910,10 +4923,12 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,  	ret = sched_getaffinity(pid, mask);  	if (ret == 0) { -		if (copy_to_user(user_mask_ptr, mask, cpumask_size())) +		size_t retlen = min_t(size_t, len, cpumask_size()); + +		if (copy_to_user(user_mask_ptr, mask, retlen))  			ret = -EFAULT;  		else -			ret = cpumask_size(); +			ret = retlen;  	}  	free_cpumask_var(mask); @@ -5383,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);  |