Greg Kroah-Hartman | b244131 | 2017-11-01 15:07:57 +0100 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
Waiman Long | 19c5d69 | 2016-05-17 21:26:19 -0400 | [diff] [blame] | 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 | |
Davidlohr Bueso | 7a215f8 | 2015-01-30 01:14:25 -0800 | [diff] [blame] | 19 | #ifdef CONFIG_RWSEM_SPIN_ON_OWNER |
Waiman Long | fb6a44f | 2016-05-17 21:26:20 -0400 | [diff] [blame] | 20 | /* |
| 21 | * All writes to owner are protected by WRITE_ONCE() to make sure that |
| 22 | * store tearing can't happen as optimistic spinners may read and use |
| 23 | * the owner value concurrently without lock. Read from owner, however, |
| 24 | * may not need READ_ONCE() as long as the pointer value is only used |
| 25 | * for comparison and isn't being dereferenced. |
| 26 | */ |
Davidlohr Bueso | 7a215f8 | 2015-01-30 01:14:25 -0800 | [diff] [blame] | 27 | static inline void rwsem_set_owner(struct rw_semaphore *sem) |
| 28 | { |
Waiman Long | fb6a44f | 2016-05-17 21:26:20 -0400 | [diff] [blame] | 29 | WRITE_ONCE(sem->owner, current); |
Davidlohr Bueso | 7a215f8 | 2015-01-30 01:14:25 -0800 | [diff] [blame] | 30 | } |
| 31 | |
| 32 | static inline void rwsem_clear_owner(struct rw_semaphore *sem) |
| 33 | { |
Waiman Long | fb6a44f | 2016-05-17 21:26:20 -0400 | [diff] [blame] | 34 | WRITE_ONCE(sem->owner, NULL); |
Davidlohr Bueso | 7a215f8 | 2015-01-30 01:14:25 -0800 | [diff] [blame] | 35 | } |
| 36 | |
Waiman Long | 19c5d69 | 2016-05-17 21:26:19 -0400 | [diff] [blame] | 37 | static inline void rwsem_set_reader_owned(struct rw_semaphore *sem) |
| 38 | { |
| 39 | /* |
| 40 | * We check the owner value first to make sure that we will only |
| 41 | * do a write to the rwsem cacheline when it is really necessary |
| 42 | * to minimize cacheline contention. |
| 43 | */ |
| 44 | if (sem->owner != RWSEM_READER_OWNED) |
Waiman Long | fb6a44f | 2016-05-17 21:26:20 -0400 | [diff] [blame] | 45 | WRITE_ONCE(sem->owner, RWSEM_READER_OWNED); |
Waiman Long | 19c5d69 | 2016-05-17 21:26:19 -0400 | [diff] [blame] | 46 | } |
| 47 | |
| 48 | static inline bool rwsem_owner_is_writer(struct task_struct *owner) |
| 49 | { |
| 50 | return owner && owner != RWSEM_READER_OWNED; |
| 51 | } |
| 52 | |
| 53 | static inline bool rwsem_owner_is_reader(struct task_struct *owner) |
| 54 | { |
| 55 | return owner == RWSEM_READER_OWNED; |
| 56 | } |
Davidlohr Bueso | 7a215f8 | 2015-01-30 01:14:25 -0800 | [diff] [blame] | 57 | #else |
| 58 | static inline void rwsem_set_owner(struct rw_semaphore *sem) |
| 59 | { |
| 60 | } |
| 61 | |
| 62 | static inline void rwsem_clear_owner(struct rw_semaphore *sem) |
| 63 | { |
| 64 | } |
Waiman Long | 19c5d69 | 2016-05-17 21:26:19 -0400 | [diff] [blame] | 65 | |
| 66 | static inline void rwsem_set_reader_owned(struct rw_semaphore *sem) |
| 67 | { |
| 68 | } |
Davidlohr Bueso | 7a215f8 | 2015-01-30 01:14:25 -0800 | [diff] [blame] | 69 | #endif |