Waiman Long | 19c5d69 | 2016-05-17 21:26:19 -0400 | [diff] [blame] | 1 | /* |
| 2 | * The owner field of the rw_semaphore structure will be set to |
| 3 | * RWSEM_READ_OWNED when a reader grabs the lock. A writer will clear |
| 4 | * the owner field when it unlocks. A reader, on the other hand, will |
| 5 | * not touch the owner field when it unlocks. |
| 6 | * |
| 7 | * In essence, the owner field now has the following 3 states: |
| 8 | * 1) 0 |
| 9 | * - lock is free or the owner hasn't set the field yet |
| 10 | * 2) RWSEM_READER_OWNED |
| 11 | * - lock is currently or previously owned by readers (lock is free |
| 12 | * or not set by owner yet) |
| 13 | * 3) Other non-zero value |
| 14 | * - a writer owns the lock |
| 15 | */ |
| 16 | #define RWSEM_READER_OWNED ((struct task_struct *)1UL) |
| 17 | |
Davidlohr Bueso | 7a215f8 | 2015-01-30 01:14:25 -0800 | [diff] [blame] | 18 | #ifdef CONFIG_RWSEM_SPIN_ON_OWNER |
Waiman Long | fb6a44f | 2016-05-17 21:26:20 -0400 | [diff] [blame] | 19 | /* |
| 20 | * All writes to owner are protected by WRITE_ONCE() to make sure that |
| 21 | * store tearing can't happen as optimistic spinners may read and use |
| 22 | * the owner value concurrently without lock. Read from owner, however, |
| 23 | * may not need READ_ONCE() as long as the pointer value is only used |
| 24 | * for comparison and isn't being dereferenced. |
| 25 | */ |
Davidlohr Bueso | 7a215f8 | 2015-01-30 01:14:25 -0800 | [diff] [blame] | 26 | static inline void rwsem_set_owner(struct rw_semaphore *sem) |
| 27 | { |
Waiman Long | fb6a44f | 2016-05-17 21:26:20 -0400 | [diff] [blame] | 28 | WRITE_ONCE(sem->owner, current); |
Davidlohr Bueso | 7a215f8 | 2015-01-30 01:14:25 -0800 | [diff] [blame] | 29 | } |
| 30 | |
| 31 | static inline void rwsem_clear_owner(struct rw_semaphore *sem) |
| 32 | { |
Waiman Long | fb6a44f | 2016-05-17 21:26:20 -0400 | [diff] [blame] | 33 | WRITE_ONCE(sem->owner, NULL); |
Davidlohr Bueso | 7a215f8 | 2015-01-30 01:14:25 -0800 | [diff] [blame] | 34 | } |
| 35 | |
Waiman Long | 19c5d69 | 2016-05-17 21:26:19 -0400 | [diff] [blame] | 36 | static inline void rwsem_set_reader_owned(struct rw_semaphore *sem) |
| 37 | { |
| 38 | /* |
| 39 | * We check the owner value first to make sure that we will only |
| 40 | * do a write to the rwsem cacheline when it is really necessary |
| 41 | * to minimize cacheline contention. |
| 42 | */ |
| 43 | if (sem->owner != RWSEM_READER_OWNED) |
Waiman Long | fb6a44f | 2016-05-17 21:26:20 -0400 | [diff] [blame] | 44 | WRITE_ONCE(sem->owner, RWSEM_READER_OWNED); |
Waiman Long | 19c5d69 | 2016-05-17 21:26:19 -0400 | [diff] [blame] | 45 | } |
| 46 | |
| 47 | static inline bool rwsem_owner_is_writer(struct task_struct *owner) |
| 48 | { |
| 49 | return owner && owner != RWSEM_READER_OWNED; |
| 50 | } |
| 51 | |
| 52 | static inline bool rwsem_owner_is_reader(struct task_struct *owner) |
| 53 | { |
| 54 | return owner == RWSEM_READER_OWNED; |
| 55 | } |
Davidlohr Bueso | 7a215f8 | 2015-01-30 01:14:25 -0800 | [diff] [blame] | 56 | #else |
| 57 | static inline void rwsem_set_owner(struct rw_semaphore *sem) |
| 58 | { |
| 59 | } |
| 60 | |
| 61 | static inline void rwsem_clear_owner(struct rw_semaphore *sem) |
| 62 | { |
| 63 | } |
Waiman Long | 19c5d69 | 2016-05-17 21:26:19 -0400 | [diff] [blame] | 64 | |
| 65 | static inline void rwsem_set_reader_owned(struct rw_semaphore *sem) |
| 66 | { |
| 67 | } |
Davidlohr Bueso | 7a215f8 | 2015-01-30 01:14:25 -0800 | [diff] [blame] | 68 | #endif |