Deleted Added
full compact
kern_sx.c (161337) kern_sx.c (164159)
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

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

29 * Shared/exclusive locks. This implementation assures deterministic lock
30 * granting behavior, so that slocks and xlocks are interleaved.
31 *
32 * Priority propagation will not generally raise the priority of lock holders,
33 * so should not be relied upon in combination with sx locks.
34 */
35
36#include <sys/cdefs.h>
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

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

29 * Shared/exclusive locks. This implementation assures deterministic lock
30 * granting behavior, so that slocks and xlocks are interleaved.
31 *
32 * Priority propagation will not generally raise the priority of lock holders,
33 * so should not be relied upon in combination with sx locks.
34 */
35
36#include <sys/cdefs.h>
37__FBSDID("$FreeBSD: head/sys/kern/kern_sx.c 161337 2006-08-15 18:29:01Z jhb $");
37__FBSDID("$FreeBSD: head/sys/kern/kern_sx.c 164159 2006-11-11 03:18:07Z kmacy $");
38
39#include "opt_ddb.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/ktr.h>
44#include <sys/linker_set.h>
45#include <sys/condvar.h>
46#include <sys/lock.h>
47#include <sys/mutex.h>
48#include <sys/proc.h>
49#include <sys/sx.h>
38
39#include "opt_ddb.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/ktr.h>
44#include <sys/linker_set.h>
45#include <sys/condvar.h>
46#include <sys/lock.h>
47#include <sys/mutex.h>
48#include <sys/proc.h>
49#include <sys/sx.h>
50#include <sys/lock_profile.h>
50
51#ifdef DDB
52#include <ddb/ddb.h>
53
54static void db_show_sx(struct lock_object *lock);
55#endif
56
57struct lock_class lock_class_sx = {

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

80
81 sx->sx_lock = mtx_pool_find(mtxpool_lockbuilder, sx);
82 sx->sx_cnt = 0;
83 cv_init(&sx->sx_shrd_cv, description);
84 sx->sx_shrd_wcnt = 0;
85 cv_init(&sx->sx_excl_cv, description);
86 sx->sx_excl_wcnt = 0;
87 sx->sx_xholder = NULL;
51
52#ifdef DDB
53#include <ddb/ddb.h>
54
55static void db_show_sx(struct lock_object *lock);
56#endif
57
58struct lock_class lock_class_sx = {

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

81
82 sx->sx_lock = mtx_pool_find(mtxpool_lockbuilder, sx);
83 sx->sx_cnt = 0;
84 cv_init(&sx->sx_shrd_cv, description);
85 sx->sx_shrd_wcnt = 0;
86 cv_init(&sx->sx_excl_cv, description);
87 sx->sx_excl_wcnt = 0;
88 sx->sx_xholder = NULL;
89 lock_profile_object_init(&sx->sx_object, description);
88 lock_init(&sx->sx_object, &lock_class_sx, description, NULL,
89 LO_WITNESS | LO_RECURSABLE | LO_SLEEPABLE | LO_UPGRADABLE);
90}
91
92void
93sx_destroy(struct sx *sx)
94{
95
96 KASSERT((sx->sx_cnt == 0 && sx->sx_shrd_wcnt == 0 && sx->sx_excl_wcnt ==
97 0), ("%s (%s): holders or waiters\n", __func__,
98 sx->sx_object.lo_name));
99
100 sx->sx_lock = NULL;
101 cv_destroy(&sx->sx_shrd_cv);
102 cv_destroy(&sx->sx_excl_cv);
90 lock_init(&sx->sx_object, &lock_class_sx, description, NULL,
91 LO_WITNESS | LO_RECURSABLE | LO_SLEEPABLE | LO_UPGRADABLE);
92}
93
94void
95sx_destroy(struct sx *sx)
96{
97
98 KASSERT((sx->sx_cnt == 0 && sx->sx_shrd_wcnt == 0 && sx->sx_excl_wcnt ==
99 0), ("%s (%s): holders or waiters\n", __func__,
100 sx->sx_object.lo_name));
101
102 sx->sx_lock = NULL;
103 cv_destroy(&sx->sx_shrd_cv);
104 cv_destroy(&sx->sx_excl_cv);
103
105
106 lock_profile_object_destroy(&sx->sx_object);
104 lock_destroy(&sx->sx_object);
105}
106
107void
108_sx_slock(struct sx *sx, const char *file, int line)
109{
107 lock_destroy(&sx->sx_object);
108}
109
110void
111_sx_slock(struct sx *sx, const char *file, int line)
112{
113 uint64_t waittime = 0;
114 int contested;
110
111 mtx_lock(sx->sx_lock);
112 KASSERT(sx->sx_xholder != curthread,
113 ("%s (%s): slock while xlock is held @ %s:%d\n", __func__,
114 sx->sx_object.lo_name, file, line));
115 WITNESS_CHECKORDER(&sx->sx_object, LOP_NEWORDER, file, line);
116
117 /*
118 * Loop in case we lose the race for lock acquisition.
119 */
115
116 mtx_lock(sx->sx_lock);
117 KASSERT(sx->sx_xholder != curthread,
118 ("%s (%s): slock while xlock is held @ %s:%d\n", __func__,
119 sx->sx_object.lo_name, file, line));
120 WITNESS_CHECKORDER(&sx->sx_object, LOP_NEWORDER, file, line);
121
122 /*
123 * Loop in case we lose the race for lock acquisition.
124 */
125 if (sx->sx_cnt < 0)
126 lock_profile_waitstart(&waittime);
120 while (sx->sx_cnt < 0) {
121 sx->sx_shrd_wcnt++;
127 while (sx->sx_cnt < 0) {
128 sx->sx_shrd_wcnt++;
129 lock_profile_obtain_lock_failed(&sx->sx_object, &contested);
122 cv_wait(&sx->sx_shrd_cv, sx->sx_lock);
123 sx->sx_shrd_wcnt--;
124 }
125
126 /* Acquire a shared lock. */
127 sx->sx_cnt++;
128
130 cv_wait(&sx->sx_shrd_cv, sx->sx_lock);
131 sx->sx_shrd_wcnt--;
132 }
133
134 /* Acquire a shared lock. */
135 sx->sx_cnt++;
136
137 if (sx->sx_cnt == 1)
138 lock_profile_obtain_lock_success(&sx->sx_object, waittime, file, line);
139
129 LOCK_LOG_LOCK("SLOCK", &sx->sx_object, 0, 0, file, line);
130 WITNESS_LOCK(&sx->sx_object, 0, file, line);
131 curthread->td_locks++;
132
133 mtx_unlock(sx->sx_lock);
134}
135
136int

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

150 mtx_unlock(sx->sx_lock);
151 return (0);
152 }
153}
154
155void
156_sx_xlock(struct sx *sx, const char *file, int line)
157{
140 LOCK_LOG_LOCK("SLOCK", &sx->sx_object, 0, 0, file, line);
141 WITNESS_LOCK(&sx->sx_object, 0, file, line);
142 curthread->td_locks++;
143
144 mtx_unlock(sx->sx_lock);
145}
146
147int

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

