| 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 |
|
| 18 | #ifdef CONFIG_RWSEM_SPIN_ON_OWNER
|
| 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 |
|
| 26 | static inline void rwsem_set_owner(struct rw_semaphore *sem)
|
| 27 | {
|
| 28 | WRITE_ONCE(sem->owner, current);
|
| 29 | }
|
| 30 |
|
| 31 | static inline void rwsem_clear_owner(struct rw_semaphore *sem)
|
| 32 | {
|
| 33 | WRITE_ONCE(sem->owner, NULL);
|
| 34 | }
|
| 35 |
|
| 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)
|
| 44 | WRITE_ONCE(sem->owner, RWSEM_READER_OWNED);
|
| 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 | }
|
| 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 | }
|
| 64 |
|
| 65 | static inline void rwsem_set_reader_owned(struct rw_semaphore *sem)
|
| 66 | {
|
| 67 | }
|
| 68 | #endif
|