Merge tag 'pci-v4.8-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
[deliverable/linux.git] / kernel / locking / rwsem.c
CommitLineData
c4e05116
IM
1/* kernel/rwsem.c: R/W semaphores, public implementation
2 *
3 * Written by David Howells (dhowells@redhat.com).
4 * Derived from asm-i386/semaphore.h
5 */
6
7#include <linux/types.h>
8#include <linux/kernel.h>
c7af77b5 9#include <linux/sched.h>
9984de1a 10#include <linux/export.h>
c4e05116 11#include <linux/rwsem.h>
60063497 12#include <linux/atomic.h>
c4e05116 13
7a215f89 14#include "rwsem.h"
4fc828e2 15
c4e05116
IM
16/*
17 * lock for reading
18 */
c7af77b5 19void __sched down_read(struct rw_semaphore *sem)
c4e05116
IM
20{
21 might_sleep();
22 rwsem_acquire_read(&sem->dep_map, 0, 0, _RET_IP_);
23
4fe87745 24 LOCK_CONTENDED(sem, __down_read_trylock, __down_read);
19c5d690 25 rwsem_set_reader_owned(sem);
c4e05116
IM
26}
27
28EXPORT_SYMBOL(down_read);
29
30/*
31 * trylock for reading -- returns 1 if successful, 0 if contention
32 */
33int down_read_trylock(struct rw_semaphore *sem)
34{
35 int ret = __down_read_trylock(sem);
36
19c5d690 37 if (ret == 1) {
c4e05116 38 rwsem_acquire_read(&sem->dep_map, 0, 1, _RET_IP_);
19c5d690
WL
39 rwsem_set_reader_owned(sem);
40 }
c4e05116
IM
41 return ret;
42}
43
44EXPORT_SYMBOL(down_read_trylock);
45
46/*
47 * lock for writing
48 */
c7af77b5 49void __sched down_write(struct rw_semaphore *sem)
c4e05116
IM
50{
51 might_sleep();
52 rwsem_acquire(&sem->dep_map, 0, 0, _RET_IP_);
53
4fe87745 54 LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
4fc828e2 55 rwsem_set_owner(sem);
c4e05116
IM
56}
57
58EXPORT_SYMBOL(down_write);
59
916633a4
MH
60/*
61 * lock for writing
62 */
63int __sched down_write_killable(struct rw_semaphore *sem)
64{
65 might_sleep();
66 rwsem_acquire(&sem->dep_map, 0, 0, _RET_IP_);
67
68 if (LOCK_CONTENDED_RETURN(sem, __down_write_trylock, __down_write_killable)) {
69 rwsem_release(&sem->dep_map, 1, _RET_IP_);
70 return -EINTR;
71 }
72
73 rwsem_set_owner(sem);
74 return 0;
75}
76
77EXPORT_SYMBOL(down_write_killable);
78
c4e05116
IM
79/*
80 * trylock for writing -- returns 1 if successful, 0 if contention
81 */
82int down_write_trylock(struct rw_semaphore *sem)
83{
84 int ret = __down_write_trylock(sem);
85
4fc828e2 86 if (ret == 1) {
428e6ce0 87 rwsem_acquire(&sem->dep_map, 0, 1, _RET_IP_);
4fc828e2
DB
88 rwsem_set_owner(sem);
89 }
90
c4e05116
IM
91 return ret;
92}
93
94EXPORT_SYMBOL(down_write_trylock);
95
96/*
97 * release a read lock
98 */
99void up_read(struct rw_semaphore *sem)
100{
101 rwsem_release(&sem->dep_map, 1, _RET_IP_);
102
103 __up_read(sem);
104}
105
106EXPORT_SYMBOL(up_read);
107
108/*
109 * release a write lock
110 */
111void up_write(struct rw_semaphore *sem)
112{
113 rwsem_release(&sem->dep_map, 1, _RET_IP_);
114
4fc828e2 115 rwsem_clear_owner(sem);
c4e05116
IM
116 __up_write(sem);
117}
118
119EXPORT_SYMBOL(up_write);
120
121/*
122 * downgrade write lock to read lock
123 */
124void downgrade_write(struct rw_semaphore *sem)
125{
126 /*
127 * lockdep: a downgraded write will live on as a write
128 * dependency.
129 */
19c5d690 130 rwsem_set_reader_owned(sem);
c4e05116
IM
131 __downgrade_write(sem);
132}
133
134EXPORT_SYMBOL(downgrade_write);
4ea2176d
IM
135
136#ifdef CONFIG_DEBUG_LOCK_ALLOC
137
138void down_read_nested(struct rw_semaphore *sem, int subclass)
139{
140 might_sleep();
141 rwsem_acquire_read(&sem->dep_map, subclass, 0, _RET_IP_);
142
4fe87745 143 LOCK_CONTENDED(sem, __down_read_trylock, __down_read);
19c5d690 144 rwsem_set_reader_owned(sem);
4ea2176d
IM
145}
146
147EXPORT_SYMBOL(down_read_nested);
148
1b963c81
JK
149void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest)
150{
151 might_sleep();
152 rwsem_acquire_nest(&sem->dep_map, 0, 0, nest, _RET_IP_);
153
154 LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
4fc828e2 155 rwsem_set_owner(sem);
1b963c81
JK
156}
157
158EXPORT_SYMBOL(_down_write_nest_lock);
159
84759c6d
KO
160void down_read_non_owner(struct rw_semaphore *sem)
161{
162 might_sleep();
163
164 __down_read(sem);
165}
166
167EXPORT_SYMBOL(down_read_non_owner);
168
4ea2176d
IM
169void down_write_nested(struct rw_semaphore *sem, int subclass)
170{
171 might_sleep();
172 rwsem_acquire(&sem->dep_map, subclass, 0, _RET_IP_);
173
4fe87745 174 LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
4fc828e2 175 rwsem_set_owner(sem);
4ea2176d
IM
176}
177
178EXPORT_SYMBOL(down_write_nested);
179
887bddfa
AV
180int __sched down_write_killable_nested(struct rw_semaphore *sem, int subclass)
181{
182 might_sleep();
183 rwsem_acquire(&sem->dep_map, subclass, 0, _RET_IP_);
184
185 if (LOCK_CONTENDED_RETURN(sem, __down_write_trylock, __down_write_killable)) {
186 rwsem_release(&sem->dep_map, 1, _RET_IP_);
187 return -EINTR;
188 }
189
190 rwsem_set_owner(sem);
191 return 0;
192}
193
194EXPORT_SYMBOL(down_write_killable_nested);
195
84759c6d
KO
196void up_read_non_owner(struct rw_semaphore *sem)
197{
198 __up_read(sem);
199}
200
201EXPORT_SYMBOL(up_read_non_owner);
202
4ea2176d
IM
203#endif
204
205
This page took 0.951285 seconds and 5 git commands to generate.