161 mtx_unlock(sx->sx_lock);
162 return (0);
163 }
164}
165
166void
167_sx_xlock(struct sx *sx, const char *file, int line)
168{
169 int contested;
170 uint64_t waittime = 0;
158
159 mtx_lock(sx->sx_lock);
160
161 /*
162 * With sx locks, we're absolutely not permitted to recurse on
163 * xlocks, as it is fatal (deadlock). Normally, recursion is handled
164 * by WITNESS, but as it is not semantically correct to hold the
165 * xlock while in here, we consider it API abuse and put it under
166 * INVARIANTS.
167 */
168 KASSERT(sx->sx_xholder != curthread,
169 ("%s (%s): xlock already held @ %s:%d", __func__,
170 sx->sx_object.lo_name, file, line));
171 WITNESS_CHECKORDER(&sx->sx_object, LOP_NEWORDER | LOP_EXCLUSIVE, file,
172 line);
173
171
172 mtx_lock(sx->sx_lock);
173
174 /*
175 * With sx locks, we're absolutely not permitted to recurse on
176 * xlocks, as it is fatal (deadlock). Normally, recursion is handled
177 * by WITNESS, but as it is not semantically correct to hold the
178 * xlock while in here, we consider it API abuse and put it under
179 * INVARIANTS.
180 */
181 KASSERT(sx->sx_xholder != curthread,
182 ("%s (%s): xlock already held @ %s:%d", __func__,
183 sx->sx_object.lo_name, file, line));
184 WITNESS_CHECKORDER(&sx->sx_object, LOP_NEWORDER | LOP_EXCLUSIVE, file,
185 line);
186
187 if (sx->sx_cnt)
188 lock_profile_waitstart(&waittime);
174 /* Loop in case we lose the race for lock acquisition. */
175 while (sx->sx_cnt != 0) {
176 sx->sx_excl_wcnt++;
189 /* Loop in case we lose the race for lock acquisition. */
190 while (sx->sx_cnt != 0) {
191 sx->sx_excl_wcnt++;
192 lock_profile_obtain_lock_failed(&sx->sx_object, &contested);
177 cv_wait(&sx->sx_excl_cv, sx->sx_lock);
178 sx->sx_excl_wcnt--;
179 }
180
181 MPASS(sx->sx_cnt == 0);
182
183 /* Acquire an exclusive lock. */
184 sx->sx_cnt--;
185 sx->sx_xholder = curthread;
186
193 cv_wait(&sx->sx_excl_cv, sx->sx_lock);
194 sx->sx_excl_wcnt--;
195 }
196
197 MPASS(sx->sx_cnt == 0);
198
199 /* Acquire an exclusive lock. */
200 sx->sx_cnt--;
201 sx->sx_xholder = curthread;
202
203 lock_profile_obtain_lock_success(&sx->sx_object, waittime, file, line);
187 LOCK_LOG_LOCK("XLOCK", &sx->sx_object, 0, 0, file, line);
188 WITNESS_LOCK(&sx->sx_object, LOP_EXCLUSIVE, file, line);
189 curthread->td_locks++;
190
191 mtx_unlock(sx->sx_lock);
192}
193
194int

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

