Deleted Added
full compact
kern_sx.c (73901) kern_sx.c (74912)
1/*
2 * Copyright (C) 2001 Jason Evans <jasone@freebsd.org>. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice(s), this list of conditions and the following disclaimer as

--- 10 unchanged lines hidden (view full) ---

19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
25 * DAMAGE.
26 *
1/*
2 * Copyright (C) 2001 Jason Evans <jasone@freebsd.org>. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice(s), this list of conditions and the following disclaimer as

--- 10 unchanged lines hidden (view full) ---

19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
25 * DAMAGE.
26 *
27 * $FreeBSD: head/sys/kern/kern_sx.c 73901 2001-03-06 23:13:15Z jhb $
27 * $FreeBSD: head/sys/kern/kern_sx.c 74912 2001-03-28 09:03:24Z jhb $
28 */
29
30/*
31 * Shared/exclusive locks. This implementation assures deterministic lock
32 * granting behavior, so that slocks and xlocks are interleaved.
33 *
34 * Priority propagation will not generally raise the priority of lock holders,
35 * so should not be relied upon in combination with sx locks.

--- 5 unchanged lines hidden (view full) ---

41 * slock --> xlock (deadlock)
42 * slock --> slock (slock recursion, not fatal)
43 */
44
45#include <sys/param.h>
46#include <sys/systm.h>
47#include <sys/ktr.h>
48#include <sys/condvar.h>
28 */
29
30/*
31 * Shared/exclusive locks. This implementation assures deterministic lock
32 * granting behavior, so that slocks and xlocks are interleaved.
33 *
34 * Priority propagation will not generally raise the priority of lock holders,
35 * so should not be relied upon in combination with sx locks.

--- 5 unchanged lines hidden (view full) ---

41 * slock --> xlock (deadlock)
42 * slock --> slock (slock recursion, not fatal)
43 */
44
45#include <sys/param.h>
46#include <sys/systm.h>
47#include <sys/ktr.h>
48#include <sys/condvar.h>
49#include <sys/lock.h>
49#include <sys/mutex.h>
50#include <sys/sx.h>
51
50#include <sys/mutex.h>
51#include <sys/sx.h>
52
53/*
54 * XXX: We don't implement the LO_RECURSED flag for this lock yet.
55 * We could do this by walking p_sleeplocks if we really wanted to.
56 */
57struct lock_class lock_class_sx = {
58 "sx",
59 LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE
60};
61
52void
53sx_init(struct sx *sx, const char *description)
54{
62void
63sx_init(struct sx *sx, const char *description)
64{
65 struct lock_object *lock;
55
66
56 mtx_init(&sx->sx_lock, description, MTX_DEF);
67 bzero(sx, sizeof(*sx));
68 lock = &sx->sx_object;
69 lock->lo_class = &lock_class_sx;
70 lock->lo_name = description;
71 lock->lo_flags = LO_WITNESS | LO_SLEEPABLE;
72 mtx_init(&sx->sx_lock, "sx backing lock",
73 MTX_DEF | MTX_NOWITNESS | MTX_QUIET);
57 sx->sx_cnt = 0;
58 cv_init(&sx->sx_shrd_cv, description);
59 sx->sx_shrd_wcnt = 0;
60 cv_init(&sx->sx_excl_cv, description);
74 sx->sx_cnt = 0;
75 cv_init(&sx->sx_shrd_cv, description);
76 sx->sx_shrd_wcnt = 0;
77 cv_init(&sx->sx_excl_cv, description);
61 sx->sx_descr = description;
62 sx->sx_excl_wcnt = 0;
63 sx->sx_xholder = NULL;
78 sx->sx_excl_wcnt = 0;
79 sx->sx_xholder = NULL;
80
81 LOCK_LOG_INIT(lock, 0);
82
83 WITNESS_INIT(lock);
64}
65
66void
67sx_destroy(struct sx *sx)
68{
69
84}
85
86void
87sx_destroy(struct sx *sx)
88{
89
90 LOCK_LOG_DESTROY(&sx->sx_object, 0);
91
70 KASSERT((sx->sx_cnt == 0 && sx->sx_shrd_wcnt == 0 && sx->sx_excl_wcnt ==
92 KASSERT((sx->sx_cnt == 0 && sx->sx_shrd_wcnt == 0 && sx->sx_excl_wcnt ==
71 0), ("%s (%s): holders or waiters\n", __FUNCTION__, sx->sx_descr));
93 0), ("%s (%s): holders or waiters\n", __FUNCTION__,
94 sx->sx_object.lo_name));
72
73 mtx_destroy(&sx->sx_lock);
74 cv_destroy(&sx->sx_shrd_cv);
75 cv_destroy(&sx->sx_excl_cv);
95
96 mtx_destroy(&sx->sx_lock);
97 cv_destroy(&sx->sx_shrd_cv);
98 cv_destroy(&sx->sx_excl_cv);
99
100 WITNESS_DESTROY(&sx->sx_object);
76}
77
78void
101}
102
103void
79sx_slock(struct sx *sx)
104_sx_slock(struct sx *sx, const char *file, int line)
80{
81
82 mtx_lock(&sx->sx_lock);
83 KASSERT(sx->sx_xholder != curproc,
84 ("%s (%s): trying to get slock while xlock is held\n", __FUNCTION__,
105{
106
107 mtx_lock(&sx->sx_lock);
108 KASSERT(sx->sx_xholder != curproc,
109 ("%s (%s): trying to get slock while xlock is held\n", __FUNCTION__,
85 sx->sx_descr));
110 sx->sx_object.lo_name));
86
87 /*
88 * Loop in case we lose the race for lock acquisition.
89 */
90 while (sx->sx_cnt < 0) {
91 sx->sx_shrd_wcnt++;
92 cv_wait(&sx->sx_shrd_cv, &sx->sx_lock);
93 sx->sx_shrd_wcnt--;
94 }
95
96 /* Acquire a shared lock. */
97 sx->sx_cnt++;
98
111
112 /*
113 * Loop in case we lose the race for lock acquisition.
114 */
115 while (sx->sx_cnt < 0) {
116 sx->sx_shrd_wcnt++;
117 cv_wait(&sx->sx_shrd_cv, &sx->sx_lock);
118 sx->sx_shrd_wcnt--;
119 }
120
121 /* Acquire a shared lock. */
122 sx->sx_cnt++;
123
124#ifdef WITNESS
125 sx->sx_object.lo_flags |= LO_LOCKED;
126#endif
127 LOCK_LOG_LOCK("SLOCK", &sx->sx_object, 0, 0, file, line);
128 WITNESS_LOCK(&sx->sx_object, 0, file, line);
129
99 mtx_unlock(&sx->sx_lock);
100}
101
102void
130 mtx_unlock(&sx->sx_lock);
131}
132
133void
103sx_xlock(struct sx *sx)
134_sx_xlock(struct sx *sx, const char *file, int line)
104{
105
106 mtx_lock(&sx->sx_lock);
107
108 /*
109 * With sx locks, we're absolutely not permitted to recurse on
110 * xlocks, as it is fatal (deadlock). Normally, recursion is handled
111 * by WITNESS, but as it is not semantically correct to hold the
112 * xlock while in here, we consider it API abuse and put it under
113 * INVARIANTS.
114 */
115 KASSERT(sx->sx_xholder != curproc,
135{
136
137 mtx_lock(&sx->sx_lock);
138
139 /*
140 * With sx locks, we're absolutely not permitted to recurse on
141 * xlocks, as it is fatal (deadlock). Normally, recursion is handled
142 * by WITNESS, but as it is not semantically correct to hold the
143 * xlock while in here, we consider it API abuse and put it under
144 * INVARIANTS.
145 */
146 KASSERT(sx->sx_xholder != curproc,
116 ("%s (%s): xlock already held", __FUNCTION__, sx->sx_descr));
147 ("%s (%s): xlock already held @ %s:%d", __FUNCTION__,
148 sx->sx_object.lo_name, file, line));
117
118 /* Loop in case we lose the race for lock acquisition. */
119 while (sx->sx_cnt != 0) {
120 sx->sx_excl_wcnt++;
121 cv_wait(&sx->sx_excl_cv, &sx->sx_lock);
122 sx->sx_excl_wcnt--;
123 }
124
125 MPASS(sx->sx_cnt == 0);
126
127 /* Acquire an exclusive lock. */
128 sx->sx_cnt--;
129 sx->sx_xholder = curproc;
130
149
150 /* Loop in case we lose the race for lock acquisition. */
151 while (sx->sx_cnt != 0) {
152 sx->sx_excl_wcnt++;
153 cv_wait(&sx->sx_excl_cv, &sx->sx_lock);
154 sx->sx_excl_wcnt--;
155 }
156
157 MPASS(sx->sx_cnt == 0);
158
159 /* Acquire an exclusive lock. */
160 sx->sx_cnt--;
161 sx->sx_xholder = curproc;
162
163#ifdef WITNESS
164 sx->sx_object.lo_flags |= LO_LOCKED;
165#endif
166 LOCK_LOG_LOCK("XLOCK", &sx->sx_object, 0, 0, file, line);
167 WITNESS_LOCK(&sx->sx_object, 0, file, line);
168
131 mtx_unlock(&sx->sx_lock);
132}
133
134void
169 mtx_unlock(&sx->sx_lock);
170}
171
172void
135sx_sunlock(struct sx *sx)
173_sx_sunlock(struct sx *sx, const char *file, int line)
136{
137
138 mtx_lock(&sx->sx_lock);
139 _SX_ASSERT_SLOCKED(sx);
140
174{
175
176 mtx_lock(&sx->sx_lock);
177 _SX_ASSERT_SLOCKED(sx);
178
179#ifdef WITNESS
180 if (sx->sx_cnt == 0)
181 sx->sx_object.lo_flags &= ~LO_LOCKED;
182#endif
183 WITNESS_UNLOCK(&sx->sx_object, 0, file, line);
184
141 /* Release. */
142 sx->sx_cnt--;
143
144 /*
145 * If we just released the last shared lock, wake any waiters up, giving
146 * exclusive lockers precedence. In order to make sure that exclusive
147 * lockers won't be blocked forever, don't wake shared lock waiters if
148 * there are exclusive lock waiters.
149 */
150 if (sx->sx_excl_wcnt > 0) {
151 if (sx->sx_cnt == 0)
152 cv_signal(&sx->sx_excl_cv);
153 } else if (sx->sx_shrd_wcnt > 0)
154 cv_broadcast(&sx->sx_shrd_cv);
155
185 /* Release. */
186 sx->sx_cnt--;
187
188 /*
189 * If we just released the last shared lock, wake any waiters up, giving
190 * exclusive lockers precedence. In order to make sure that exclusive
191 * lockers won't be blocked forever, don't wake shared lock waiters if
192 * there are exclusive lock waiters.
193 */
194 if (sx->sx_excl_wcnt > 0) {
195 if (sx->sx_cnt == 0)
196 cv_signal(&sx->sx_excl_cv);
197 } else if (sx->sx_shrd_wcnt > 0)
198 cv_broadcast(&sx->sx_shrd_cv);
199
200 LOCK_LOG_LOCK("SUNLOCK", &sx->sx_object, 0, 0, file, line);
201
156 mtx_unlock(&sx->sx_lock);
157}
158
159void
202 mtx_unlock(&sx->sx_lock);
203}
204
205void
160sx_xunlock(struct sx *sx)
206_sx_xunlock(struct sx *sx, const char *file, int line)
161{
162
163 mtx_lock(&sx->sx_lock);
164 _SX_ASSERT_XLOCKED(sx);
165 MPASS(sx->sx_cnt == -1);
166
207{
208
209 mtx_lock(&sx->sx_lock);
210 _SX_ASSERT_XLOCKED(sx);
211 MPASS(sx->sx_cnt == -1);
212
213#ifdef WITNESS
214 sx->sx_object.lo_flags &= ~LO_LOCKED;
215#endif
216 WITNESS_UNLOCK(&sx->sx_object, 0, file, line);
217
167 /* Release. */
168 sx->sx_cnt++;
169 sx->sx_xholder = NULL;
170
171 /*
172 * Wake up waiters if there are any. Give precedence to slock waiters.
173 */
174 if (sx->sx_shrd_wcnt > 0)
175 cv_broadcast(&sx->sx_shrd_cv);
176 else if (sx->sx_excl_wcnt > 0)
177 cv_signal(&sx->sx_excl_cv);
178
218 /* Release. */
219 sx->sx_cnt++;
220 sx->sx_xholder = NULL;
221
222 /*
223 * Wake up waiters if there are any. Give precedence to slock waiters.
224 */
225 if (sx->sx_shrd_wcnt > 0)
226 cv_broadcast(&sx->sx_shrd_cv);
227 else if (sx->sx_excl_wcnt > 0)
228 cv_signal(&sx->sx_excl_cv);
229
230 LOCK_LOG_LOCK("XUNLOCK", &sx->sx_object, 0, 0, file, line);
231
179 mtx_unlock(&sx->sx_lock);
180}
232 mtx_unlock(&sx->sx_lock);
233}