aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched.c
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2011-04-05 11:23:41 -0400
committerIngo Molnar <mingo@elte.hu>2011-04-14 02:52:33 -0400
commitc6eb3dda25892f1f974f5420f63e6721aab02f6f (patch)
treeb9be3e193dcfeda3589832be10189085cde496c5 /kernel/sched.c
parent3ca7a440da394808571dad32d33d3bc0389982e6 (diff)
mutex: Use p->on_cpu for the adaptive spin
Since we now have p->on_cpu unconditionally available, use it to re-implement mutex_spin_on_owner. Requested-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Frank Rowand <frank.rowand@am.sony.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Nick Piggin <npiggin@kernel.dk> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/20110405152728.826338173@chello.nl
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c83
1 files changed, 33 insertions, 50 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index cd2593e1a3ec..55cc50323ce1 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -4173,70 +4173,53 @@ need_resched:
4173EXPORT_SYMBOL(schedule); 4173EXPORT_SYMBOL(schedule);
4174 4174
4175#ifdef CONFIG_MUTEX_SPIN_ON_OWNER 4175#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
4176/*
4177 * Look out! "owner" is an entirely speculative pointer
4178 * access and not reliable.
4179 */
4180int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner)
4181{
4182 unsigned int cpu;
4183 struct rq *rq;
4184 4176
4185 if (!sched_feat(OWNER_SPIN)) 4177static inline bool owner_running(struct mutex *lock, struct task_struct *owner)
4186 return 0; 4178{
4179 bool ret = false;
4187 4180
4188#ifdef CONFIG_DEBUG_PAGEALLOC 4181 rcu_read_lock();
4189 /* 4182 if (lock->owner != owner)
4190 * Need to access the cpu field knowing that 4183 goto fail;
4191 * DEBUG_PAGEALLOC could have unmapped it if
4192 * the mutex owner just released it and exited.
4193 */
4194 if (probe_kernel_address(&owner->cpu, cpu))
4195 return 0;
4196#else
4197 cpu = owner->cpu;
4198#endif
4199 4184
4200 /* 4185 /*
4201 * Even if the access succeeded (likely case), 4186 * Ensure we emit the owner->on_cpu, dereference _after_ checking
4202 * the cpu field may no longer be valid. 4187 * lock->owner still matches owner, if that fails, owner might
4188 * point to free()d memory, if it still matches, the rcu_read_lock()
4189 * ensures the memory stays valid.
4203 */ 4190 */
4204 if (cpu >= nr_cpumask_bits) 4191 barrier();
4205 return 0;
4206 4192
4207 /* 4193 ret = owner->on_cpu;
4208 * We need to validate that we can do a 4194fail:
4209 * get_cpu() and that we have the percpu area. 4195 rcu_read_unlock();
4210 */
4211 if (!cpu_online(cpu))
4212 return 0;
4213 4196
4214 rq = cpu_rq(cpu); 4197 return ret;
4198}
4215 4199
4216 for (;;) { 4200/*
4217 /* 4201 * Look out! "owner" is an entirely speculative pointer
4218 * Owner changed, break to re-assess state. 4202 * access and not reliable.
4219 */ 4203 */
4220 if (lock->owner != owner) { 4204int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner)
4221 /* 4205{
4222 * If the lock has switched to a different owner, 4206 if (!sched_feat(OWNER_SPIN))
4223 * we likely have heavy contention. Return 0 to quit 4207 return 0;
4224 * optimistic spinning and not contend further:
4225 */
4226 if (lock->owner)
4227 return 0;
4228 break;
4229 }
4230 4208
4231 /* 4209 while (owner_running(lock, owner)) {
4232 * Is that owner really running on that cpu? 4210 if (need_resched())
4233 */
4234 if (task_thread_info(rq->curr) != owner || need_resched())
4235 return 0; 4211 return 0;
4236 4212
4237 arch_mutex_cpu_relax(); 4213 arch_mutex_cpu_relax();
4238 } 4214 }
4239 4215
4216 /*
4217 * If the owner changed to another task there is likely
4218 * heavy contention, stop spinning.
4219 */
4220 if (lock->owner)
4221 return 0;
4222
4240 return 1; 4223 return 1;
4241} 4224}
4242#endif 4225#endif