220 mtx_lock(sx->sx_lock);
221
222 curthread->td_locks--;
223 WITNESS_UNLOCK(&sx->sx_object, 0, file, line);
224
225 /* Release. */
226 sx->sx_cnt--;
227
204 LOCK_LOG_LOCK("XLOCK", &sx->sx_object, 0, 0, file, line);
205 WITNESS_LOCK(&sx->sx_object, LOP_EXCLUSIVE, file, line);
206 curthread->td_locks++;
207
208 mtx_unlock(sx->sx_lock);
209}
210
211int

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

237 mtx_lock(sx->sx_lock);
238
239 curthread->td_locks--;
240 WITNESS_UNLOCK(&sx->sx_object, 0, file, line);
241
242 /* Release. */
243 sx->sx_cnt--;
244
245 if (sx->sx_cnt == 0)
246 lock_profile_release_lock(&sx->sx_object);
228 /*
229 * If we just released the last shared lock, wake any waiters up, giving
230 * exclusive lockers precedence. In order to make sure that exclusive
231 * lockers won't be blocked forever, don't wake shared lock waiters if
232 * there are exclusive lock waiters.
233 */
234 if (sx->sx_excl_wcnt > 0) {
235 if (sx->sx_cnt == 0)

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

252
253 curthread->td_locks--;
254 WITNESS_UNLOCK(&sx->sx_object, LOP_EXCLUSIVE, file, line);
255
256 /* Release. */
257 sx->sx_cnt++;
258 sx->sx_xholder = NULL;
259
247 /*
248 * If we just released the last shared lock, wake any waiters up, giving
249 * exclusive lockers precedence. In order to make sure that exclusive
250 * lockers won't be blocked forever, don't wake shared lock waiters if
251 * there are exclusive lock waiters.
252 */
253 if (sx->sx_excl_wcnt > 0) {
254 if (sx->sx_cnt == 0)

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

271
272 curthread->td_locks--;
273 WITNESS_UNLOCK(&sx->sx_object, LOP_EXCLUSIVE, file, line);
274
275 /* Release. */
276 sx->sx_cnt++;
277 sx->sx_xholder = NULL;
278
279 lock_profile_release_lock(&sx->sx_object);
260 /*
261 * Wake up waiters if there are any. Give precedence to slock waiters.
262 */
263 if (sx->sx_shrd_wcnt > 0)
264 cv_broadcast(&sx->sx_shrd_cv);
265 else if (sx->sx_excl_wcnt > 0)
266 cv_signal(&sx->sx_excl_cv);
267

--- 184 unchanged lines hidden ---
280 /*
281 * Wake up waiters if there are any. Give precedence to slock waiters.
282 */
283 if (sx->sx_shrd_wcnt > 0)
284 cv_broadcast(&sx->sx_shrd_cv);
285 else if (sx->sx_excl_wcnt > 0)
286 cv_signal(&sx->sx_excl_cv);
287

--- 184 unchanged lines hidden ---