diff options
Diffstat (limited to 'kernel/locking')
| -rw-r--r-- | kernel/locking/rwsem-xadd.c | 31 |
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 | ||
| 327 | static 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 | |||
| 344 | static noinline | 327 | static noinline |
| 345 | bool rwsem_spin_on_owner(struct rw_semaphore *sem, struct task_struct *owner) | 328 | bool 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 | } |
