Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
19c5d690 WL |
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 | ||
5149cbac WL |
19 | #ifdef CONFIG_DEBUG_RWSEMS |
20 | # define DEBUG_RWSEMS_WARN_ON(c) DEBUG_LOCKS_WARN_ON(c) | |
21 | #else | |
22 | # define DEBUG_RWSEMS_WARN_ON(c) | |
23 | #endif | |
24 | ||
7a215f89 | 25 | #ifdef CONFIG_RWSEM_SPIN_ON_OWNER |
fb6a44f3 WL |
26 | /* |
27 | * All writes to owner are protected by WRITE_ONCE() to make sure that | |
28 | * store tearing can't happen as optimistic spinners may read and use | |
29 | * the owner value concurrently without lock. Read from owner, however, | |
30 | * may not need READ_ONCE() as long as the pointer value is only used | |
31 | * for comparison and isn't being dereferenced. | |
32 | */ | |
7a215f89 DB |
33 | static inline void rwsem_set_owner(struct rw_semaphore *sem) |
34 | { | |
fb6a44f3 | 35 | WRITE_ONCE(sem->owner, current); |
7a215f89 DB |
36 | } |
37 | ||
38 | static inline void rwsem_clear_owner(struct rw_semaphore *sem) | |
39 | { | |
fb6a44f3 | 40 | WRITE_ONCE(sem->owner, NULL); |
7a215f89 DB |
41 | } |
42 | ||
19c5d690 WL |
43 | static inline void rwsem_set_reader_owned(struct rw_semaphore *sem) |
44 | { | |
45 | /* | |
46 | * We check the owner value first to make sure that we will only | |
47 | * do a write to the rwsem cacheline when it is really necessary | |
48 | * to minimize cacheline contention. | |
49 | */ | |
5149cbac | 50 | if (READ_ONCE(sem->owner) != RWSEM_READER_OWNED) |
fb6a44f3 | 51 | WRITE_ONCE(sem->owner, RWSEM_READER_OWNED); |
19c5d690 WL |
52 | } |
53 | ||
54 | static inline bool rwsem_owner_is_writer(struct task_struct *owner) | |
55 | { | |
56 | return owner && owner != RWSEM_READER_OWNED; | |
57 | } | |
58 | ||
59 | static inline bool rwsem_owner_is_reader(struct task_struct *owner) | |
60 | { | |
61 | return owner == RWSEM_READER_OWNED; | |
62 | } | |
7a215f89 DB |
63 | #else |
64 | static inline void rwsem_set_owner(struct rw_semaphore *sem) | |
65 | { | |
66 | } | |
67 | ||
68 | static inline void rwsem_clear_owner(struct rw_semaphore *sem) | |
69 | { | |
70 | } | |
19c5d690 WL |
71 | |
72 | static inline void rwsem_set_reader_owned(struct rw_semaphore *sem) | |
73 | { | |
74 | } | |
7a215f89 | 75 | #endif |