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