Merge branch 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull locking fixes from Thomas Gleixner:
"Two fixes to address shortcomings of the rwsem/percpu-rwsem lock
debugging code which emits false positive warnings when the rwsem is
anonymously locked and unlocked"

* 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
locking/percpu-rwsem: Annotate rwsem ownership transfer by setting RWSEM_OWNER_UNKNOWN
locking/rwsem: Add a new RWSEM_ANONYMOUSLY_OWNED flag

+41 -22
+5 -1
include/linux/percpu-rwsem.h
··· 133 lock_release(&sem->rw_sem.dep_map, 1, ip); 134 #ifdef CONFIG_RWSEM_SPIN_ON_OWNER 135 if (!read) 136 - sem->rw_sem.owner = NULL; 137 #endif 138 } 139 ··· 141 bool read, unsigned long ip) 142 { 143 lock_acquire(&sem->rw_sem.dep_map, 0, 1, read, 1, NULL, ip); 144 } 145 146 #endif
··· 133 lock_release(&sem->rw_sem.dep_map, 1, ip); 134 #ifdef CONFIG_RWSEM_SPIN_ON_OWNER 135 if (!read) 136 + sem->rw_sem.owner = RWSEM_OWNER_UNKNOWN; 137 #endif 138 } 139 ··· 141 bool read, unsigned long ip) 142 { 143 lock_acquire(&sem->rw_sem.dep_map, 0, 1, read, 1, NULL, ip); 144 + #ifdef CONFIG_RWSEM_SPIN_ON_OWNER 145 + if (!read) 146 + sem->rw_sem.owner = current; 147 + #endif 148 } 149 150 #endif
+6
include/linux/rwsem.h
··· 44 #endif 45 }; 46 47 extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem); 48 extern struct rw_semaphore *rwsem_down_read_failed_killable(struct rw_semaphore *sem); 49 extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
··· 44 #endif 45 }; 46 47 + /* 48 + * Setting bit 0 of the owner field with other non-zero bits will indicate 49 + * that the rwsem is writer-owned with an unknown owner. 50 + */ 51 + #define RWSEM_OWNER_UNKNOWN ((struct task_struct *)-1L) 52 + 53 extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem); 54 extern struct rw_semaphore *rwsem_down_read_failed_killable(struct rw_semaphore *sem); 55 extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
+9 -10
kernel/locking/rwsem-xadd.c
··· 352 struct task_struct *owner; 353 bool ret = true; 354 355 if (need_resched()) 356 return false; 357 358 rcu_read_lock(); 359 owner = READ_ONCE(sem->owner); 360 - if (!rwsem_owner_is_writer(owner)) { 361 - /* 362 - * Don't spin if the rwsem is readers owned. 363 - */ 364 - ret = !rwsem_owner_is_reader(owner); 365 goto done; 366 } 367 ··· 381 { 382 struct task_struct *owner = READ_ONCE(sem->owner); 383 384 - if (!rwsem_owner_is_writer(owner)) 385 - goto out; 386 387 rcu_read_lock(); 388 - while (sem->owner == owner) { 389 /* 390 * Ensure we emit the owner->on_cpu, dereference _after_ 391 * checking sem->owner still matches owner, if that fails, ··· 407 cpu_relax(); 408 } 409 rcu_read_unlock(); 410 - out: 411 /* 412 * If there is a new owner or the owner is not set, we continue 413 * spinning. 414 */ 415 - return !rwsem_owner_is_reader(READ_ONCE(sem->owner)); 416 } 417 418 static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
··· 352 struct task_struct *owner; 353 bool ret = true; 354 355 + BUILD_BUG_ON(!rwsem_has_anonymous_owner(RWSEM_OWNER_UNKNOWN)); 356 + 357 if (need_resched()) 358 return false; 359 360 rcu_read_lock(); 361 owner = READ_ONCE(sem->owner); 362 + if (!owner || !is_rwsem_owner_spinnable(owner)) { 363 + ret = !owner; /* !owner is spinnable */ 364 goto done; 365 } 366 ··· 382 { 383 struct task_struct *owner = READ_ONCE(sem->owner); 384 385 + if (!is_rwsem_owner_spinnable(owner)) 386 + return false; 387 388 rcu_read_lock(); 389 + while (owner && (READ_ONCE(sem->owner) == owner)) { 390 /* 391 * Ensure we emit the owner->on_cpu, dereference _after_ 392 * checking sem->owner still matches owner, if that fails, ··· 408 cpu_relax(); 409 } 410 rcu_read_unlock(); 411 + 412 /* 413 * If there is a new owner or the owner is not set, we continue 414 * spinning. 415 */ 416 + return is_rwsem_owner_spinnable(READ_ONCE(sem->owner)); 417 } 418 419 static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
-2
kernel/locking/rwsem.c
··· 221 EXPORT_SYMBOL(up_read_non_owner); 222 223 #endif 224 - 225 -
··· 221 EXPORT_SYMBOL(up_read_non_owner); 222 223 #endif
+21 -9
kernel/locking/rwsem.h
··· 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * The owner field of the rw_semaphore structure will be set to 4 - * RWSEM_READ_OWNED when a reader grabs the lock. A writer will clear 5 * the owner field when it unlocks. A reader, on the other hand, will 6 * not touch the owner field when it unlocks. 7 * 8 - * In essence, the owner field now has the following 3 states: 9 * 1) 0 10 * - lock is free or the owner hasn't set the field yet 11 * 2) RWSEM_READER_OWNED 12 * - lock is currently or previously owned by readers (lock is free 13 * or not set by owner yet) 14 - * 3) Other non-zero value 15 - * - a writer owns the lock 16 */ 17 - #define RWSEM_READER_OWNED ((struct task_struct *)1UL) 18 19 #ifdef CONFIG_DEBUG_RWSEMS 20 # define DEBUG_RWSEMS_WARN_ON(c) DEBUG_LOCKS_WARN_ON(c) ··· 55 WRITE_ONCE(sem->owner, RWSEM_READER_OWNED); 56 } 57 58 - static inline bool rwsem_owner_is_writer(struct task_struct *owner) 59 { 60 - return owner && owner != RWSEM_READER_OWNED; 61 } 62 63 - static inline bool rwsem_owner_is_reader(struct task_struct *owner) 64 { 65 - return owner == RWSEM_READER_OWNED; 66 } 67 #else 68 static inline void rwsem_set_owner(struct rw_semaphore *sem)
··· 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * The owner field of the rw_semaphore structure will be set to 4 + * RWSEM_READER_OWNED when a reader grabs the lock. A writer will clear 5 * the owner field when it unlocks. A reader, on the other hand, will 6 * not touch the owner field when it unlocks. 7 * 8 + * In essence, the owner field now has the following 4 states: 9 * 1) 0 10 * - lock is free or the owner hasn't set the field yet 11 * 2) RWSEM_READER_OWNED 12 * - lock is currently or previously owned by readers (lock is free 13 * or not set by owner yet) 14 + * 3) RWSEM_ANONYMOUSLY_OWNED bit set with some other bits set as well 15 + * - lock is owned by an anonymous writer, so spinning on the lock 16 + * owner should be disabled. 17 + * 4) Other non-zero value 18 + * - a writer owns the lock and other writers can spin on the lock owner. 19 */ 20 + #define RWSEM_ANONYMOUSLY_OWNED (1UL << 0) 21 + #define RWSEM_READER_OWNED ((struct task_struct *)RWSEM_ANONYMOUSLY_OWNED) 22 23 #ifdef CONFIG_DEBUG_RWSEMS 24 # define DEBUG_RWSEMS_WARN_ON(c) DEBUG_LOCKS_WARN_ON(c) ··· 51 WRITE_ONCE(sem->owner, RWSEM_READER_OWNED); 52 } 53 54 + /* 55 + * Return true if the a rwsem waiter can spin on the rwsem's owner 56 + * and steal the lock, i.e. the lock is not anonymously owned. 57 + * N.B. !owner is considered spinnable. 58 + */ 59 + static inline bool is_rwsem_owner_spinnable(struct task_struct *owner) 60 { 61 + return !((unsigned long)owner & RWSEM_ANONYMOUSLY_OWNED); 62 } 63 64 + /* 65 + * Return true if rwsem is owned by an anonymous writer or readers. 66 + */ 67 + static inline bool rwsem_has_anonymous_owner(struct task_struct *owner) 68 { 69 + return (unsigned long)owner & RWSEM_ANONYMOUSLY_OWNED; 70 } 71 #else 72 static inline void rwsem_set_owner(struct rw_semaphore *sem)