aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/locking
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/locking')
-rw-r--r--kernel/locking/rwsem-xadd.c31
1 files changed, 11 insertions, 20 deletions
diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c
index 06e2214edf98..3417d0172a5d 100644
--- a/kernel/locking/rwsem-xadd.c
+++ b/kernel/locking/rwsem-xadd.c
@@ -324,32 +324,23 @@ done:
324 return ret; 324 return ret;
325} 325}
326 326
327static inline bool owner_running(struct rw_semaphore *sem,
328 struct task_struct *owner)
329{
330 if (sem->owner != owner)
331 return false;
332
333 /*
334 * Ensure we emit the owner->on_cpu, dereference _after_ checking
335 * sem->owner still matches owner, if that fails, owner might
336 * point to free()d memory, if it still matches, the rcu_read_lock()
337 * ensures the memory stays valid.
338 */
339 barrier();
340
341 return owner->on_cpu;
342}
343
344static noinline 327static noinline
345bool rwsem_spin_on_owner(struct rw_semaphore *sem, struct task_struct *owner) 328bool rwsem_spin_on_owner(struct rw_semaphore *sem, struct task_struct *owner)
346{ 329{
347 long count; 330 long count;
348 331
349 rcu_read_lock(); 332 rcu_read_lock();
350 while (owner_running(sem, owner)) { 333 while (sem->owner == owner) {
351 /* abort spinning when need_resched */ 334 /*
352 if (need_resched()) { 335 * Ensure we emit the owner->on_cpu, dereference _after_
336 * checking sem->owner still matches owner, if that fails,
337 * owner might point to free()d memory, if it still matches,
338 * the rcu_read_lock() ensures the memory stays valid.
339 */
340 barrier();
341
342 /* abort spinning when need_resched or owner is not running */
343 if (!owner->on_cpu || need_resched()) {
353 rcu_read_unlock(); 344 rcu_read_unlock();
354 return false; 345 return false;
355 } 346 }