xref: /freebsd/sys/kern/kern_sx.c (revision 094fc1ed0f2627525c7b0342efcbad5be7a8546a)
1 /*-
2  * Copyright (c) 2007 Attilio Rao <attilio@freebsd.org>
3  * Copyright (c) 2001 Jason Evans <jasone@freebsd.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice(s), this list of conditions and the following disclaimer as
11  *    the first lines of this file unmodified other than the possible
12  *    addition of one or more copyright notices.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice(s), this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
27  * DAMAGE.
28  */
29 
30 /*
31  * Shared/exclusive locks.  This implementation attempts to ensure
32  * deterministic lock granting behavior, so that slocks and xlocks are
33  * interleaved.
34  *
35  * Priority propagation will not generally raise the priority of lock holders,
36  * so should not be relied upon in combination with sx locks.
37  */
38 
39 #include "opt_ddb.h"
40 #include "opt_hwpmc_hooks.h"
41 #include "opt_no_adaptive_sx.h"
42 
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
45 
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/kdb.h>
49 #include <sys/kernel.h>
50 #include <sys/ktr.h>
51 #include <sys/lock.h>
52 #include <sys/mutex.h>
53 #include <sys/proc.h>
54 #include <sys/sched.h>
55 #include <sys/sleepqueue.h>
56 #include <sys/sx.h>
57 #include <sys/smp.h>
58 #include <sys/sysctl.h>
59 
60 #if defined(SMP) && !defined(NO_ADAPTIVE_SX)
61 #include <machine/cpu.h>
62 #endif
63 
64 #ifdef DDB
65 #include <ddb/ddb.h>
66 #endif
67 
68 #if defined(SMP) && !defined(NO_ADAPTIVE_SX)
69 #define	ADAPTIVE_SX
70 #endif
71 
72 CTASSERT((SX_NOADAPTIVE & LO_CLASSFLAGS) == SX_NOADAPTIVE);
73 
74 #ifdef HWPMC_HOOKS
75 #include <sys/pmckern.h>
76 PMC_SOFT_DECLARE( , , lock, failed);
77 #endif
78 
79 /* Handy macros for sleep queues. */
80 #define	SQ_EXCLUSIVE_QUEUE	0
81 #define	SQ_SHARED_QUEUE		1
82 
83 /*
84  * Variations on DROP_GIANT()/PICKUP_GIANT() for use in this file.  We
85  * drop Giant anytime we have to sleep or if we adaptively spin.
86  */
87 #define	GIANT_DECLARE							\
88 	int _giantcnt = 0;						\
89 	WITNESS_SAVE_DECL(Giant)					\
90 
91 #define	GIANT_SAVE() do {						\
92 	if (mtx_owned(&Giant)) {					\
93 		WITNESS_SAVE(&Giant.lock_object, Giant);		\
94 		while (mtx_owned(&Giant)) {				\
95 			_giantcnt++;					\
96 			mtx_unlock(&Giant);				\
97 		}							\
98 	}								\
99 } while (0)
100 
101 #define GIANT_RESTORE() do {						\
102 	if (_giantcnt > 0) {						\
103 		mtx_assert(&Giant, MA_NOTOWNED);			\
104 		while (_giantcnt--)					\
105 			mtx_lock(&Giant);				\
106 		WITNESS_RESTORE(&Giant.lock_object, Giant);		\
107 	}								\
108 } while (0)
109 
110 /*
111  * Returns true if an exclusive lock is recursed.  It assumes
112  * curthread currently has an exclusive lock.
113  */
114 #define	sx_recursed(sx)		((sx)->sx_recurse != 0)
115 
116 static void	assert_sx(const struct lock_object *lock, int what);
117 #ifdef DDB
118 static void	db_show_sx(const struct lock_object *lock);
119 #endif
120 static void	lock_sx(struct lock_object *lock, uintptr_t how);
121 #ifdef KDTRACE_HOOKS
122 static int	owner_sx(const struct lock_object *lock, struct thread **owner);
123 #endif
124 static uintptr_t unlock_sx(struct lock_object *lock);
125 
126 struct lock_class lock_class_sx = {
127 	.lc_name = "sx",
128 	.lc_flags = LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE | LC_UPGRADABLE,
129 	.lc_assert = assert_sx,
130 #ifdef DDB
131 	.lc_ddb_show = db_show_sx,
132 #endif
133 	.lc_lock = lock_sx,
134 	.lc_unlock = unlock_sx,
135 #ifdef KDTRACE_HOOKS
136 	.lc_owner = owner_sx,
137 #endif
138 };
139 
140 #ifndef INVARIANTS
141 #define	_sx_assert(sx, what, file, line)
142 #endif
143 
144 #ifdef ADAPTIVE_SX
145 static __read_frequently u_int asx_retries = 10;
146 static __read_frequently u_int asx_loops = 10000;
147 static SYSCTL_NODE(_debug, OID_AUTO, sx, CTLFLAG_RD, NULL, "sxlock debugging");
148 SYSCTL_UINT(_debug_sx, OID_AUTO, retries, CTLFLAG_RW, &asx_retries, 0, "");
149 SYSCTL_UINT(_debug_sx, OID_AUTO, loops, CTLFLAG_RW, &asx_loops, 0, "");
150 
151 static struct lock_delay_config __read_frequently sx_delay;
152 
153 SYSCTL_INT(_debug_sx, OID_AUTO, delay_base, CTLFLAG_RW, &sx_delay.base,
154     0, "");
155 SYSCTL_INT(_debug_sx, OID_AUTO, delay_max, CTLFLAG_RW, &sx_delay.max,
156     0, "");
157 
158 LOCK_DELAY_SYSINIT_DEFAULT(sx_delay);
159 #endif
160 
161 void
162 assert_sx(const struct lock_object *lock, int what)
163 {
164 
165 	sx_assert((const struct sx *)lock, what);
166 }
167 
168 void
169 lock_sx(struct lock_object *lock, uintptr_t how)
170 {
171 	struct sx *sx;
172 
173 	sx = (struct sx *)lock;
174 	if (how)
175 		sx_slock(sx);
176 	else
177 		sx_xlock(sx);
178 }
179 
180 uintptr_t
181 unlock_sx(struct lock_object *lock)
182 {
183 	struct sx *sx;
184 
185 	sx = (struct sx *)lock;
186 	sx_assert(sx, SA_LOCKED | SA_NOTRECURSED);
187 	if (sx_xlocked(sx)) {
188 		sx_xunlock(sx);
189 		return (0);
190 	} else {
191 		sx_sunlock(sx);
192 		return (1);
193 	}
194 }
195 
196 #ifdef KDTRACE_HOOKS
197 int
198 owner_sx(const struct lock_object *lock, struct thread **owner)
199 {
200 	const struct sx *sx;
201 	uintptr_t x;
202 
203 	sx = (const struct sx *)lock;
204 	x = sx->sx_lock;
205 	*owner = NULL;
206 	return ((x & SX_LOCK_SHARED) != 0 ? (SX_SHARERS(x) != 0) :
207 	    ((*owner = (struct thread *)SX_OWNER(x)) != NULL));
208 }
209 #endif
210 
211 void
212 sx_sysinit(void *arg)
213 {
214 	struct sx_args *sargs = arg;
215 
216 	sx_init_flags(sargs->sa_sx, sargs->sa_desc, sargs->sa_flags);
217 }
218 
219 void
220 sx_init_flags(struct sx *sx, const char *description, int opts)
221 {
222 	int flags;
223 
224 	MPASS((opts & ~(SX_QUIET | SX_RECURSE | SX_NOWITNESS | SX_DUPOK |
225 	    SX_NOPROFILE | SX_NOADAPTIVE | SX_NEW)) == 0);
226 	ASSERT_ATOMIC_LOAD_PTR(sx->sx_lock,
227 	    ("%s: sx_lock not aligned for %s: %p", __func__, description,
228 	    &sx->sx_lock));
229 
230 	flags = LO_SLEEPABLE | LO_UPGRADABLE;
231 	if (opts & SX_DUPOK)
232 		flags |= LO_DUPOK;
233 	if (opts & SX_NOPROFILE)
234 		flags |= LO_NOPROFILE;
235 	if (!(opts & SX_NOWITNESS))
236 		flags |= LO_WITNESS;
237 	if (opts & SX_RECURSE)
238 		flags |= LO_RECURSABLE;
239 	if (opts & SX_QUIET)
240 		flags |= LO_QUIET;
241 	if (opts & SX_NEW)
242 		flags |= LO_NEW;
243 
244 	flags |= opts & SX_NOADAPTIVE;
245 	lock_init(&sx->lock_object, &lock_class_sx, description, NULL, flags);
246 	sx->sx_lock = SX_LOCK_UNLOCKED;
247 	sx->sx_recurse = 0;
248 }
249 
250 void
251 sx_destroy(struct sx *sx)
252 {
253 
254 	KASSERT(sx->sx_lock == SX_LOCK_UNLOCKED, ("sx lock still held"));
255 	KASSERT(sx->sx_recurse == 0, ("sx lock still recursed"));
256 	sx->sx_lock = SX_LOCK_DESTROYED;
257 	lock_destroy(&sx->lock_object);
258 }
259 
260 int
261 sx_try_slock_(struct sx *sx, const char *file, int line)
262 {
263 	uintptr_t x;
264 
265 	if (SCHEDULER_STOPPED())
266 		return (1);
267 
268 	KASSERT(kdb_active != 0 || !TD_IS_IDLETHREAD(curthread),
269 	    ("sx_try_slock() by idle thread %p on sx %s @ %s:%d",
270 	    curthread, sx->lock_object.lo_name, file, line));
271 
272 	x = sx->sx_lock;
273 	for (;;) {
274 		KASSERT(x != SX_LOCK_DESTROYED,
275 		    ("sx_try_slock() of destroyed sx @ %s:%d", file, line));
276 		if (!(x & SX_LOCK_SHARED))
277 			break;
278 		if (atomic_fcmpset_acq_ptr(&sx->sx_lock, &x, x + SX_ONE_SHARER)) {
279 			LOCK_LOG_TRY("SLOCK", &sx->lock_object, 0, 1, file, line);
280 			WITNESS_LOCK(&sx->lock_object, LOP_TRYLOCK, file, line);
281 			LOCKSTAT_PROFILE_OBTAIN_RWLOCK_SUCCESS(sx__acquire,
282 			    sx, 0, 0, file, line, LOCKSTAT_READER);
283 			TD_LOCKS_INC(curthread);
284 			return (1);
285 		}
286 	}
287 
288 	LOCK_LOG_TRY("SLOCK", &sx->lock_object, 0, 0, file, line);
289 	return (0);
290 }
291 
292 int
293 _sx_xlock(struct sx *sx, int opts, const char *file, int line)
294 {
295 	uintptr_t tid, x;
296 	int error = 0;
297 
298 	KASSERT(kdb_active != 0 || SCHEDULER_STOPPED() ||
299 	    !TD_IS_IDLETHREAD(curthread),
300 	    ("sx_xlock() by idle thread %p on sx %s @ %s:%d",
301 	    curthread, sx->lock_object.lo_name, file, line));
302 	KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
303 	    ("sx_xlock() of destroyed sx @ %s:%d", file, line));
304 	WITNESS_CHECKORDER(&sx->lock_object, LOP_NEWORDER | LOP_EXCLUSIVE, file,
305 	    line, NULL);
306 	tid = (uintptr_t)curthread;
307 	x = SX_LOCK_UNLOCKED;
308 	if (!atomic_fcmpset_acq_ptr(&sx->sx_lock, &x, tid))
309 		error = _sx_xlock_hard(sx, x, tid, opts, file, line);
310 	else
311 		LOCKSTAT_PROFILE_OBTAIN_RWLOCK_SUCCESS(sx__acquire, sx,
312 		    0, 0, file, line, LOCKSTAT_WRITER);
313 	if (!error) {
314 		LOCK_LOG_LOCK("XLOCK", &sx->lock_object, 0, sx->sx_recurse,
315 		    file, line);
316 		WITNESS_LOCK(&sx->lock_object, LOP_EXCLUSIVE, file, line);
317 		TD_LOCKS_INC(curthread);
318 	}
319 
320 	return (error);
321 }
322 
323 int
324 sx_try_xlock_(struct sx *sx, const char *file, int line)
325 {
326 	struct thread *td;
327 	uintptr_t tid, x;
328 	int rval;
329 	bool recursed;
330 
331 	td = curthread;
332 	tid = (uintptr_t)td;
333 	if (SCHEDULER_STOPPED_TD(td))
334 		return (1);
335 
336 	KASSERT(kdb_active != 0 || !TD_IS_IDLETHREAD(td),
337 	    ("sx_try_xlock() by idle thread %p on sx %s @ %s:%d",
338 	    curthread, sx->lock_object.lo_name, file, line));
339 	KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
340 	    ("sx_try_xlock() of destroyed sx @ %s:%d", file, line));
341 
342 	rval = 1;
343 	recursed = false;
344 	x = SX_LOCK_UNLOCKED;
345 	for (;;) {
346 		if (atomic_fcmpset_acq_ptr(&sx->sx_lock, &x, tid))
347 			break;
348 		if (x == SX_LOCK_UNLOCKED)
349 			continue;
350 		if (x == tid && (sx->lock_object.lo_flags & LO_RECURSABLE)) {
351 			sx->sx_recurse++;
352 			atomic_set_ptr(&sx->sx_lock, SX_LOCK_RECURSED);
353 			break;
354 		}
355 		rval = 0;
356 		break;
357 	}
358 
359 	LOCK_LOG_TRY("XLOCK", &sx->lock_object, 0, rval, file, line);
360 	if (rval) {
361 		WITNESS_LOCK(&sx->lock_object, LOP_EXCLUSIVE | LOP_TRYLOCK,
362 		    file, line);
363 		if (!recursed)
364 			LOCKSTAT_PROFILE_OBTAIN_RWLOCK_SUCCESS(sx__acquire,
365 			    sx, 0, 0, file, line, LOCKSTAT_WRITER);
366 		TD_LOCKS_INC(curthread);
367 	}
368 
369 	return (rval);
370 }
371 
372 void
373 _sx_xunlock(struct sx *sx, const char *file, int line)
374 {
375 
376 	KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
377 	    ("sx_xunlock() of destroyed sx @ %s:%d", file, line));
378 	_sx_assert(sx, SA_XLOCKED, file, line);
379 	WITNESS_UNLOCK(&sx->lock_object, LOP_EXCLUSIVE, file, line);
380 	LOCK_LOG_LOCK("XUNLOCK", &sx->lock_object, 0, sx->sx_recurse, file,
381 	    line);
382 #if LOCK_DEBUG > 0
383 	_sx_xunlock_hard(sx, (uintptr_t)curthread, file, line);
384 #else
385 	__sx_xunlock(sx, curthread, file, line);
386 #endif
387 	TD_LOCKS_DEC(curthread);
388 }
389 
390 /*
391  * Try to do a non-blocking upgrade from a shared lock to an exclusive lock.
392  * This will only succeed if this thread holds a single shared lock.
393  * Return 1 if if the upgrade succeed, 0 otherwise.
394  */
395 int
396 sx_try_upgrade_(struct sx *sx, const char *file, int line)
397 {
398 	uintptr_t x;
399 	int success;
400 
401 	if (SCHEDULER_STOPPED())
402 		return (1);
403 
404 	KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
405 	    ("sx_try_upgrade() of destroyed sx @ %s:%d", file, line));
406 	_sx_assert(sx, SA_SLOCKED, file, line);
407 
408 	/*
409 	 * Try to switch from one shared lock to an exclusive lock.  We need
410 	 * to maintain the SX_LOCK_EXCLUSIVE_WAITERS flag if set so that
411 	 * we will wake up the exclusive waiters when we drop the lock.
412 	 */
413 	x = sx->sx_lock & SX_LOCK_EXCLUSIVE_WAITERS;
414 	success = atomic_cmpset_acq_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1) | x,
415 	    (uintptr_t)curthread | x);
416 	LOCK_LOG_TRY("XUPGRADE", &sx->lock_object, 0, success, file, line);
417 	if (success) {
418 		WITNESS_UPGRADE(&sx->lock_object, LOP_EXCLUSIVE | LOP_TRYLOCK,
419 		    file, line);
420 		LOCKSTAT_RECORD0(sx__upgrade, sx);
421 	}
422 	return (success);
423 }
424 
425 /*
426  * Downgrade an unrecursed exclusive lock into a single shared lock.
427  */
428 void
429 sx_downgrade_(struct sx *sx, const char *file, int line)
430 {
431 	uintptr_t x;
432 	int wakeup_swapper;
433 
434 	if (SCHEDULER_STOPPED())
435 		return;
436 
437 	KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
438 	    ("sx_downgrade() of destroyed sx @ %s:%d", file, line));
439 	_sx_assert(sx, SA_XLOCKED | SA_NOTRECURSED, file, line);
440 #ifndef INVARIANTS
441 	if (sx_recursed(sx))
442 		panic("downgrade of a recursed lock");
443 #endif
444 
445 	WITNESS_DOWNGRADE(&sx->lock_object, 0, file, line);
446 
447 	/*
448 	 * Try to switch from an exclusive lock with no shared waiters
449 	 * to one sharer with no shared waiters.  If there are
450 	 * exclusive waiters, we don't need to lock the sleep queue so
451 	 * long as we preserve the flag.  We do one quick try and if
452 	 * that fails we grab the sleepq lock to keep the flags from
453 	 * changing and do it the slow way.
454 	 *
455 	 * We have to lock the sleep queue if there are shared waiters
456 	 * so we can wake them up.
457 	 */
458 	x = sx->sx_lock;
459 	if (!(x & SX_LOCK_SHARED_WAITERS) &&
460 	    atomic_cmpset_rel_ptr(&sx->sx_lock, x, SX_SHARERS_LOCK(1) |
461 	    (x & SX_LOCK_EXCLUSIVE_WAITERS))) {
462 		LOCK_LOG_LOCK("XDOWNGRADE", &sx->lock_object, 0, 0, file, line);
463 		return;
464 	}
465 
466 	/*
467 	 * Lock the sleep queue so we can read the waiters bits
468 	 * without any races and wakeup any shared waiters.
469 	 */
470 	sleepq_lock(&sx->lock_object);
471 
472 	/*
473 	 * Preserve SX_LOCK_EXCLUSIVE_WAITERS while downgraded to a single
474 	 * shared lock.  If there are any shared waiters, wake them up.
475 	 */
476 	wakeup_swapper = 0;
477 	x = sx->sx_lock;
478 	atomic_store_rel_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1) |
479 	    (x & SX_LOCK_EXCLUSIVE_WAITERS));
480 	if (x & SX_LOCK_SHARED_WAITERS)
481 		wakeup_swapper = sleepq_broadcast(&sx->lock_object, SLEEPQ_SX,
482 		    0, SQ_SHARED_QUEUE);
483 	sleepq_release(&sx->lock_object);
484 
485 	LOCK_LOG_LOCK("XDOWNGRADE", &sx->lock_object, 0, 0, file, line);
486 	LOCKSTAT_RECORD0(sx__downgrade, sx);
487 
488 	if (wakeup_swapper)
489 		kick_proc0();
490 }
491 
492 /*
493  * This function represents the so-called 'hard case' for sx_xlock
494  * operation.  All 'easy case' failures are redirected to this.  Note
495  * that ideally this would be a static function, but it needs to be
496  * accessible from at least sx.h.
497  */
498 int
499 _sx_xlock_hard(struct sx *sx, uintptr_t x, uintptr_t tid, int opts,
500     const char *file, int line)
501 {
502 	GIANT_DECLARE;
503 #ifdef ADAPTIVE_SX
504 	volatile struct thread *owner;
505 	u_int i, n, spintries = 0;
506 #endif
507 #ifdef LOCK_PROFILING
508 	uint64_t waittime = 0;
509 	int contested = 0;
510 #endif
511 	int error = 0;
512 #if defined(ADAPTIVE_SX) || defined(KDTRACE_HOOKS)
513 	struct lock_delay_arg lda;
514 #endif
515 #ifdef	KDTRACE_HOOKS
516 	uintptr_t state;
517 	u_int sleep_cnt = 0;
518 	int64_t sleep_time = 0;
519 	int64_t all_time = 0;
520 #endif
521 
522 	if (SCHEDULER_STOPPED())
523 		return (0);
524 
525 #if defined(ADAPTIVE_SX)
526 	lock_delay_arg_init(&lda, &sx_delay);
527 #elif defined(KDTRACE_HOOKS)
528 	lock_delay_arg_init(&lda, NULL);
529 #endif
530 
531 	if (__predict_false(x == SX_LOCK_UNLOCKED))
532 		x = SX_READ_VALUE(sx);
533 
534 	/* If we already hold an exclusive lock, then recurse. */
535 	if (__predict_false(lv_sx_owner(x) == (struct thread *)tid)) {
536 		KASSERT((sx->lock_object.lo_flags & LO_RECURSABLE) != 0,
537 	    ("_sx_xlock_hard: recursed on non-recursive sx %s @ %s:%d\n",
538 		    sx->lock_object.lo_name, file, line));
539 		sx->sx_recurse++;
540 		atomic_set_ptr(&sx->sx_lock, SX_LOCK_RECURSED);
541 		if (LOCK_LOG_TEST(&sx->lock_object, 0))
542 			CTR2(KTR_LOCK, "%s: %p recursing", __func__, sx);
543 		return (0);
544 	}
545 
546 	if (LOCK_LOG_TEST(&sx->lock_object, 0))
547 		CTR5(KTR_LOCK, "%s: %s contested (lock=%p) at %s:%d", __func__,
548 		    sx->lock_object.lo_name, (void *)sx->sx_lock, file, line);
549 
550 #ifdef KDTRACE_HOOKS
551 	all_time -= lockstat_nsecs(&sx->lock_object);
552 	state = x;
553 #endif
554 	for (;;) {
555 		if (x == SX_LOCK_UNLOCKED) {
556 			if (atomic_fcmpset_acq_ptr(&sx->sx_lock, &x, tid))
557 				break;
558 			continue;
559 		}
560 #ifdef KDTRACE_HOOKS
561 		lda.spin_cnt++;
562 #endif
563 #ifdef HWPMC_HOOKS
564 		PMC_SOFT_CALL( , , lock, failed);
565 #endif
566 		lock_profile_obtain_lock_failed(&sx->lock_object, &contested,
567 		    &waittime);
568 #ifdef ADAPTIVE_SX
569 		/*
570 		 * If the lock is write locked and the owner is
571 		 * running on another CPU, spin until the owner stops
572 		 * running or the state of the lock changes.
573 		 */
574 		if ((sx->lock_object.lo_flags & SX_NOADAPTIVE) == 0) {
575 			if ((x & SX_LOCK_SHARED) == 0) {
576 				owner = lv_sx_owner(x);
577 				if (TD_IS_RUNNING(owner)) {
578 					if (LOCK_LOG_TEST(&sx->lock_object, 0))
579 						CTR3(KTR_LOCK,
580 					    "%s: spinning on %p held by %p",
581 						    __func__, sx, owner);
582 					KTR_STATE1(KTR_SCHED, "thread",
583 					    sched_tdname(curthread), "spinning",
584 					    "lockname:\"%s\"",
585 					    sx->lock_object.lo_name);
586 					GIANT_SAVE();
587 					do {
588 						lock_delay(&lda);
589 						x = SX_READ_VALUE(sx);
590 						owner = lv_sx_owner(x);
591 					} while (owner != NULL &&
592 						    TD_IS_RUNNING(owner));
593 					KTR_STATE0(KTR_SCHED, "thread",
594 					    sched_tdname(curthread), "running");
595 					continue;
596 				}
597 			} else if (SX_SHARERS(x) && spintries < asx_retries) {
598 				KTR_STATE1(KTR_SCHED, "thread",
599 				    sched_tdname(curthread), "spinning",
600 				    "lockname:\"%s\"", sx->lock_object.lo_name);
601 				GIANT_SAVE();
602 				spintries++;
603 				for (i = 0; i < asx_loops; i += n) {
604 					if (LOCK_LOG_TEST(&sx->lock_object, 0))
605 						CTR4(KTR_LOCK,
606 				    "%s: shared spinning on %p with %u and %u",
607 						    __func__, sx, spintries, i);
608 					n = SX_SHARERS(x);
609 					lock_delay_spin(n);
610 					x = SX_READ_VALUE(sx);
611 					if ((x & SX_LOCK_SHARED) == 0 ||
612 					    SX_SHARERS(x) == 0)
613 						break;
614 				}
615 #ifdef KDTRACE_HOOKS
616 				lda.spin_cnt += i;
617 #endif
618 				KTR_STATE0(KTR_SCHED, "thread",
619 				    sched_tdname(curthread), "running");
620 				if (i != asx_loops)
621 					continue;
622 			}
623 		}
624 #endif
625 
626 		sleepq_lock(&sx->lock_object);
627 		x = SX_READ_VALUE(sx);
628 
629 		/*
630 		 * If the lock was released while spinning on the
631 		 * sleep queue chain lock, try again.
632 		 */
633 		if (x == SX_LOCK_UNLOCKED) {
634 			sleepq_release(&sx->lock_object);
635 			continue;
636 		}
637 
638 #ifdef ADAPTIVE_SX
639 		/*
640 		 * The current lock owner might have started executing
641 		 * on another CPU (or the lock could have changed
642 		 * owners) while we were waiting on the sleep queue
643 		 * chain lock.  If so, drop the sleep queue lock and try
644 		 * again.
645 		 */
646 		if (!(x & SX_LOCK_SHARED) &&
647 		    (sx->lock_object.lo_flags & SX_NOADAPTIVE) == 0) {
648 			owner = (struct thread *)SX_OWNER(x);
649 			if (TD_IS_RUNNING(owner)) {
650 				sleepq_release(&sx->lock_object);
651 				continue;
652 			}
653 		}
654 #endif
655 
656 		/*
657 		 * If an exclusive lock was released with both shared
658 		 * and exclusive waiters and a shared waiter hasn't
659 		 * woken up and acquired the lock yet, sx_lock will be
660 		 * set to SX_LOCK_UNLOCKED | SX_LOCK_EXCLUSIVE_WAITERS.
661 		 * If we see that value, try to acquire it once.  Note
662 		 * that we have to preserve SX_LOCK_EXCLUSIVE_WAITERS
663 		 * as there are other exclusive waiters still.  If we
664 		 * fail, restart the loop.
665 		 */
666 		if (x == (SX_LOCK_UNLOCKED | SX_LOCK_EXCLUSIVE_WAITERS)) {
667 			if (atomic_cmpset_acq_ptr(&sx->sx_lock,
668 			    SX_LOCK_UNLOCKED | SX_LOCK_EXCLUSIVE_WAITERS,
669 			    tid | SX_LOCK_EXCLUSIVE_WAITERS)) {
670 				sleepq_release(&sx->lock_object);
671 				CTR2(KTR_LOCK, "%s: %p claimed by new writer",
672 				    __func__, sx);
673 				break;
674 			}
675 			sleepq_release(&sx->lock_object);
676 			x = SX_READ_VALUE(sx);
677 			continue;
678 		}
679 
680 		/*
681 		 * Try to set the SX_LOCK_EXCLUSIVE_WAITERS.  If we fail,
682 		 * than loop back and retry.
683 		 */
684 		if (!(x & SX_LOCK_EXCLUSIVE_WAITERS)) {
685 			if (!atomic_cmpset_ptr(&sx->sx_lock, x,
686 			    x | SX_LOCK_EXCLUSIVE_WAITERS)) {
687 				sleepq_release(&sx->lock_object);
688 				x = SX_READ_VALUE(sx);
689 				continue;
690 			}
691 			if (LOCK_LOG_TEST(&sx->lock_object, 0))
692 				CTR2(KTR_LOCK, "%s: %p set excl waiters flag",
693 				    __func__, sx);
694 		}
695 
696 		/*
697 		 * Since we have been unable to acquire the exclusive
698 		 * lock and the exclusive waiters flag is set, we have
699 		 * to sleep.
700 		 */
701 		if (LOCK_LOG_TEST(&sx->lock_object, 0))
702 			CTR2(KTR_LOCK, "%s: %p blocking on sleep queue",
703 			    __func__, sx);
704 
705 #ifdef KDTRACE_HOOKS
706 		sleep_time -= lockstat_nsecs(&sx->lock_object);
707 #endif
708 		GIANT_SAVE();
709 		sleepq_add(&sx->lock_object, NULL, sx->lock_object.lo_name,
710 		    SLEEPQ_SX | ((opts & SX_INTERRUPTIBLE) ?
711 		    SLEEPQ_INTERRUPTIBLE : 0), SQ_EXCLUSIVE_QUEUE);
712 		if (!(opts & SX_INTERRUPTIBLE))
713 			sleepq_wait(&sx->lock_object, 0);
714 		else
715 			error = sleepq_wait_sig(&sx->lock_object, 0);
716 #ifdef KDTRACE_HOOKS
717 		sleep_time += lockstat_nsecs(&sx->lock_object);
718 		sleep_cnt++;
719 #endif
720 		if (error) {
721 			if (LOCK_LOG_TEST(&sx->lock_object, 0))
722 				CTR2(KTR_LOCK,
723 			"%s: interruptible sleep by %p suspended by signal",
724 				    __func__, sx);
725 			break;
726 		}
727 		if (LOCK_LOG_TEST(&sx->lock_object, 0))
728 			CTR2(KTR_LOCK, "%s: %p resuming from sleep queue",
729 			    __func__, sx);
730 		x = SX_READ_VALUE(sx);
731 	}
732 #ifdef KDTRACE_HOOKS
733 	all_time += lockstat_nsecs(&sx->lock_object);
734 	if (sleep_time)
735 		LOCKSTAT_RECORD4(sx__block, sx, sleep_time,
736 		    LOCKSTAT_WRITER, (state & SX_LOCK_SHARED) == 0,
737 		    (state & SX_LOCK_SHARED) == 0 ? 0 : SX_SHARERS(state));
738 	if (lda.spin_cnt > sleep_cnt)
739 		LOCKSTAT_RECORD4(sx__spin, sx, all_time - sleep_time,
740 		    LOCKSTAT_WRITER, (state & SX_LOCK_SHARED) == 0,
741 		    (state & SX_LOCK_SHARED) == 0 ? 0 : SX_SHARERS(state));
742 #endif
743 	if (!error)
744 		LOCKSTAT_PROFILE_OBTAIN_RWLOCK_SUCCESS(sx__acquire, sx,
745 		    contested, waittime, file, line, LOCKSTAT_WRITER);
746 	GIANT_RESTORE();
747 	return (error);
748 }
749 
750 /*
751  * This function represents the so-called 'hard case' for sx_xunlock
752  * operation.  All 'easy case' failures are redirected to this.  Note
753  * that ideally this would be a static function, but it needs to be
754  * accessible from at least sx.h.
755  */
756 void
757 _sx_xunlock_hard(struct sx *sx, uintptr_t tid, const char *file, int line)
758 {
759 	uintptr_t x;
760 	int queue, wakeup_swapper;
761 
762 	if (SCHEDULER_STOPPED())
763 		return;
764 
765 	MPASS(!(sx->sx_lock & SX_LOCK_SHARED));
766 
767 	x = SX_READ_VALUE(sx);
768 	if (x & SX_LOCK_RECURSED) {
769 		/* The lock is recursed, unrecurse one level. */
770 		if ((--sx->sx_recurse) == 0)
771 			atomic_clear_ptr(&sx->sx_lock, SX_LOCK_RECURSED);
772 		if (LOCK_LOG_TEST(&sx->lock_object, 0))
773 			CTR2(KTR_LOCK, "%s: %p unrecursing", __func__, sx);
774 		return;
775 	}
776 
777 	LOCKSTAT_PROFILE_RELEASE_RWLOCK(sx__release, sx, LOCKSTAT_WRITER);
778 	if (x == tid &&
779 	    atomic_cmpset_rel_ptr(&sx->sx_lock, tid, SX_LOCK_UNLOCKED))
780 		return;
781 
782 	MPASS(sx->sx_lock & (SX_LOCK_SHARED_WAITERS |
783 	    SX_LOCK_EXCLUSIVE_WAITERS));
784 	if (LOCK_LOG_TEST(&sx->lock_object, 0))
785 		CTR2(KTR_LOCK, "%s: %p contested", __func__, sx);
786 
787 	sleepq_lock(&sx->lock_object);
788 	x = SX_LOCK_UNLOCKED;
789 
790 	/*
791 	 * The wake up algorithm here is quite simple and probably not
792 	 * ideal.  It gives precedence to shared waiters if they are
793 	 * present.  For this condition, we have to preserve the
794 	 * state of the exclusive waiters flag.
795 	 * If interruptible sleeps left the shared queue empty avoid a
796 	 * starvation for the threads sleeping on the exclusive queue by giving
797 	 * them precedence and cleaning up the shared waiters bit anyway.
798 	 */
799 	if ((sx->sx_lock & SX_LOCK_SHARED_WAITERS) != 0 &&
800 	    sleepq_sleepcnt(&sx->lock_object, SQ_SHARED_QUEUE) != 0) {
801 		queue = SQ_SHARED_QUEUE;
802 		x |= (sx->sx_lock & SX_LOCK_EXCLUSIVE_WAITERS);
803 	} else
804 		queue = SQ_EXCLUSIVE_QUEUE;
805 
806 	/* Wake up all the waiters for the specific queue. */
807 	if (LOCK_LOG_TEST(&sx->lock_object, 0))
808 		CTR3(KTR_LOCK, "%s: %p waking up all threads on %s queue",
809 		    __func__, sx, queue == SQ_SHARED_QUEUE ? "shared" :
810 		    "exclusive");
811 	atomic_store_rel_ptr(&sx->sx_lock, x);
812 	wakeup_swapper = sleepq_broadcast(&sx->lock_object, SLEEPQ_SX, 0,
813 	    queue);
814 	sleepq_release(&sx->lock_object);
815 	if (wakeup_swapper)
816 		kick_proc0();
817 }
818 
819 static bool __always_inline
820 __sx_slock_try(struct sx *sx, uintptr_t *xp, const char *file, int line)
821 {
822 
823 	/*
824 	 * If no other thread has an exclusive lock then try to bump up
825 	 * the count of sharers.  Since we have to preserve the state
826 	 * of SX_LOCK_EXCLUSIVE_WAITERS, if we fail to acquire the
827 	 * shared lock loop back and retry.
828 	 */
829 	while (*xp & SX_LOCK_SHARED) {
830 		MPASS(!(*xp & SX_LOCK_SHARED_WAITERS));
831 		if (atomic_fcmpset_acq_ptr(&sx->sx_lock, xp,
832 		    *xp + SX_ONE_SHARER)) {
833 			if (LOCK_LOG_TEST(&sx->lock_object, 0))
834 				CTR4(KTR_LOCK, "%s: %p succeed %p -> %p",
835 				    __func__, sx, (void *)*xp,
836 				    (void *)(*xp + SX_ONE_SHARER));
837 			return (true);
838 		}
839 	}
840 	return (false);
841 }
842 
843 static int __noinline
844 _sx_slock_hard(struct sx *sx, int opts, const char *file, int line, uintptr_t x)
845 {
846 	GIANT_DECLARE;
847 #ifdef ADAPTIVE_SX
848 	volatile struct thread *owner;
849 #endif
850 #ifdef LOCK_PROFILING
851 	uint64_t waittime = 0;
852 	int contested = 0;
853 #endif
854 	int error = 0;
855 #if defined(ADAPTIVE_SX) || defined(KDTRACE_HOOKS)
856 	struct lock_delay_arg lda;
857 #endif
858 #ifdef KDTRACE_HOOKS
859 	uintptr_t state;
860 	u_int sleep_cnt = 0;
861 	int64_t sleep_time = 0;
862 	int64_t all_time = 0;
863 #endif
864 
865 	if (SCHEDULER_STOPPED())
866 		return (0);
867 
868 #if defined(ADAPTIVE_SX)
869 	lock_delay_arg_init(&lda, &sx_delay);
870 #elif defined(KDTRACE_HOOKS)
871 	lock_delay_arg_init(&lda, NULL);
872 #endif
873 #ifdef KDTRACE_HOOKS
874 	all_time -= lockstat_nsecs(&sx->lock_object);
875 	state = x;
876 #endif
877 
878 	/*
879 	 * As with rwlocks, we don't make any attempt to try to block
880 	 * shared locks once there is an exclusive waiter.
881 	 */
882 	for (;;) {
883 		if (__sx_slock_try(sx, &x, file, line))
884 			break;
885 #ifdef KDTRACE_HOOKS
886 		lda.spin_cnt++;
887 #endif
888 
889 #ifdef HWPMC_HOOKS
890 		PMC_SOFT_CALL( , , lock, failed);
891 #endif
892 		lock_profile_obtain_lock_failed(&sx->lock_object, &contested,
893 		    &waittime);
894 
895 #ifdef ADAPTIVE_SX
896 		/*
897 		 * If the owner is running on another CPU, spin until
898 		 * the owner stops running or the state of the lock
899 		 * changes.
900 		 */
901 		if ((sx->lock_object.lo_flags & SX_NOADAPTIVE) == 0) {
902 			owner = lv_sx_owner(x);
903 			if (TD_IS_RUNNING(owner)) {
904 				if (LOCK_LOG_TEST(&sx->lock_object, 0))
905 					CTR3(KTR_LOCK,
906 					    "%s: spinning on %p held by %p",
907 					    __func__, sx, owner);
908 				KTR_STATE1(KTR_SCHED, "thread",
909 				    sched_tdname(curthread), "spinning",
910 				    "lockname:\"%s\"", sx->lock_object.lo_name);
911 				GIANT_SAVE();
912 				do {
913 					lock_delay(&lda);
914 					x = SX_READ_VALUE(sx);
915 					owner = lv_sx_owner(x);
916 				} while (owner != NULL && TD_IS_RUNNING(owner));
917 				KTR_STATE0(KTR_SCHED, "thread",
918 				    sched_tdname(curthread), "running");
919 				continue;
920 			}
921 		}
922 #endif
923 
924 		/*
925 		 * Some other thread already has an exclusive lock, so
926 		 * start the process of blocking.
927 		 */
928 		sleepq_lock(&sx->lock_object);
929 		x = SX_READ_VALUE(sx);
930 
931 		/*
932 		 * The lock could have been released while we spun.
933 		 * In this case loop back and retry.
934 		 */
935 		if (x & SX_LOCK_SHARED) {
936 			sleepq_release(&sx->lock_object);
937 			continue;
938 		}
939 
940 #ifdef ADAPTIVE_SX
941 		/*
942 		 * If the owner is running on another CPU, spin until
943 		 * the owner stops running or the state of the lock
944 		 * changes.
945 		 */
946 		if (!(x & SX_LOCK_SHARED) &&
947 		    (sx->lock_object.lo_flags & SX_NOADAPTIVE) == 0) {
948 			owner = (struct thread *)SX_OWNER(x);
949 			if (TD_IS_RUNNING(owner)) {
950 				sleepq_release(&sx->lock_object);
951 				x = SX_READ_VALUE(sx);
952 				continue;
953 			}
954 		}
955 #endif
956 
957 		/*
958 		 * Try to set the SX_LOCK_SHARED_WAITERS flag.  If we
959 		 * fail to set it drop the sleep queue lock and loop
960 		 * back.
961 		 */
962 		if (!(x & SX_LOCK_SHARED_WAITERS)) {
963 			if (!atomic_cmpset_ptr(&sx->sx_lock, x,
964 			    x | SX_LOCK_SHARED_WAITERS)) {
965 				sleepq_release(&sx->lock_object);
966 				x = SX_READ_VALUE(sx);
967 				continue;
968 			}
969 			if (LOCK_LOG_TEST(&sx->lock_object, 0))
970 				CTR2(KTR_LOCK, "%s: %p set shared waiters flag",
971 				    __func__, sx);
972 		}
973 
974 		/*
975 		 * Since we have been unable to acquire the shared lock,
976 		 * we have to sleep.
977 		 */
978 		if (LOCK_LOG_TEST(&sx->lock_object, 0))
979 			CTR2(KTR_LOCK, "%s: %p blocking on sleep queue",
980 			    __func__, sx);
981 
982 #ifdef KDTRACE_HOOKS
983 		sleep_time -= lockstat_nsecs(&sx->lock_object);
984 #endif
985 		GIANT_SAVE();
986 		sleepq_add(&sx->lock_object, NULL, sx->lock_object.lo_name,
987 		    SLEEPQ_SX | ((opts & SX_INTERRUPTIBLE) ?
988 		    SLEEPQ_INTERRUPTIBLE : 0), SQ_SHARED_QUEUE);
989 		if (!(opts & SX_INTERRUPTIBLE))
990 			sleepq_wait(&sx->lock_object, 0);
991 		else
992 			error = sleepq_wait_sig(&sx->lock_object, 0);
993 #ifdef KDTRACE_HOOKS
994 		sleep_time += lockstat_nsecs(&sx->lock_object);
995 		sleep_cnt++;
996 #endif
997 		if (error) {
998 			if (LOCK_LOG_TEST(&sx->lock_object, 0))
999 				CTR2(KTR_LOCK,
1000 			"%s: interruptible sleep by %p suspended by signal",
1001 				    __func__, sx);
1002 			break;
1003 		}
1004 		if (LOCK_LOG_TEST(&sx->lock_object, 0))
1005 			CTR2(KTR_LOCK, "%s: %p resuming from sleep queue",
1006 			    __func__, sx);
1007 		x = SX_READ_VALUE(sx);
1008 	}
1009 #ifdef KDTRACE_HOOKS
1010 	all_time += lockstat_nsecs(&sx->lock_object);
1011 	if (sleep_time)
1012 		LOCKSTAT_RECORD4(sx__block, sx, sleep_time,
1013 		    LOCKSTAT_READER, (state & SX_LOCK_SHARED) == 0,
1014 		    (state & SX_LOCK_SHARED) == 0 ? 0 : SX_SHARERS(state));
1015 	if (lda.spin_cnt > sleep_cnt)
1016 		LOCKSTAT_RECORD4(sx__spin, sx, all_time - sleep_time,
1017 		    LOCKSTAT_READER, (state & SX_LOCK_SHARED) == 0,
1018 		    (state & SX_LOCK_SHARED) == 0 ? 0 : SX_SHARERS(state));
1019 #endif
1020 	if (error == 0) {
1021 		LOCKSTAT_PROFILE_OBTAIN_RWLOCK_SUCCESS(sx__acquire, sx,
1022 		    contested, waittime, file, line, LOCKSTAT_READER);
1023 	}
1024 	GIANT_RESTORE();
1025 	return (error);
1026 }
1027 
1028 int
1029 _sx_slock(struct sx *sx, int opts, const char *file, int line)
1030 {
1031 	uintptr_t x;
1032 	int error;
1033 
1034 	KASSERT(kdb_active != 0 || SCHEDULER_STOPPED() ||
1035 	    !TD_IS_IDLETHREAD(curthread),
1036 	    ("sx_slock() by idle thread %p on sx %s @ %s:%d",
1037 	    curthread, sx->lock_object.lo_name, file, line));
1038 	KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
1039 	    ("sx_slock() of destroyed sx @ %s:%d", file, line));
1040 	WITNESS_CHECKORDER(&sx->lock_object, LOP_NEWORDER, file, line, NULL);
1041 
1042 	error = 0;
1043 	x = SX_READ_VALUE(sx);
1044 	if (__predict_false(LOCKSTAT_OOL_PROFILE_ENABLED(sx__acquire) ||
1045 	    !__sx_slock_try(sx, &x, file, line)))
1046 		error = _sx_slock_hard(sx, opts, file, line, x);
1047 	if (error == 0) {
1048 		LOCK_LOG_LOCK("SLOCK", &sx->lock_object, 0, 0, file, line);
1049 		WITNESS_LOCK(&sx->lock_object, 0, file, line);
1050 		TD_LOCKS_INC(curthread);
1051 	}
1052 	return (error);
1053 }
1054 
1055 static bool __always_inline
1056 _sx_sunlock_try(struct sx *sx, uintptr_t *xp)
1057 {
1058 
1059 	for (;;) {
1060 		/*
1061 		 * We should never have sharers while at least one thread
1062 		 * holds a shared lock.
1063 		 */
1064 		KASSERT(!(*xp & SX_LOCK_SHARED_WAITERS),
1065 		    ("%s: waiting sharers", __func__));
1066 
1067 		/*
1068 		 * See if there is more than one shared lock held.  If
1069 		 * so, just drop one and return.
1070 		 */
1071 		if (SX_SHARERS(*xp) > 1) {
1072 			if (atomic_fcmpset_rel_ptr(&sx->sx_lock, xp,
1073 			    *xp - SX_ONE_SHARER)) {
1074 				if (LOCK_LOG_TEST(&sx->lock_object, 0))
1075 					CTR4(KTR_LOCK,
1076 					    "%s: %p succeeded %p -> %p",
1077 					    __func__, sx, (void *)*xp,
1078 					    (void *)(*xp - SX_ONE_SHARER));
1079 				return (true);
1080 			}
1081 			continue;
1082 		}
1083 
1084 		/*
1085 		 * If there aren't any waiters for an exclusive lock,
1086 		 * then try to drop it quickly.
1087 		 */
1088 		if (!(*xp & SX_LOCK_EXCLUSIVE_WAITERS)) {
1089 			MPASS(*xp == SX_SHARERS_LOCK(1));
1090 			*xp = SX_SHARERS_LOCK(1);
1091 			if (atomic_fcmpset_rel_ptr(&sx->sx_lock,
1092 			    xp, SX_LOCK_UNLOCKED)) {
1093 				if (LOCK_LOG_TEST(&sx->lock_object, 0))
1094 					CTR2(KTR_LOCK, "%s: %p last succeeded",
1095 					    __func__, sx);
1096 				return (true);
1097 			}
1098 			continue;
1099 		}
1100 		break;
1101 	}
1102 	return (false);
1103 }
1104 
1105 static void __noinline
1106 _sx_sunlock_hard(struct sx *sx, uintptr_t x, const char *file, int line)
1107 {
1108 	int wakeup_swapper;
1109 
1110 	if (SCHEDULER_STOPPED())
1111 		return;
1112 
1113 	LOCKSTAT_PROFILE_RELEASE_RWLOCK(sx__release, sx, LOCKSTAT_READER);
1114 
1115 	for (;;) {
1116 		if (_sx_sunlock_try(sx, &x))
1117 			break;
1118 
1119 		/*
1120 		 * At this point, there should just be one sharer with
1121 		 * exclusive waiters.
1122 		 */
1123 		MPASS(x == (SX_SHARERS_LOCK(1) | SX_LOCK_EXCLUSIVE_WAITERS));
1124 
1125 		sleepq_lock(&sx->lock_object);
1126 
1127 		/*
1128 		 * Wake up semantic here is quite simple:
1129 		 * Just wake up all the exclusive waiters.
1130 		 * Note that the state of the lock could have changed,
1131 		 * so if it fails loop back and retry.
1132 		 */
1133 		if (!atomic_cmpset_rel_ptr(&sx->sx_lock,
1134 		    SX_SHARERS_LOCK(1) | SX_LOCK_EXCLUSIVE_WAITERS,
1135 		    SX_LOCK_UNLOCKED)) {
1136 			sleepq_release(&sx->lock_object);
1137 			x = SX_READ_VALUE(sx);
1138 			continue;
1139 		}
1140 		if (LOCK_LOG_TEST(&sx->lock_object, 0))
1141 			CTR2(KTR_LOCK, "%s: %p waking up all thread on"
1142 			    "exclusive queue", __func__, sx);
1143 		wakeup_swapper = sleepq_broadcast(&sx->lock_object, SLEEPQ_SX,
1144 		    0, SQ_EXCLUSIVE_QUEUE);
1145 		sleepq_release(&sx->lock_object);
1146 		if (wakeup_swapper)
1147 			kick_proc0();
1148 		break;
1149 	}
1150 }
1151 
1152 void
1153 _sx_sunlock(struct sx *sx, const char *file, int line)
1154 {
1155 	uintptr_t x;
1156 
1157 	KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
1158 	    ("sx_sunlock() of destroyed sx @ %s:%d", file, line));
1159 	_sx_assert(sx, SA_SLOCKED, file, line);
1160 	WITNESS_UNLOCK(&sx->lock_object, 0, file, line);
1161 	LOCK_LOG_LOCK("SUNLOCK", &sx->lock_object, 0, 0, file, line);
1162 
1163 	x = SX_READ_VALUE(sx);
1164 	if (__predict_false(LOCKSTAT_OOL_PROFILE_ENABLED(sx__release) ||
1165 	    !_sx_sunlock_try(sx, &x)))
1166 		_sx_sunlock_hard(sx, x, file, line);
1167 
1168 	TD_LOCKS_DEC(curthread);
1169 }
1170 
1171 #ifdef INVARIANT_SUPPORT
1172 #ifndef INVARIANTS
1173 #undef	_sx_assert
1174 #endif
1175 
1176 /*
1177  * In the non-WITNESS case, sx_assert() can only detect that at least
1178  * *some* thread owns an slock, but it cannot guarantee that *this*
1179  * thread owns an slock.
1180  */
1181 void
1182 _sx_assert(const struct sx *sx, int what, const char *file, int line)
1183 {
1184 #ifndef WITNESS
1185 	int slocked = 0;
1186 #endif
1187 
1188 	if (panicstr != NULL)
1189 		return;
1190 	switch (what) {
1191 	case SA_SLOCKED:
1192 	case SA_SLOCKED | SA_NOTRECURSED:
1193 	case SA_SLOCKED | SA_RECURSED:
1194 #ifndef WITNESS
1195 		slocked = 1;
1196 		/* FALLTHROUGH */
1197 #endif
1198 	case SA_LOCKED:
1199 	case SA_LOCKED | SA_NOTRECURSED:
1200 	case SA_LOCKED | SA_RECURSED:
1201 #ifdef WITNESS
1202 		witness_assert(&sx->lock_object, what, file, line);
1203 #else
1204 		/*
1205 		 * If some other thread has an exclusive lock or we
1206 		 * have one and are asserting a shared lock, fail.
1207 		 * Also, if no one has a lock at all, fail.
1208 		 */
1209 		if (sx->sx_lock == SX_LOCK_UNLOCKED ||
1210 		    (!(sx->sx_lock & SX_LOCK_SHARED) && (slocked ||
1211 		    sx_xholder(sx) != curthread)))
1212 			panic("Lock %s not %slocked @ %s:%d\n",
1213 			    sx->lock_object.lo_name, slocked ? "share " : "",
1214 			    file, line);
1215 
1216 		if (!(sx->sx_lock & SX_LOCK_SHARED)) {
1217 			if (sx_recursed(sx)) {
1218 				if (what & SA_NOTRECURSED)
1219 					panic("Lock %s recursed @ %s:%d\n",
1220 					    sx->lock_object.lo_name, file,
1221 					    line);
1222 			} else if (what & SA_RECURSED)
1223 				panic("Lock %s not recursed @ %s:%d\n",
1224 				    sx->lock_object.lo_name, file, line);
1225 		}
1226 #endif
1227 		break;
1228 	case SA_XLOCKED:
1229 	case SA_XLOCKED | SA_NOTRECURSED:
1230 	case SA_XLOCKED | SA_RECURSED:
1231 		if (sx_xholder(sx) != curthread)
1232 			panic("Lock %s not exclusively locked @ %s:%d\n",
1233 			    sx->lock_object.lo_name, file, line);
1234 		if (sx_recursed(sx)) {
1235 			if (what & SA_NOTRECURSED)
1236 				panic("Lock %s recursed @ %s:%d\n",
1237 				    sx->lock_object.lo_name, file, line);
1238 		} else if (what & SA_RECURSED)
1239 			panic("Lock %s not recursed @ %s:%d\n",
1240 			    sx->lock_object.lo_name, file, line);
1241 		break;
1242 	case SA_UNLOCKED:
1243 #ifdef WITNESS
1244 		witness_assert(&sx->lock_object, what, file, line);
1245 #else
1246 		/*
1247 		 * If we hold an exclusve lock fail.  We can't
1248 		 * reliably check to see if we hold a shared lock or
1249 		 * not.
1250 		 */
1251 		if (sx_xholder(sx) == curthread)
1252 			panic("Lock %s exclusively locked @ %s:%d\n",
1253 			    sx->lock_object.lo_name, file, line);
1254 #endif
1255 		break;
1256 	default:
1257 		panic("Unknown sx lock assertion: %d @ %s:%d", what, file,
1258 		    line);
1259 	}
1260 }
1261 #endif	/* INVARIANT_SUPPORT */
1262 
1263 #ifdef DDB
1264 static void
1265 db_show_sx(const struct lock_object *lock)
1266 {
1267 	struct thread *td;
1268 	const struct sx *sx;
1269 
1270 	sx = (const struct sx *)lock;
1271 
1272 	db_printf(" state: ");
1273 	if (sx->sx_lock == SX_LOCK_UNLOCKED)
1274 		db_printf("UNLOCKED\n");
1275 	else if (sx->sx_lock == SX_LOCK_DESTROYED) {
1276 		db_printf("DESTROYED\n");
1277 		return;
1278 	} else if (sx->sx_lock & SX_LOCK_SHARED)
1279 		db_printf("SLOCK: %ju\n", (uintmax_t)SX_SHARERS(sx->sx_lock));
1280 	else {
1281 		td = sx_xholder(sx);
1282 		db_printf("XLOCK: %p (tid %d, pid %d, \"%s\")\n", td,
1283 		    td->td_tid, td->td_proc->p_pid, td->td_name);
1284 		if (sx_recursed(sx))
1285 			db_printf(" recursed: %d\n", sx->sx_recurse);
1286 	}
1287 
1288 	db_printf(" waiters: ");
1289 	switch(sx->sx_lock &
1290 	    (SX_LOCK_SHARED_WAITERS | SX_LOCK_EXCLUSIVE_WAITERS)) {
1291 	case SX_LOCK_SHARED_WAITERS:
1292 		db_printf("shared\n");
1293 		break;
1294 	case SX_LOCK_EXCLUSIVE_WAITERS:
1295 		db_printf("exclusive\n");
1296 		break;
1297 	case SX_LOCK_SHARED_WAITERS | SX_LOCK_EXCLUSIVE_WAITERS:
1298 		db_printf("exclusive and shared\n");
1299 		break;
1300 	default:
1301 		db_printf("none\n");
1302 	}
1303 }
1304 
1305 /*
1306  * Check to see if a thread that is blocked on a sleep queue is actually
1307  * blocked on an sx lock.  If so, output some details and return true.
1308  * If the lock has an exclusive owner, return that in *ownerp.
1309  */
1310 int
1311 sx_chain(struct thread *td, struct thread **ownerp)
1312 {
1313 	struct sx *sx;
1314 
1315 	/*
1316 	 * Check to see if this thread is blocked on an sx lock.
1317 	 * First, we check the lock class.  If that is ok, then we
1318 	 * compare the lock name against the wait message.
1319 	 */
1320 	sx = td->td_wchan;
1321 	if (LOCK_CLASS(&sx->lock_object) != &lock_class_sx ||
1322 	    sx->lock_object.lo_name != td->td_wmesg)
1323 		return (0);
1324 
1325 	/* We think we have an sx lock, so output some details. */
1326 	db_printf("blocked on sx \"%s\" ", td->td_wmesg);
1327 	*ownerp = sx_xholder(sx);
1328 	if (sx->sx_lock & SX_LOCK_SHARED)
1329 		db_printf("SLOCK (count %ju)\n",
1330 		    (uintmax_t)SX_SHARERS(sx->sx_lock));
1331 	else
1332 		db_printf("XLOCK\n");
1333 	return (1);
1334 }
1335 #endif
1336