Branch data Line data Source code
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>
9 : : #include <linux/sched.h>
10 : : #include <linux/export.h>
11 : : #include <linux/rwsem.h>
12 : :
13 : : #include <linux/atomic.h>
14 : :
15 : : /*
16 : : * lock for reading
17 : : */
18 : 0 : void __sched down_read(struct rw_semaphore *sem)
19 : : {
20 : : might_sleep();
21 : : rwsem_acquire_read(&sem->dep_map, 0, 0, _RET_IP_);
22 : :
23 : 7606576 : LOCK_CONTENDED(sem, __down_read_trylock, __down_read);
24 : 7608984 : }
25 : :
26 : : EXPORT_SYMBOL(down_read);
27 : :
28 : : /*
29 : : * trylock for reading -- returns 1 if successful, 0 if contention
30 : : */
31 : 0 : int down_read_trylock(struct rw_semaphore *sem)
32 : : {
33 : 67645280 : int ret = __down_read_trylock(sem);
34 : :
35 : : if (ret == 1)
36 : : rwsem_acquire_read(&sem->dep_map, 0, 1, _RET_IP_);
37 : 67668886 : return ret;
38 : : }
39 : :
40 : : EXPORT_SYMBOL(down_read_trylock);
41 : :
42 : : /*
43 : : * lock for writing
44 : : */
45 : 0 : void __sched down_write(struct rw_semaphore *sem)
46 : : {
47 : : might_sleep();
48 : : rwsem_acquire(&sem->dep_map, 0, 0, _RET_IP_);
49 : :
50 : 45543051 : LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
51 : 45547557 : }
52 : :
53 : : EXPORT_SYMBOL(down_write);
54 : :
55 : : /*
56 : : * trylock for writing -- returns 1 if successful, 0 if contention
57 : : */
58 : 0 : int down_write_trylock(struct rw_semaphore *sem)
59 : : {
60 : 0 : int ret = __down_write_trylock(sem);
61 : :
62 : : if (ret == 1)
63 : : rwsem_acquire(&sem->dep_map, 0, 1, _RET_IP_);
64 : 0 : return ret;
65 : : }
66 : :
67 : : EXPORT_SYMBOL(down_write_trylock);
68 : :
69 : : /*
70 : : * release a read lock
71 : : */
72 : 0 : void up_read(struct rw_semaphore *sem)
73 : : {
74 : : rwsem_release(&sem->dep_map, 1, _RET_IP_);
75 : :
76 : 75114445 : __up_read(sem);
77 : 75182981 : }
78 : :
79 : : EXPORT_SYMBOL(up_read);
80 : :
81 : : /*
82 : : * release a write lock
83 : : */
84 : 0 : void up_write(struct rw_semaphore *sem)
85 : : {
86 : : rwsem_release(&sem->dep_map, 1, _RET_IP_);
87 : :
88 : 45545735 : __up_write(sem);
89 : 45548196 : }
90 : :
91 : : EXPORT_SYMBOL(up_write);
92 : :
93 : : /*
94 : : * downgrade write lock to read lock
95 : : */
96 : 0 : void downgrade_write(struct rw_semaphore *sem)
97 : : {
98 : : /*
99 : : * lockdep: a downgraded write will live on as a write
100 : : * dependency.
101 : : */
102 : 0 : __downgrade_write(sem);
103 : 0 : }
104 : :
105 : : EXPORT_SYMBOL(downgrade_write);
106 : :
107 : : #ifdef CONFIG_DEBUG_LOCK_ALLOC
108 : :
109 : : void down_read_nested(struct rw_semaphore *sem, int subclass)
110 : : {
111 : : might_sleep();
112 : : rwsem_acquire_read(&sem->dep_map, subclass, 0, _RET_IP_);
113 : :
114 : : LOCK_CONTENDED(sem, __down_read_trylock, __down_read);
115 : : }
116 : :
117 : : EXPORT_SYMBOL(down_read_nested);
118 : :
119 : : void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest)
120 : : {
121 : : might_sleep();
122 : : rwsem_acquire_nest(&sem->dep_map, 0, 0, nest, _RET_IP_);
123 : :
124 : : LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
125 : : }
126 : :
127 : : EXPORT_SYMBOL(_down_write_nest_lock);
128 : :
129 : : void down_read_non_owner(struct rw_semaphore *sem)
130 : : {
131 : : might_sleep();
132 : :
133 : : __down_read(sem);
134 : : }
135 : :
136 : : EXPORT_SYMBOL(down_read_non_owner);
137 : :
138 : : void down_write_nested(struct rw_semaphore *sem, int subclass)
139 : : {
140 : : might_sleep();
141 : : rwsem_acquire(&sem->dep_map, subclass, 0, _RET_IP_);
142 : :
143 : : LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
144 : : }
145 : :
146 : : EXPORT_SYMBOL(down_write_nested);
147 : :
148 : : void up_read_non_owner(struct rw_semaphore *sem)
149 : : {
150 : : __up_read(sem);
151 : : }
152 : :
153 : : EXPORT_SYMBOL(up_read_non_owner);
154 : :
155 : : #endif
156 : :
157 : :
|