xref: /freebsd/sys/kern/subr_turnstile.c (revision d5a08a6065a153f519dc5ada150c981d37f91345)
10384fff8SJason Evans /*-
20384fff8SJason Evans  * Copyright (c) 1998 Berkeley Software Design, Inc. All rights reserved.
30384fff8SJason Evans  *
40384fff8SJason Evans  * Redistribution and use in source and binary forms, with or without
50384fff8SJason Evans  * modification, are permitted provided that the following conditions
60384fff8SJason Evans  * are met:
70384fff8SJason Evans  * 1. Redistributions of source code must retain the above copyright
80384fff8SJason Evans  *    notice, this list of conditions and the following disclaimer.
90384fff8SJason Evans  * 2. Redistributions in binary form must reproduce the above copyright
100384fff8SJason Evans  *    notice, this list of conditions and the following disclaimer in the
110384fff8SJason Evans  *    documentation and/or other materials provided with the distribution.
120384fff8SJason Evans  * 3. Berkeley Software Design Inc's name may not be used to endorse or
130384fff8SJason Evans  *    promote products derived from this software without specific prior
140384fff8SJason Evans  *    written permission.
150384fff8SJason Evans  *
160384fff8SJason Evans  * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND
170384fff8SJason Evans  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
180384fff8SJason Evans  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
190384fff8SJason Evans  * ARE DISCLAIMED.  IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE
200384fff8SJason Evans  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
210384fff8SJason Evans  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
220384fff8SJason Evans  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
230384fff8SJason Evans  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
240384fff8SJason Evans  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
250384fff8SJason Evans  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
260384fff8SJason Evans  * SUCH DAMAGE.
270384fff8SJason Evans  *
280384fff8SJason Evans  *	from BSDI $Id: mutex_witness.c,v 1.1.2.20 2000/04/27 03:10:27 cp Exp $
2936412d79SJohn Baldwin  *	and BSDI $Id: synch_machdep.c,v 2.3.2.39 2000/04/27 03:10:25 cp Exp $
300384fff8SJason Evans  * $FreeBSD$
310384fff8SJason Evans  */
320384fff8SJason Evans 
330384fff8SJason Evans /*
349ed346baSBosko Milekic  * Machine independent bits of mutex implementation and implementation of
359ed346baSBosko Milekic  * `witness' structure & related debugging routines.
369ed346baSBosko Milekic  */
379ed346baSBosko Milekic 
389ed346baSBosko Milekic /*
390384fff8SJason Evans  *	Main Entry: witness
400384fff8SJason Evans  *	Pronunciation: 'wit-n&s
410384fff8SJason Evans  *	Function: noun
420384fff8SJason Evans  *	Etymology: Middle English witnesse, from Old English witnes knowledge,
430384fff8SJason Evans  *	    testimony, witness, from 2wit
440384fff8SJason Evans  *	Date: before 12th century
450384fff8SJason Evans  *	1 : attestation of a fact or event : TESTIMONY
460384fff8SJason Evans  *	2 : one that gives evidence; specifically : one who testifies in
470384fff8SJason Evans  *	    a cause or before a judicial tribunal
480384fff8SJason Evans  *	3 : one asked to be present at a transaction so as to be able to
490384fff8SJason Evans  *	    testify to its having taken place
500384fff8SJason Evans  *	4 : one who has personal knowledge of something
510384fff8SJason Evans  *	5 a : something serving as evidence or proof : SIGN
520384fff8SJason Evans  *	  b : public affirmation by word or example of usually
530384fff8SJason Evans  *	      religious faith or conviction <the heroic witness to divine
540384fff8SJason Evans  *	      life -- Pilot>
550384fff8SJason Evans  *	6 capitalized : a member of the Jehovah's Witnesses
560384fff8SJason Evans  */
570384fff8SJason Evans 
589c36c934SJohn Baldwin #include "opt_ddb.h"
59a5a96a19SJohn Baldwin #include "opt_witness.h"
60a5a96a19SJohn Baldwin 
610384fff8SJason Evans #include <sys/param.h>
6236412d79SJohn Baldwin #include <sys/bus.h>
6336412d79SJohn Baldwin #include <sys/kernel.h>
6436412d79SJohn Baldwin #include <sys/malloc.h>
650384fff8SJason Evans #include <sys/proc.h>
66a5a96a19SJohn Baldwin #include <sys/sysctl.h>
670384fff8SJason Evans #include <sys/systm.h>
6836412d79SJohn Baldwin #include <sys/vmmeter.h>
690384fff8SJason Evans #include <sys/ktr.h>
700384fff8SJason Evans 
7136412d79SJohn Baldwin #include <machine/atomic.h>
7236412d79SJohn Baldwin #include <machine/bus.h>
7336412d79SJohn Baldwin #include <machine/clock.h>
740384fff8SJason Evans #include <machine/cpu.h>
7536412d79SJohn Baldwin 
769c36c934SJohn Baldwin #include <ddb/ddb.h>
779c36c934SJohn Baldwin 
7836412d79SJohn Baldwin #include <vm/vm.h>
7936412d79SJohn Baldwin #include <vm/vm_extern.h>
8036412d79SJohn Baldwin 
8136412d79SJohn Baldwin #include <sys/mutex.h>
8236412d79SJohn Baldwin 
8336412d79SJohn Baldwin /*
849ed346baSBosko Milekic  * The WITNESS-enabled mutex debug structure.
8536412d79SJohn Baldwin  */
866936206eSJohn Baldwin #ifdef WITNESS
870cde2e34SJason Evans struct mtx_debug {
880cde2e34SJason Evans 	struct witness	*mtxd_witness;
890cde2e34SJason Evans 	LIST_ENTRY(mtx)	mtxd_held;
900cde2e34SJason Evans 	const char	*mtxd_file;
910cde2e34SJason Evans 	int		mtxd_line;
920cde2e34SJason Evans };
930cde2e34SJason Evans 
948484de75SJohn Baldwin #define mtx_held	mtx_debug->mtxd_held
958484de75SJohn Baldwin #define	mtx_file	mtx_debug->mtxd_file
968484de75SJohn Baldwin #define	mtx_line	mtx_debug->mtxd_line
978484de75SJohn Baldwin #define	mtx_witness	mtx_debug->mtxd_witness
980cde2e34SJason Evans #endif	/* WITNESS */
990cde2e34SJason Evans 
1000cde2e34SJason Evans /*
1019ed346baSBosko Milekic  * Internal utility macros.
1020cde2e34SJason Evans  */
1039ed346baSBosko Milekic #define mtx_unowned(m)	((m)->mtx_lock == MTX_UNOWNED)
1040cde2e34SJason Evans 
1059ed346baSBosko Milekic #define mtx_owner(m)	(mtx_unowned((m)) ? NULL \
1069ed346baSBosko Milekic 	: (struct proc *)((m)->mtx_lock & MTX_FLAGMASK))
1079ed346baSBosko Milekic 
1089ed346baSBosko Milekic #define RETIP(x)		*(((uintptr_t *)(&x)) - 1)
109d5a08a60SJake Burkholder #define SET_PRIO(p, pri)	(p)->p_pri.pri_level = (pri)
1100cde2e34SJason Evans 
1110cde2e34SJason Evans /*
1129ed346baSBosko Milekic  * Early WITNESS-enabled declarations.
1130cde2e34SJason Evans  */
1140cde2e34SJason Evans #ifdef WITNESS
1159ed346baSBosko Milekic 
1169ed346baSBosko Milekic /*
1179ed346baSBosko Milekic  * Internal WITNESS routines which must be prototyped early.
1189ed346baSBosko Milekic  *
1199ed346baSBosko Milekic  * XXX: When/if witness code is cleaned up, it would be wise to place all
1209ed346baSBosko Milekic  *	witness prototyping early in this file.
1219ed346baSBosko Milekic  */
1220cde2e34SJason Evans static void witness_init(struct mtx *, int flag);
1230cde2e34SJason Evans static void witness_destroy(struct mtx *);
1240cde2e34SJason Evans static void witness_display(void(*)(const char *fmt, ...));
1250cde2e34SJason Evans 
1269ed346baSBosko Milekic MALLOC_DEFINE(M_WITNESS, "witness", "witness mtx_debug structure");
1279ed346baSBosko Milekic 
1280cde2e34SJason Evans /* All mutexes in system (used for debug/panic) */
1298484de75SJohn Baldwin static struct mtx_debug all_mtx_debug = { NULL, {NULL, NULL}, NULL, 0 };
1300cde2e34SJason Evans 
1310cde2e34SJason Evans /*
1329ed346baSBosko Milekic  * This global is set to 0 once it becomes safe to use the witness code.
1339ed346baSBosko Milekic  */
1349ed346baSBosko Milekic static int witness_cold = 1;
1359ed346baSBosko Milekic 
1369ed346baSBosko Milekic #else	/* WITNESS */
1379ed346baSBosko Milekic 
1389ed346baSBosko Milekic /* XXX XXX XXX
1399ed346baSBosko Milekic  * flag++ is sleazoid way of shuting up warning
1400cde2e34SJason Evans  */
1410cde2e34SJason Evans #define witness_init(m, flag) flag++
1420cde2e34SJason Evans #define witness_destroy(m)
1430cde2e34SJason Evans #define witness_try_enter(m, t, f, l)
1446936206eSJohn Baldwin #endif	/* WITNESS */
14536412d79SJohn Baldwin 
1469ed346baSBosko Milekic /*
1479ed346baSBosko Milekic  * All mutex locks in system are kept on the all_mtx list.
1489ed346baSBosko Milekic  */
1498484de75SJohn Baldwin static struct mtx all_mtx = { MTX_UNOWNED, 0, 0, 0, "All mutexes queue head",
1508484de75SJohn Baldwin 	TAILQ_HEAD_INITIALIZER(all_mtx.mtx_blocked),
1518484de75SJohn Baldwin 	{ NULL, NULL }, &all_mtx, &all_mtx,
1528484de75SJohn Baldwin #ifdef WITNESS
1538484de75SJohn Baldwin 	&all_mtx_debug
1548484de75SJohn Baldwin #else
1558484de75SJohn Baldwin 	NULL
1568484de75SJohn Baldwin #endif
1578484de75SJohn Baldwin 	 };
1588484de75SJohn Baldwin 
1599ed346baSBosko Milekic /*
1609ed346baSBosko Milekic  * Global variables for book keeping.
1619ed346baSBosko Milekic  */
16236412d79SJohn Baldwin static int	mtx_cur_cnt;
16336412d79SJohn Baldwin static int	mtx_max_cnt;
16436412d79SJohn Baldwin 
1659ed346baSBosko Milekic /*
1665746a1d8SBosko Milekic  * Couple of strings for KTR_LOCK tracing in order to avoid duplicates.
1675746a1d8SBosko Milekic  */
1685746a1d8SBosko Milekic char	STR_mtx_lock_slp[] = "GOT (sleep) %s [%p] r=%d at %s:%d";
1695746a1d8SBosko Milekic char	STR_mtx_unlock_slp[] = "REL (sleep) %s [%p] r=%d at %s:%d";
1705746a1d8SBosko Milekic char	STR_mtx_lock_spn[] = "GOT (spin) %s [%p] r=%d at %s:%d";
1715746a1d8SBosko Milekic char	STR_mtx_unlock_spn[] = "REL (spin) %s [%p] r=%d at %s:%d";
1725746a1d8SBosko Milekic 
1735746a1d8SBosko Milekic /*
1749ed346baSBosko Milekic  * Prototypes for non-exported routines.
1759ed346baSBosko Milekic  *
1769ed346baSBosko Milekic  * NOTE: Prototypes for witness routines are placed at the bottom of the file.
1779ed346baSBosko Milekic  */
1781bd0eefbSJohn Baldwin static void	propagate_priority(struct proc *);
17936412d79SJohn Baldwin 
18036412d79SJohn Baldwin static void
18136412d79SJohn Baldwin propagate_priority(struct proc *p)
18236412d79SJohn Baldwin {
183d5a08a60SJake Burkholder 	int pri = p->p_pri.pri_level;
18436412d79SJohn Baldwin 	struct mtx *m = p->p_blocked;
18536412d79SJohn Baldwin 
1861bd0eefbSJohn Baldwin 	mtx_assert(&sched_lock, MA_OWNED);
18736412d79SJohn Baldwin 	for (;;) {
18836412d79SJohn Baldwin 		struct proc *p1;
18936412d79SJohn Baldwin 
19036412d79SJohn Baldwin 		p = mtx_owner(m);
19136412d79SJohn Baldwin 
19236412d79SJohn Baldwin 		if (p == NULL) {
19336412d79SJohn Baldwin 			/*
19436412d79SJohn Baldwin 			 * This really isn't quite right. Really
19536412d79SJohn Baldwin 			 * ought to bump priority of process that
19636412d79SJohn Baldwin 			 * next acquires the mutex.
19736412d79SJohn Baldwin 			 */
19836412d79SJohn Baldwin 			MPASS(m->mtx_lock == MTX_CONTESTED);
19936412d79SJohn Baldwin 			return;
20036412d79SJohn Baldwin 		}
2019ed346baSBosko Milekic 
20236412d79SJohn Baldwin 		MPASS(p->p_magic == P_MAGIC);
2031bd0eefbSJohn Baldwin 		KASSERT(p->p_stat != SSLEEP, ("sleeping process owns a mutex"));
204d5a08a60SJake Burkholder 		if (p->p_pri.pri_level <= pri)
20536412d79SJohn Baldwin 			return;
2061bd0eefbSJohn Baldwin 
2071bd0eefbSJohn Baldwin 		/*
2081bd0eefbSJohn Baldwin 		 * Bump this process' priority.
2091bd0eefbSJohn Baldwin 		 */
2101bd0eefbSJohn Baldwin 		SET_PRIO(p, pri);
2111bd0eefbSJohn Baldwin 
21236412d79SJohn Baldwin 		/*
21336412d79SJohn Baldwin 		 * If lock holder is actually running, just bump priority.
21436412d79SJohn Baldwin 		 */
2151bd0eefbSJohn Baldwin 		if (p->p_oncpu != 0xff) {
21636412d79SJohn Baldwin 			MPASS(p->p_stat == SRUN || p->p_stat == SZOMB);
21736412d79SJohn Baldwin 			return;
21836412d79SJohn Baldwin 		}
219d5a08a60SJake Burkholder 
22036412d79SJohn Baldwin 		/*
22136412d79SJohn Baldwin 		 * If on run queue move to new run queue, and
22236412d79SJohn Baldwin 		 * quit.
22336412d79SJohn Baldwin 		 */
22436412d79SJohn Baldwin 		if (p->p_stat == SRUN) {
22536412d79SJohn Baldwin 			MPASS(p->p_blocked == NULL);
22636412d79SJohn Baldwin 			remrunqueue(p);
22736412d79SJohn Baldwin 			setrunqueue(p);
22836412d79SJohn Baldwin 			return;
22936412d79SJohn Baldwin 		}
23036412d79SJohn Baldwin 
23136412d79SJohn Baldwin 		/*
2321bd0eefbSJohn Baldwin 		 * If we aren't blocked on a mutex, we should be.
23336412d79SJohn Baldwin 		 */
2341bd0eefbSJohn Baldwin 		KASSERT(p->p_stat == SMTX, (
2351bd0eefbSJohn Baldwin 		    "process %d(%s):%d holds %s but isn't blocked on a mutex\n",
2361bd0eefbSJohn Baldwin 		    p->p_pid, p->p_comm, p->p_stat,
2371bd0eefbSJohn Baldwin 		    m->mtx_description));
23836412d79SJohn Baldwin 
23936412d79SJohn Baldwin 		/*
24036412d79SJohn Baldwin 		 * Pick up the mutex that p is blocked on.
24136412d79SJohn Baldwin 		 */
24236412d79SJohn Baldwin 		m = p->p_blocked;
24336412d79SJohn Baldwin 		MPASS(m != NULL);
24436412d79SJohn Baldwin 
24536412d79SJohn Baldwin 		/*
24636412d79SJohn Baldwin 		 * Check if the proc needs to be moved up on
24736412d79SJohn Baldwin 		 * the blocked chain
24836412d79SJohn Baldwin 		 */
2491bd0eefbSJohn Baldwin 		if (p == TAILQ_FIRST(&m->mtx_blocked)) {
2501bd0eefbSJohn Baldwin 			continue;
2511bd0eefbSJohn Baldwin 		}
2529ed346baSBosko Milekic 
253d5a08a60SJake Burkholder 		p1 = TAILQ_PREV(p, procqueue, p_procq);
254d5a08a60SJake Burkholder 		if (p1->p_pri.pri_level <= pri) {
25536412d79SJohn Baldwin 			continue;
25636412d79SJohn Baldwin 		}
25736412d79SJohn Baldwin 
25836412d79SJohn Baldwin 		/*
2591bd0eefbSJohn Baldwin 		 * Remove proc from blocked chain and determine where
2601bd0eefbSJohn Baldwin 		 * it should be moved up to.  Since we know that p1 has
2611bd0eefbSJohn Baldwin 		 * a lower priority than p, we know that at least one
2621bd0eefbSJohn Baldwin 		 * process in the chain has a lower priority and that
2631bd0eefbSJohn Baldwin 		 * p1 will thus not be NULL after the loop.
26436412d79SJohn Baldwin 		 */
26536412d79SJohn Baldwin 		TAILQ_REMOVE(&m->mtx_blocked, p, p_procq);
26636412d79SJohn Baldwin 		TAILQ_FOREACH(p1, &m->mtx_blocked, p_procq) {
26736412d79SJohn Baldwin 			MPASS(p1->p_magic == P_MAGIC);
268d5a08a60SJake Burkholder 			if (p1->p_pri.pri_level > pri)
26936412d79SJohn Baldwin 				break;
27036412d79SJohn Baldwin 		}
2719ed346baSBosko Milekic 
2721bd0eefbSJohn Baldwin 		MPASS(p1 != NULL);
27336412d79SJohn Baldwin 		TAILQ_INSERT_BEFORE(p1, p, p_procq);
27436412d79SJohn Baldwin 		CTR4(KTR_LOCK,
2758484de75SJohn Baldwin 		    "propagate_priority: p %p moved before %p on [%p] %s",
27636412d79SJohn Baldwin 		    p, p1, m, m->mtx_description);
27736412d79SJohn Baldwin 	}
27836412d79SJohn Baldwin }
27936412d79SJohn Baldwin 
2800cde2e34SJason Evans /*
2819ed346baSBosko Milekic  * The important part of mtx_trylock{,_flags}()
2829ed346baSBosko Milekic  * Tries to acquire lock `m.' We do NOT handle recursion here; we assume that
2839ed346baSBosko Milekic  * if we're called, it's because we know we don't already own this lock.
2840cde2e34SJason Evans  */
2850cde2e34SJason Evans int
2869ed346baSBosko Milekic _mtx_trylock(struct mtx *m, int opts, const char *file, int line)
2870cde2e34SJason Evans {
2880cde2e34SJason Evans 	int rval;
2890cde2e34SJason Evans 
2905746a1d8SBosko Milekic 	MPASS(CURPROC != NULL);
2919ed346baSBosko Milekic 
2929ed346baSBosko Milekic 	/*
2939ed346baSBosko Milekic 	 * _mtx_trylock does not accept MTX_NOSWITCH option.
2949ed346baSBosko Milekic 	 */
2955746a1d8SBosko Milekic 	KASSERT((opts & MTX_NOSWITCH) == 0,
2965746a1d8SBosko Milekic 	    ("mtx_trylock() called with invalid option flag(s) %d", opts));
2979ed346baSBosko Milekic 
2989ed346baSBosko Milekic 	rval = _obtain_lock(m, CURTHD);
2999ed346baSBosko Milekic 
3000cde2e34SJason Evans #ifdef WITNESS
3019ed346baSBosko Milekic 	if (rval && m->mtx_witness != NULL) {
3029ed346baSBosko Milekic 		/*
3039ed346baSBosko Milekic 		 * We do not handle recursion in _mtx_trylock; see the
3049ed346baSBosko Milekic 		 * note at the top of the routine.
3059ed346baSBosko Milekic 		 */
3065746a1d8SBosko Milekic 		KASSERT(!mtx_recursed(m),
3075746a1d8SBosko Milekic 		    ("mtx_trylock() called on a recursed mutex"));
3089ed346baSBosko Milekic 		witness_try_enter(m, (opts | m->mtx_flags), file, line);
3090cde2e34SJason Evans 	}
3100cde2e34SJason Evans #endif	/* WITNESS */
3119ed346baSBosko Milekic 
3129ed346baSBosko Milekic 	if ((opts & MTX_QUIET) == 0)
3139ed346baSBosko Milekic 		CTR5(KTR_LOCK, "TRY_ENTER %s [%p] result=%d at %s:%d",
3149ed346baSBosko Milekic 		    m->mtx_description, m, rval, file, line);
3150cde2e34SJason Evans 
3160cde2e34SJason Evans 	return rval;
3170cde2e34SJason Evans }
3180cde2e34SJason Evans 
3190cde2e34SJason Evans /*
3209ed346baSBosko Milekic  * _mtx_lock_sleep: the tougher part of acquiring an MTX_DEF lock.
3219ed346baSBosko Milekic  *
3229ed346baSBosko Milekic  * We call this if the lock is either contested (i.e. we need to go to
3239ed346baSBosko Milekic  * sleep waiting for it), or if we need to recurse on it.
3240cde2e34SJason Evans  */
3250cde2e34SJason Evans void
3269ed346baSBosko Milekic _mtx_lock_sleep(struct mtx *m, int opts, const char *file, int line)
32736412d79SJohn Baldwin {
32836412d79SJohn Baldwin 	struct proc *p = CURPROC;
32936412d79SJohn Baldwin 
33036412d79SJohn Baldwin 	if ((m->mtx_lock & MTX_FLAGMASK) == (uintptr_t)p) {
33136412d79SJohn Baldwin 		m->mtx_recurse++;
33208812b39SBosko Milekic 		atomic_set_ptr(&m->mtx_lock, MTX_RECURSED);
3339ed346baSBosko Milekic 		if ((opts & MTX_QUIET) == 0)
3345746a1d8SBosko Milekic 			CTR1(KTR_LOCK, "_mtx_lock_sleep: %p recursing", m);
33536412d79SJohn Baldwin 		return;
33636412d79SJohn Baldwin 	}
3379ed346baSBosko Milekic 
3389ed346baSBosko Milekic 	if ((opts & MTX_QUIET) == 0)
3395746a1d8SBosko Milekic 		CTR3(KTR_LOCK, "_mtx_lock_sleep: %p contested (lock=%p) [%p]",
3405746a1d8SBosko Milekic 		    m, (void *)m->mtx_lock, (void *)RETIP(m));
3411bd0eefbSJohn Baldwin 
3421bd0eefbSJohn Baldwin 	/*
3439ed346baSBosko Milekic 	 * Save our priority. Even though p_nativepri is protected by
3449ed346baSBosko Milekic 	 * sched_lock, we don't obtain it here as it can be expensive.
3459ed346baSBosko Milekic 	 * Since this is the only place p_nativepri is set, and since two
3469ed346baSBosko Milekic 	 * CPUs will not be executing the same process concurrently, we know
3479ed346baSBosko Milekic 	 * that no other CPU is going to be messing with this. Also,
3489ed346baSBosko Milekic 	 * p_nativepri is only read when we are blocked on a mutex, so that
3499ed346baSBosko Milekic 	 * can't be happening right now either.
3501bd0eefbSJohn Baldwin 	 */
351d5a08a60SJake Burkholder 	p->p_pri.pri_native = p->p_pri.pri_level;
3529ed346baSBosko Milekic 
35336412d79SJohn Baldwin 	while (!_obtain_lock(m, p)) {
354f5271ebcSJohn Baldwin 		uintptr_t v;
35536412d79SJohn Baldwin 		struct proc *p1;
35636412d79SJohn Baldwin 
3579ed346baSBosko Milekic 		mtx_lock_spin(&sched_lock);
35836412d79SJohn Baldwin 		/*
3599ed346baSBosko Milekic 		 * Check if the lock has been released while spinning for
3609ed346baSBosko Milekic 		 * the sched_lock.
36136412d79SJohn Baldwin 		 */
36236412d79SJohn Baldwin 		if ((v = m->mtx_lock) == MTX_UNOWNED) {
3639ed346baSBosko Milekic 			mtx_unlock_spin(&sched_lock);
36436412d79SJohn Baldwin 			continue;
36536412d79SJohn Baldwin 		}
3669ed346baSBosko Milekic 
36736412d79SJohn Baldwin 		/*
3689ed346baSBosko Milekic 		 * The mutex was marked contested on release. This means that
3699ed346baSBosko Milekic 		 * there are processes blocked on it.
37036412d79SJohn Baldwin 		 */
37136412d79SJohn Baldwin 		if (v == MTX_CONTESTED) {
37236412d79SJohn Baldwin 			p1 = TAILQ_FIRST(&m->mtx_blocked);
3735746a1d8SBosko Milekic 			MPASS(p1 != NULL);
37436412d79SJohn Baldwin 			m->mtx_lock = (uintptr_t)p | MTX_CONTESTED;
3759ed346baSBosko Milekic 
376d5a08a60SJake Burkholder 			if (p1->p_pri.pri_level < p->p_pri.pri_level)
377d5a08a60SJake Burkholder 				SET_PRIO(p, p1->p_pri.pri_level);
3789ed346baSBosko Milekic 			mtx_unlock_spin(&sched_lock);
37936412d79SJohn Baldwin 			return;
38036412d79SJohn Baldwin 		}
3819ed346baSBosko Milekic 
38236412d79SJohn Baldwin 		/*
3839ed346baSBosko Milekic 		 * If the mutex isn't already contested and a failure occurs
3849ed346baSBosko Milekic 		 * setting the contested bit, the mutex was either released
3859ed346baSBosko Milekic 		 * or the state of the MTX_RECURSED bit changed.
38636412d79SJohn Baldwin 		 */
38736412d79SJohn Baldwin 		if ((v & MTX_CONTESTED) == 0 &&
38836412d79SJohn Baldwin 		    !atomic_cmpset_ptr(&m->mtx_lock, (void *)v,
38936412d79SJohn Baldwin 			(void *)(v | MTX_CONTESTED))) {
3909ed346baSBosko Milekic 			mtx_unlock_spin(&sched_lock);
39136412d79SJohn Baldwin 			continue;
39236412d79SJohn Baldwin 		}
39336412d79SJohn Baldwin 
3949ed346baSBosko Milekic 		/*
3959ed346baSBosko Milekic 		 * We deffinately must sleep for this lock.
3969ed346baSBosko Milekic 		 */
39736412d79SJohn Baldwin 		mtx_assert(m, MA_NOTOWNED);
39836412d79SJohn Baldwin 
39936412d79SJohn Baldwin #ifdef notyet
40036412d79SJohn Baldwin 		/*
4019ed346baSBosko Milekic 		 * If we're borrowing an interrupted thread's VM context, we
4029ed346baSBosko Milekic 		 * must clean up before going to sleep.
40336412d79SJohn Baldwin 		 */
40436412d79SJohn Baldwin 		if (p->p_flag & (P_ITHD | P_SITHD)) {
40536412d79SJohn Baldwin 			ithd_t *it = (ithd_t *)p;
40636412d79SJohn Baldwin 
40736412d79SJohn Baldwin 			if (it->it_interrupted) {
4089ed346baSBosko Milekic 				if ((opts & MTX_QUIET) == 0)
40936412d79SJohn Baldwin 					CTR2(KTR_LOCK,
4105746a1d8SBosko Milekic 				    "_mtx_lock_sleep: 0x%x interrupted 0x%x",
41136412d79SJohn Baldwin 					    it, it->it_interrupted);
41236412d79SJohn Baldwin 				intr_thd_fixup(it);
41336412d79SJohn Baldwin 			}
41436412d79SJohn Baldwin 		}
41536412d79SJohn Baldwin #endif
41636412d79SJohn Baldwin 
4179ed346baSBosko Milekic 		/*
4189ed346baSBosko Milekic 		 * Put us on the list of threads blocked on this mutex.
4199ed346baSBosko Milekic 		 */
42036412d79SJohn Baldwin 		if (TAILQ_EMPTY(&m->mtx_blocked)) {
4219ed346baSBosko Milekic 			p1 = (struct proc *)(m->mtx_lock & MTX_FLAGMASK);
4229ed346baSBosko Milekic 			LIST_INSERT_HEAD(&p1->p_contested, m, mtx_contested);
42336412d79SJohn Baldwin 			TAILQ_INSERT_TAIL(&m->mtx_blocked, p, p_procq);
42436412d79SJohn Baldwin 		} else {
42536412d79SJohn Baldwin 			TAILQ_FOREACH(p1, &m->mtx_blocked, p_procq)
426d5a08a60SJake Burkholder 				if (p1->p_pri.pri_level > p->p_pri.pri_level)
42736412d79SJohn Baldwin 					break;
42836412d79SJohn Baldwin 			if (p1)
42936412d79SJohn Baldwin 				TAILQ_INSERT_BEFORE(p1, p, p_procq);
43036412d79SJohn Baldwin 			else
4319ed346baSBosko Milekic 				TAILQ_INSERT_TAIL(&m->mtx_blocked, p, p_procq);
43236412d79SJohn Baldwin 		}
43336412d79SJohn Baldwin 
4349ed346baSBosko Milekic 		/*
4359ed346baSBosko Milekic 		 * Save who we're blocked on.
4369ed346baSBosko Milekic 		 */
4379ed346baSBosko Milekic 		p->p_blocked = m;
43886327ad8SJohn Baldwin 		p->p_mtxname = m->mtx_description;
43936412d79SJohn Baldwin 		p->p_stat = SMTX;
44036412d79SJohn Baldwin 		propagate_priority(p);
4419ed346baSBosko Milekic 
4429ed346baSBosko Milekic 		if ((opts & MTX_QUIET) == 0)
443562e4ffeSJohn Baldwin 			CTR3(KTR_LOCK,
4449ed346baSBosko Milekic 			    "_mtx_lock_sleep: p %p blocked on [%p] %s", p, m,
4459ed346baSBosko Milekic 			    m->mtx_description);
4469ed346baSBosko Milekic 
44720cdcc5bSJohn Baldwin 		mi_switch();
4489ed346baSBosko Milekic 
4499ed346baSBosko Milekic 		if ((opts & MTX_QUIET) == 0)
45036412d79SJohn Baldwin 			CTR3(KTR_LOCK,
4519ed346baSBosko Milekic 			  "_mtx_lock_sleep: p %p free from blocked on [%p] %s",
45236412d79SJohn Baldwin 			  p, m, m->mtx_description);
4539ed346baSBosko Milekic 
4549ed346baSBosko Milekic 		mtx_unlock_spin(&sched_lock);
45536412d79SJohn Baldwin 	}
4569ed346baSBosko Milekic 
45736412d79SJohn Baldwin 	return;
4589ed346baSBosko Milekic }
4599ed346baSBosko Milekic 
4609ed346baSBosko Milekic /*
4619ed346baSBosko Milekic  * _mtx_lock_spin: the tougher part of acquiring an MTX_SPIN lock.
4629ed346baSBosko Milekic  *
4639ed346baSBosko Milekic  * This is only called if we need to actually spin for the lock. Recursion
4649ed346baSBosko Milekic  * is handled inline.
4659ed346baSBosko Milekic  */
4669ed346baSBosko Milekic void
4679ed346baSBosko Milekic _mtx_lock_spin(struct mtx *m, int opts, u_int mtx_intr, const char *file,
4689ed346baSBosko Milekic 	       int line)
46936412d79SJohn Baldwin {
47036412d79SJohn Baldwin 	int i = 0;
47136412d79SJohn Baldwin 
4729ed346baSBosko Milekic 	if ((opts & MTX_QUIET) == 0)
4735746a1d8SBosko Milekic 		CTR1(KTR_LOCK, "_mtx_lock_spin: %p spinning", m);
4749ed346baSBosko Milekic 
47536412d79SJohn Baldwin 	for (;;) {
4769ed346baSBosko Milekic 		if (_obtain_lock(m, CURPROC))
47736412d79SJohn Baldwin 			break;
4789ed346baSBosko Milekic 
47936412d79SJohn Baldwin 		while (m->mtx_lock != MTX_UNOWNED) {
48036412d79SJohn Baldwin 			if (i++ < 1000000)
48136412d79SJohn Baldwin 				continue;
48236412d79SJohn Baldwin 			if (i++ < 6000000)
48336412d79SJohn Baldwin 				DELAY(1);
48436412d79SJohn Baldwin #ifdef DDB
48536412d79SJohn Baldwin 			else if (!db_active)
48636412d79SJohn Baldwin #else
48736412d79SJohn Baldwin 			else
48836412d79SJohn Baldwin #endif
4899ed346baSBosko Milekic 			panic("spin lock %s held by %p for > 5 seconds",
4909ed346baSBosko Milekic 			    m->mtx_description, (void *)m->mtx_lock);
49136412d79SJohn Baldwin 		}
49236412d79SJohn Baldwin 	}
49336412d79SJohn Baldwin 
4949ed346baSBosko Milekic 	m->mtx_saveintr = mtx_intr;
4959ed346baSBosko Milekic 	if ((opts & MTX_QUIET) == 0)
4969ed346baSBosko Milekic 		CTR1(KTR_LOCK, "_mtx_lock_spin: %p spin done", m);
4979ed346baSBosko Milekic 
49836412d79SJohn Baldwin 	return;
49936412d79SJohn Baldwin }
50036412d79SJohn Baldwin 
5019ed346baSBosko Milekic /*
5029ed346baSBosko Milekic  * _mtx_unlock_sleep: the tougher part of releasing an MTX_DEF lock.
5039ed346baSBosko Milekic  *
5049ed346baSBosko Milekic  * We are only called here if the lock is recursed or contested (i.e. we
5059ed346baSBosko Milekic  * need to wake up a blocked thread).
5069ed346baSBosko Milekic  */
50736412d79SJohn Baldwin void
5089ed346baSBosko Milekic _mtx_unlock_sleep(struct mtx *m, int opts, const char *file, int line)
50936412d79SJohn Baldwin {
51036412d79SJohn Baldwin 	struct proc *p, *p1;
51136412d79SJohn Baldwin 	struct mtx *m1;
51236412d79SJohn Baldwin 	int pri;
51336412d79SJohn Baldwin 
51436412d79SJohn Baldwin 	p = CURPROC;
5159ed346baSBosko Milekic 	MPASS4(mtx_owned(m), "mtx_owned(mpp)", file, line);
5169ed346baSBosko Milekic 
51708812b39SBosko Milekic 	if (mtx_recursed(m)) {
51836412d79SJohn Baldwin 		if (--(m->mtx_recurse) == 0)
51908812b39SBosko Milekic 			atomic_clear_ptr(&m->mtx_lock, MTX_RECURSED);
5209ed346baSBosko Milekic 		if ((opts & MTX_QUIET) == 0)
5219ed346baSBosko Milekic 			CTR1(KTR_LOCK, "_mtx_unlock_sleep: %p unrecurse", m);
52236412d79SJohn Baldwin 		return;
52336412d79SJohn Baldwin 	}
5249ed346baSBosko Milekic 
5259ed346baSBosko Milekic 	mtx_lock_spin(&sched_lock);
5269ed346baSBosko Milekic 	if ((opts & MTX_QUIET) == 0)
5279ed346baSBosko Milekic 		CTR1(KTR_LOCK, "_mtx_unlock_sleep: %p contested", m);
5289ed346baSBosko Milekic 
52936412d79SJohn Baldwin 	p1 = TAILQ_FIRST(&m->mtx_blocked);
53036412d79SJohn Baldwin 	MPASS(p->p_magic == P_MAGIC);
53136412d79SJohn Baldwin 	MPASS(p1->p_magic == P_MAGIC);
5329ed346baSBosko Milekic 
53336412d79SJohn Baldwin 	TAILQ_REMOVE(&m->mtx_blocked, p1, p_procq);
5349ed346baSBosko Milekic 
53536412d79SJohn Baldwin 	if (TAILQ_EMPTY(&m->mtx_blocked)) {
53636412d79SJohn Baldwin 		LIST_REMOVE(m, mtx_contested);
53736412d79SJohn Baldwin 		_release_lock_quick(m);
5389ed346baSBosko Milekic 		if ((opts & MTX_QUIET) == 0)
5399ed346baSBosko Milekic 			CTR1(KTR_LOCK, "_mtx_unlock_sleep: %p not held", m);
54036412d79SJohn Baldwin 	} else
5419ed346baSBosko Milekic 		atomic_store_rel_ptr(&m->mtx_lock, (void *)MTX_CONTESTED);
5429ed346baSBosko Milekic 
543d5a08a60SJake Burkholder 	pri = PRI_MAX;
54436412d79SJohn Baldwin 	LIST_FOREACH(m1, &p->p_contested, mtx_contested) {
545d5a08a60SJake Burkholder 		int cp = TAILQ_FIRST(&m1->mtx_blocked)->p_pri.pri_level;
54636412d79SJohn Baldwin 		if (cp < pri)
54736412d79SJohn Baldwin 			pri = cp;
54836412d79SJohn Baldwin 	}
5499ed346baSBosko Milekic 
550d5a08a60SJake Burkholder 	if (pri > p->p_pri.pri_native)
551d5a08a60SJake Burkholder 		pri = p->p_pri.pri_native;
55236412d79SJohn Baldwin 	SET_PRIO(p, pri);
5539ed346baSBosko Milekic 
5549ed346baSBosko Milekic 	if ((opts & MTX_QUIET) == 0)
5559ed346baSBosko Milekic 		CTR2(KTR_LOCK, "_mtx_unlock_sleep: %p contested setrunqueue %p",
5569ed346baSBosko Milekic 		    m, p1);
5579ed346baSBosko Milekic 
55836412d79SJohn Baldwin 	p1->p_blocked = NULL;
55986327ad8SJohn Baldwin 	p1->p_mtxname = NULL;
56036412d79SJohn Baldwin 	p1->p_stat = SRUN;
56136412d79SJohn Baldwin 	setrunqueue(p1);
5629ed346baSBosko Milekic 
563d5a08a60SJake Burkholder 	if ((opts & MTX_NOSWITCH) == 0 && p1->p_pri.pri_level < pri) {
56436412d79SJohn Baldwin #ifdef notyet
56536412d79SJohn Baldwin 		if (p->p_flag & (P_ITHD | P_SITHD)) {
56636412d79SJohn Baldwin 			ithd_t *it = (ithd_t *)p;
56736412d79SJohn Baldwin 
56836412d79SJohn Baldwin 			if (it->it_interrupted) {
5699ed346baSBosko Milekic 				if ((opts & MTX_QUIET) == 0)
57036412d79SJohn Baldwin 					CTR2(KTR_LOCK,
5719ed346baSBosko Milekic 				    "_mtx_unlock_sleep: 0x%x interrupted 0x%x",
57236412d79SJohn Baldwin 					    it, it->it_interrupted);
57336412d79SJohn Baldwin 				intr_thd_fixup(it);
57436412d79SJohn Baldwin 			}
57536412d79SJohn Baldwin 		}
57636412d79SJohn Baldwin #endif
57736412d79SJohn Baldwin 		setrunqueue(p);
5789ed346baSBosko Milekic 		if ((opts & MTX_QUIET) == 0)
579562e4ffeSJohn Baldwin 			CTR2(KTR_LOCK,
5809ed346baSBosko Milekic 			    "_mtx_unlock_sleep: %p switching out lock=%p", m,
5819ed346baSBosko Milekic 			    (void *)m->mtx_lock);
5829ed346baSBosko Milekic 
58336412d79SJohn Baldwin 		mi_switch();
5849ed346baSBosko Milekic 		if ((opts & MTX_QUIET) == 0)
5859ed346baSBosko Milekic 			CTR2(KTR_LOCK, "_mtx_unlock_sleep: %p resuming lock=%p",
58631271627SJohn Baldwin 			    m, (void *)m->mtx_lock);
58736412d79SJohn Baldwin 	}
58836412d79SJohn Baldwin 
5899ed346baSBosko Milekic 	mtx_unlock_spin(&sched_lock);
5909ed346baSBosko Milekic 
5919ed346baSBosko Milekic 	return;
5929ed346baSBosko Milekic }
5939ed346baSBosko Milekic 
5949ed346baSBosko Milekic /*
5959ed346baSBosko Milekic  * All the unlocking of MTX_SPIN locks is done inline.
5969ed346baSBosko Milekic  * See the _rel_spin_lock() macro for the details.
5979ed346baSBosko Milekic  */
5989ed346baSBosko Milekic 
5999ed346baSBosko Milekic /*
6009ed346baSBosko Milekic  * The INVARIANTS-enabled mtx_assert()
6019ed346baSBosko Milekic  */
6020cde2e34SJason Evans #ifdef INVARIANTS
6030cde2e34SJason Evans void
60456771ca7SJason Evans _mtx_assert(struct mtx *m, int what, const char *file, int line)
6050cde2e34SJason Evans {
6060cde2e34SJason Evans 	switch ((what)) {
6070cde2e34SJason Evans 	case MA_OWNED:
6080cde2e34SJason Evans 	case MA_OWNED | MA_RECURSED:
6090cde2e34SJason Evans 	case MA_OWNED | MA_NOTRECURSED:
6100cde2e34SJason Evans 		if (!mtx_owned((m)))
6110cde2e34SJason Evans 			panic("mutex %s not owned at %s:%d",
61256771ca7SJason Evans 			    (m)->mtx_description, file, line);
6130cde2e34SJason Evans 		if (mtx_recursed((m))) {
6140cde2e34SJason Evans 			if (((what) & MA_NOTRECURSED) != 0)
6150cde2e34SJason Evans 				panic("mutex %s recursed at %s:%d",
61656771ca7SJason Evans 				    (m)->mtx_description, file, line);
6170cde2e34SJason Evans 		} else if (((what) & MA_RECURSED) != 0) {
6180cde2e34SJason Evans 			panic("mutex %s unrecursed at %s:%d",
61956771ca7SJason Evans 			    (m)->mtx_description, file, line);
6200cde2e34SJason Evans 		}
6210cde2e34SJason Evans 		break;
6220cde2e34SJason Evans 	case MA_NOTOWNED:
6230cde2e34SJason Evans 		if (mtx_owned((m)))
6240cde2e34SJason Evans 			panic("mutex %s owned at %s:%d",
62556771ca7SJason Evans 			    (m)->mtx_description, file, line);
6260cde2e34SJason Evans 		break;
6270cde2e34SJason Evans 	default:
62856771ca7SJason Evans 		panic("unknown mtx_assert at %s:%d", file, line);
6290cde2e34SJason Evans 	}
6300cde2e34SJason Evans }
6310cde2e34SJason Evans #endif
6320cde2e34SJason Evans 
6339ed346baSBosko Milekic /*
6349ed346baSBosko Milekic  * The MUTEX_DEBUG-enabled mtx_validate()
6359ed346baSBosko Milekic  */
63636412d79SJohn Baldwin #define MV_DESTROY	0	/* validate before destory */
63736412d79SJohn Baldwin #define MV_INIT		1	/* validate before init */
63836412d79SJohn Baldwin 
63936412d79SJohn Baldwin #ifdef MUTEX_DEBUG
64036412d79SJohn Baldwin 
64136412d79SJohn Baldwin int mtx_validate __P((struct mtx *, int));
64236412d79SJohn Baldwin 
64336412d79SJohn Baldwin int
64436412d79SJohn Baldwin mtx_validate(struct mtx *m, int when)
64536412d79SJohn Baldwin {
64636412d79SJohn Baldwin 	struct mtx *mp;
64736412d79SJohn Baldwin 	int i;
64836412d79SJohn Baldwin 	int retval = 0;
64936412d79SJohn Baldwin 
650d1c1b841SJason Evans #ifdef WITNESS
651d1c1b841SJason Evans 	if (witness_cold)
652d1c1b841SJason Evans 		return 0;
653d1c1b841SJason Evans #endif
65436412d79SJohn Baldwin 	if (m == &all_mtx || cold)
65536412d79SJohn Baldwin 		return 0;
65636412d79SJohn Baldwin 
6579ed346baSBosko Milekic 	mtx_lock(&all_mtx);
65836412d79SJohn Baldwin /*
65936412d79SJohn Baldwin  * XXX - When kernacc() is fixed on the alpha to handle K0_SEG memory properly
66036412d79SJohn Baldwin  * we can re-enable the kernacc() checks.
66136412d79SJohn Baldwin  */
66236412d79SJohn Baldwin #ifndef __alpha__
66336412d79SJohn Baldwin 	MPASS(kernacc((caddr_t)all_mtx.mtx_next, sizeof(uintptr_t),
66436412d79SJohn Baldwin 	    VM_PROT_READ) == 1);
66536412d79SJohn Baldwin #endif
66636412d79SJohn Baldwin 	MPASS(all_mtx.mtx_next->mtx_prev == &all_mtx);
66736412d79SJohn Baldwin 	for (i = 0, mp = all_mtx.mtx_next; mp != &all_mtx; mp = mp->mtx_next) {
66836412d79SJohn Baldwin #ifndef __alpha__
66936412d79SJohn Baldwin 		if (kernacc((caddr_t)mp->mtx_next, sizeof(uintptr_t),
67036412d79SJohn Baldwin 		    VM_PROT_READ) != 1) {
67136412d79SJohn Baldwin 			panic("mtx_validate: mp=%p mp->mtx_next=%p",
67236412d79SJohn Baldwin 			    mp, mp->mtx_next);
67336412d79SJohn Baldwin 		}
67436412d79SJohn Baldwin #endif
67536412d79SJohn Baldwin 		i++;
67636412d79SJohn Baldwin 		if (i > mtx_cur_cnt) {
67736412d79SJohn Baldwin 			panic("mtx_validate: too many in chain, known=%d\n",
67836412d79SJohn Baldwin 			    mtx_cur_cnt);
67936412d79SJohn Baldwin 		}
68036412d79SJohn Baldwin 	}
68136412d79SJohn Baldwin 	MPASS(i == mtx_cur_cnt);
68236412d79SJohn Baldwin 	switch (when) {
68336412d79SJohn Baldwin 	case MV_DESTROY:
68436412d79SJohn Baldwin 		for (mp = all_mtx.mtx_next; mp != &all_mtx; mp = mp->mtx_next)
68536412d79SJohn Baldwin 			if (mp == m)
68636412d79SJohn Baldwin 				break;
68736412d79SJohn Baldwin 		MPASS(mp == m);
68836412d79SJohn Baldwin 		break;
68936412d79SJohn Baldwin 	case MV_INIT:
69036412d79SJohn Baldwin 		for (mp = all_mtx.mtx_next; mp != &all_mtx; mp = mp->mtx_next)
69136412d79SJohn Baldwin 		if (mp == m) {
69236412d79SJohn Baldwin 			/*
69336412d79SJohn Baldwin 			 * Not good. This mutex already exists.
69436412d79SJohn Baldwin 			 */
69536412d79SJohn Baldwin 			printf("re-initing existing mutex %s\n",
69636412d79SJohn Baldwin 			    m->mtx_description);
69736412d79SJohn Baldwin 			MPASS(m->mtx_lock == MTX_UNOWNED);
69836412d79SJohn Baldwin 			retval = 1;
69936412d79SJohn Baldwin 		}
70036412d79SJohn Baldwin 	}
7019ed346baSBosko Milekic 	mtx_unlock(&all_mtx);
70236412d79SJohn Baldwin 	return (retval);
70336412d79SJohn Baldwin }
70436412d79SJohn Baldwin #endif
70536412d79SJohn Baldwin 
7069ed346baSBosko Milekic /*
7079ed346baSBosko Milekic  * Mutex initialization routine; initialize lock `m' of type contained in
7089ed346baSBosko Milekic  * `opts' with options contained in `opts' and description `description.'
7099ed346baSBosko Milekic  * Place on "all_mtx" queue.
7109ed346baSBosko Milekic  */
71136412d79SJohn Baldwin void
7129ed346baSBosko Milekic mtx_init(struct mtx *m, const char *description, int opts)
71336412d79SJohn Baldwin {
7149ed346baSBosko Milekic 
7159ed346baSBosko Milekic 	if ((opts & MTX_QUIET) == 0)
7169ed346baSBosko Milekic 		CTR2(KTR_LOCK, "mtx_init %p (%s)", m, description);
7179ed346baSBosko Milekic 
71836412d79SJohn Baldwin #ifdef MUTEX_DEBUG
7199ed346baSBosko Milekic 	/* Diagnostic and error correction */
7209ed346baSBosko Milekic 	if (mtx_validate(m, MV_INIT))
72136412d79SJohn Baldwin 		return;
7226936206eSJohn Baldwin #endif
72336412d79SJohn Baldwin 
72436412d79SJohn Baldwin 	bzero((void *)m, sizeof *m);
72536412d79SJohn Baldwin 	TAILQ_INIT(&m->mtx_blocked);
7269ed346baSBosko Milekic 
7276936206eSJohn Baldwin #ifdef WITNESS
728d1c1b841SJason Evans 	if (!witness_cold) {
7298484de75SJohn Baldwin 		m->mtx_debug = malloc(sizeof(struct mtx_debug),
7309ed346baSBosko Milekic 		    M_WITNESS, M_NOWAIT | M_ZERO);
7318484de75SJohn Baldwin 		MPASS(m->mtx_debug != NULL);
732d1c1b841SJason Evans 	}
733d1c1b841SJason Evans #endif
734d1c1b841SJason Evans 
7359ed346baSBosko Milekic 	m->mtx_description = description;
7369ed346baSBosko Milekic 	m->mtx_flags = opts;
73736412d79SJohn Baldwin 	m->mtx_lock = MTX_UNOWNED;
7389ed346baSBosko Milekic 
73936412d79SJohn Baldwin 	/* Put on all mutex queue */
7409ed346baSBosko Milekic 	mtx_lock(&all_mtx);
74136412d79SJohn Baldwin 	m->mtx_next = &all_mtx;
74236412d79SJohn Baldwin 	m->mtx_prev = all_mtx.mtx_prev;
74336412d79SJohn Baldwin 	m->mtx_prev->mtx_next = m;
74436412d79SJohn Baldwin 	all_mtx.mtx_prev = m;
74536412d79SJohn Baldwin 	if (++mtx_cur_cnt > mtx_max_cnt)
74636412d79SJohn Baldwin 		mtx_max_cnt = mtx_cur_cnt;
7479ed346baSBosko Milekic 	mtx_unlock(&all_mtx);
7489ed346baSBosko Milekic 
749d1c1b841SJason Evans #ifdef WITNESS
750d1c1b841SJason Evans 	if (!witness_cold)
7519ed346baSBosko Milekic 		witness_init(m, opts);
752d1c1b841SJason Evans #endif
75336412d79SJohn Baldwin }
75436412d79SJohn Baldwin 
7559ed346baSBosko Milekic /*
7569ed346baSBosko Milekic  * Remove lock `m' from all_mtx queue.
7579ed346baSBosko Milekic  */
75836412d79SJohn Baldwin void
75936412d79SJohn Baldwin mtx_destroy(struct mtx *m)
76036412d79SJohn Baldwin {
76136412d79SJohn Baldwin 
762d1c1b841SJason Evans #ifdef WITNESS
763d1c1b841SJason Evans 	KASSERT(!witness_cold, ("%s: Cannot destroy while still cold\n",
764d1c1b841SJason Evans 	    __FUNCTION__));
765d1c1b841SJason Evans #endif
7669ed346baSBosko Milekic 
7678484de75SJohn Baldwin 	CTR2(KTR_LOCK, "mtx_destroy %p (%s)", m, m->mtx_description);
7689ed346baSBosko Milekic 
76936412d79SJohn Baldwin #ifdef MUTEX_DEBUG
77036412d79SJohn Baldwin 	if (m->mtx_next == NULL)
77136412d79SJohn Baldwin 		panic("mtx_destroy: %p (%s) already destroyed",
77236412d79SJohn Baldwin 		    m, m->mtx_description);
77336412d79SJohn Baldwin 
77436412d79SJohn Baldwin 	if (!mtx_owned(m)) {
77536412d79SJohn Baldwin 		MPASS(m->mtx_lock == MTX_UNOWNED);
77636412d79SJohn Baldwin 	} else {
77708812b39SBosko Milekic 		MPASS((m->mtx_lock & (MTX_RECURSED|MTX_CONTESTED)) == 0);
77836412d79SJohn Baldwin 	}
7799ed346baSBosko Milekic 
7809ed346baSBosko Milekic 	/* diagnostic */
7819ed346baSBosko Milekic 	mtx_validate(m, MV_DESTROY);
78236412d79SJohn Baldwin #endif
78336412d79SJohn Baldwin 
78436412d79SJohn Baldwin #ifdef WITNESS
78536412d79SJohn Baldwin 	if (m->mtx_witness)
78636412d79SJohn Baldwin 		witness_destroy(m);
78736412d79SJohn Baldwin #endif /* WITNESS */
78836412d79SJohn Baldwin 
78936412d79SJohn Baldwin 	/* Remove from the all mutex queue */
7909ed346baSBosko Milekic 	mtx_lock(&all_mtx);
79136412d79SJohn Baldwin 	m->mtx_next->mtx_prev = m->mtx_prev;
79236412d79SJohn Baldwin 	m->mtx_prev->mtx_next = m->mtx_next;
7939ed346baSBosko Milekic 
79436412d79SJohn Baldwin #ifdef MUTEX_DEBUG
79536412d79SJohn Baldwin 	m->mtx_next = m->mtx_prev = NULL;
7966936206eSJohn Baldwin #endif
7979ed346baSBosko Milekic 
7986936206eSJohn Baldwin #ifdef WITNESS
7999ed346baSBosko Milekic 	free(m->mtx_debug, M_WITNESS);
8008484de75SJohn Baldwin 	m->mtx_debug = NULL;
80136412d79SJohn Baldwin #endif
8029ed346baSBosko Milekic 
80336412d79SJohn Baldwin 	mtx_cur_cnt--;
8049ed346baSBosko Milekic 	mtx_unlock(&all_mtx);
80536412d79SJohn Baldwin }
8060384fff8SJason Evans 
8078484de75SJohn Baldwin 
8089ed346baSBosko Milekic /*
8099ed346baSBosko Milekic  * The WITNESS-enabled diagnostic code.
8109ed346baSBosko Milekic  */
8116936206eSJohn Baldwin #ifdef WITNESS
8128484de75SJohn Baldwin static void
8138484de75SJohn Baldwin witness_fixup(void *dummy __unused)
8148484de75SJohn Baldwin {
8158484de75SJohn Baldwin 	struct mtx *mp;
8168484de75SJohn Baldwin 
8178484de75SJohn Baldwin 	/*
8188484de75SJohn Baldwin 	 * We have to release Giant before initializing its witness
8198484de75SJohn Baldwin 	 * structure so that WITNESS doesn't get confused.
8208484de75SJohn Baldwin 	 */
8219ed346baSBosko Milekic 	mtx_unlock(&Giant);
8228484de75SJohn Baldwin 	mtx_assert(&Giant, MA_NOTOWNED);
8239ed346baSBosko Milekic 
8249ed346baSBosko Milekic 	mtx_lock(&all_mtx);
8258484de75SJohn Baldwin 
8268484de75SJohn Baldwin 	/* Iterate through all mutexes and finish up mutex initialization. */
8278484de75SJohn Baldwin 	for (mp = all_mtx.mtx_next; mp != &all_mtx; mp = mp->mtx_next) {
8288484de75SJohn Baldwin 
8298484de75SJohn Baldwin 		mp->mtx_debug = malloc(sizeof(struct mtx_debug),
8309ed346baSBosko Milekic 		    M_WITNESS, M_NOWAIT | M_ZERO);
8318484de75SJohn Baldwin 		MPASS(mp->mtx_debug != NULL);
8328484de75SJohn Baldwin 
8338484de75SJohn Baldwin 		witness_init(mp, mp->mtx_flags);
8348484de75SJohn Baldwin 	}
8359ed346baSBosko Milekic 	mtx_unlock(&all_mtx);
8368484de75SJohn Baldwin 
8378484de75SJohn Baldwin 	/* Mark the witness code as being ready for use. */
8388484de75SJohn Baldwin 	atomic_store_rel_int(&witness_cold, 0);
8398484de75SJohn Baldwin 
8409ed346baSBosko Milekic 	mtx_lock(&Giant);
8418484de75SJohn Baldwin }
8428484de75SJohn Baldwin SYSINIT(wtnsfxup, SI_SUB_MUTEX, SI_ORDER_FIRST, witness_fixup, NULL)
8430384fff8SJason Evans 
8440384fff8SJason Evans #define WITNESS_COUNT 200
8450384fff8SJason Evans #define	WITNESS_NCHILDREN 2
8460384fff8SJason Evans 
84778f0da03SJohn Baldwin int witness_watch = 1;
8480384fff8SJason Evans 
849606f8eb2SJohn Baldwin struct witness {
8500384fff8SJason Evans 	struct witness	*w_next;
851b67a3e6eSJohn Baldwin 	const char	*w_description;
85212473b76SJason Evans 	const char	*w_file;
8530384fff8SJason Evans 	int		 w_line;
8540384fff8SJason Evans 	struct witness	*w_morechildren;
8550384fff8SJason Evans 	u_char		 w_childcnt;
8560384fff8SJason Evans 	u_char		 w_Giant_squawked:1;
8570384fff8SJason Evans 	u_char		 w_other_squawked:1;
8580384fff8SJason Evans 	u_char		 w_same_squawked:1;
85908812b39SBosko Milekic 	u_char		 w_spin:1;	/* MTX_SPIN type mutex. */
8600384fff8SJason Evans 	u_int		 w_level;
8610384fff8SJason Evans 	struct witness	*w_children[WITNESS_NCHILDREN];
862606f8eb2SJohn Baldwin };
8630384fff8SJason Evans 
864606f8eb2SJohn Baldwin struct witness_blessed {
8650384fff8SJason Evans 	char 	*b_lock1;
8660384fff8SJason Evans 	char	*b_lock2;
867606f8eb2SJohn Baldwin };
8680384fff8SJason Evans 
869a5a96a19SJohn Baldwin #ifdef DDB
8700384fff8SJason Evans /*
871a5a96a19SJohn Baldwin  * When DDB is enabled and witness_ddb is set to 1, it will cause the system to
8720384fff8SJason Evans  * drop into kdebug() when:
8730384fff8SJason Evans  *	- a lock heirarchy violation occurs
8740384fff8SJason Evans  *	- locks are held when going to sleep.
8750384fff8SJason Evans  */
8768484de75SJohn Baldwin int	witness_ddb;
877a5a96a19SJohn Baldwin #ifdef WITNESS_DDB
8788484de75SJohn Baldwin TUNABLE_INT_DECL("debug.witness_ddb", 1, witness_ddb);
879a5a96a19SJohn Baldwin #else
8808484de75SJohn Baldwin TUNABLE_INT_DECL("debug.witness_ddb", 0, witness_ddb);
8810384fff8SJason Evans #endif
882a5a96a19SJohn Baldwin SYSCTL_INT(_debug, OID_AUTO, witness_ddb, CTLFLAG_RW, &witness_ddb, 0, "");
883a5a96a19SJohn Baldwin #endif /* DDB */
8840384fff8SJason Evans 
8858484de75SJohn Baldwin int	witness_skipspin;
886a5a96a19SJohn Baldwin #ifdef WITNESS_SKIPSPIN
8878484de75SJohn Baldwin TUNABLE_INT_DECL("debug.witness_skipspin", 1, witness_skipspin);
888a5a96a19SJohn Baldwin #else
8898484de75SJohn Baldwin TUNABLE_INT_DECL("debug.witness_skipspin", 0, witness_skipspin);
8900384fff8SJason Evans #endif
891a5a96a19SJohn Baldwin SYSCTL_INT(_debug, OID_AUTO, witness_skipspin, CTLFLAG_RD, &witness_skipspin, 0,
892a5a96a19SJohn Baldwin     "");
8930384fff8SJason Evans 
8949ed346baSBosko Milekic /*
8959ed346baSBosko Milekic  * Witness-enabled globals
8969ed346baSBosko Milekic  */
897d1c1b841SJason Evans static struct mtx	w_mtx;
898606f8eb2SJohn Baldwin static struct witness	*w_free;
899606f8eb2SJohn Baldwin static struct witness	*w_all;
9000384fff8SJason Evans static int		 w_inited;
9010384fff8SJason Evans static int		 witness_dead;	/* fatal error, probably no memory */
9020384fff8SJason Evans 
903606f8eb2SJohn Baldwin static struct witness	 w_data[WITNESS_COUNT];
9040384fff8SJason Evans 
9059ed346baSBosko Milekic /*
9069ed346baSBosko Milekic  * Internal witness routine prototypes
9079ed346baSBosko Milekic  */
9089ed346baSBosko Milekic static struct witness *enroll(const char *description, int flag);
9099ed346baSBosko Milekic static int itismychild(struct witness *parent, struct witness *child);
9109ed346baSBosko Milekic static void removechild(struct witness *parent, struct witness *child);
9119ed346baSBosko Milekic static int isitmychild(struct witness *parent, struct witness *child);
9129ed346baSBosko Milekic static int isitmydescendant(struct witness *parent, struct witness *child);
9139ed346baSBosko Milekic static int dup_ok(struct witness *);
9149ed346baSBosko Milekic static int blessed(struct witness *, struct witness *);
9159ed346baSBosko Milekic static void
9169ed346baSBosko Milekic     witness_displaydescendants(void(*)(const char *fmt, ...), struct witness *);
9179ed346baSBosko Milekic static void witness_leveldescendents(struct witness *parent, int level);
9189ed346baSBosko Milekic static void witness_levelall(void);
9199ed346baSBosko Milekic static struct witness * witness_get(void);
9209ed346baSBosko Milekic static void witness_free(struct witness *m);
9210384fff8SJason Evans 
9220384fff8SJason Evans static char *ignore_list[] = {
9230384fff8SJason Evans 	"witness lock",
9240384fff8SJason Evans 	NULL
9250384fff8SJason Evans };
9260384fff8SJason Evans 
9270384fff8SJason Evans static char *spin_order_list[] = {
928e910ba59SJohn Baldwin #if defined(__i386__) && defined (SMP)
929e910ba59SJohn Baldwin 	"com",
930e910ba59SJohn Baldwin #endif
931a5a96a19SJohn Baldwin 	"sio",
932e910ba59SJohn Baldwin #ifdef __i386__
933e910ba59SJohn Baldwin 	"cy",
934e910ba59SJohn Baldwin #endif
9358f838cb5SJohn Baldwin 	"sched lock",
93620cdcc5bSJohn Baldwin #ifdef __i386__
93720cdcc5bSJohn Baldwin 	"clk",
93820cdcc5bSJohn Baldwin #endif
939fa2fbc3dSJake Burkholder 	"callout",
9400384fff8SJason Evans 	/*
9410384fff8SJason Evans 	 * leaf locks
9420384fff8SJason Evans 	 */
943e910ba59SJohn Baldwin 	"ithread table lock",
944e910ba59SJohn Baldwin 	"ithread list lock",
945e910ba59SJohn Baldwin #ifdef SMP
9461b367556SJason Evans #ifdef __i386__
9471b367556SJason Evans 	"ap boot",
9481b367556SJason Evans 	"imen",
9491b367556SJason Evans #endif
9501b367556SJason Evans 	"smp rendezvous",
951e910ba59SJohn Baldwin #endif
9520384fff8SJason Evans 	NULL
9530384fff8SJason Evans };
9540384fff8SJason Evans 
9550384fff8SJason Evans static char *order_list[] = {
956c75e5182SJohn Baldwin 	"Giant", "proctree", "allproc", "process lock", "uidinfo hash",
957c75e5182SJohn Baldwin 	    "uidinfo struct", NULL,
9580384fff8SJason Evans 	NULL
9590384fff8SJason Evans };
9600384fff8SJason Evans 
9610384fff8SJason Evans static char *dup_list[] = {
9620384fff8SJason Evans 	NULL
9630384fff8SJason Evans };
9640384fff8SJason Evans 
9650384fff8SJason Evans static char *sleep_list[] = {
9667da6f977SJake Burkholder 	"Giant",
9670384fff8SJason Evans 	NULL
9680384fff8SJason Evans };
9690384fff8SJason Evans 
9700384fff8SJason Evans /*
9710384fff8SJason Evans  * Pairs of locks which have been blessed
9720384fff8SJason Evans  * Don't complain about order problems with blessed locks
9730384fff8SJason Evans  */
974606f8eb2SJohn Baldwin static struct witness_blessed blessed_list[] = {
9750384fff8SJason Evans };
9769ed346baSBosko Milekic static int blessed_count =
9779ed346baSBosko Milekic 	sizeof(blessed_list) / sizeof(struct witness_blessed);
9780384fff8SJason Evans 
9790cde2e34SJason Evans static void
980606f8eb2SJohn Baldwin witness_init(struct mtx *m, int flag)
9810384fff8SJason Evans {
9820384fff8SJason Evans 	m->mtx_witness = enroll(m->mtx_description, flag);
9830384fff8SJason Evans }
9840384fff8SJason Evans 
9850cde2e34SJason Evans static void
986606f8eb2SJohn Baldwin witness_destroy(struct mtx *m)
9870384fff8SJason Evans {
988606f8eb2SJohn Baldwin 	struct mtx *m1;
9890384fff8SJason Evans 	struct proc *p;
9900384fff8SJason Evans 	p = CURPROC;
991e910ba59SJohn Baldwin 	LIST_FOREACH(m1, &p->p_heldmtx, mtx_held) {
9920384fff8SJason Evans 		if (m1 == m) {
9930384fff8SJason Evans 			LIST_REMOVE(m, mtx_held);
9940384fff8SJason Evans 			break;
9950384fff8SJason Evans 		}
9960384fff8SJason Evans 	}
9970384fff8SJason Evans 	return;
9980384fff8SJason Evans 
9990384fff8SJason Evans }
10000384fff8SJason Evans 
10010cde2e34SJason Evans static void
10020cde2e34SJason Evans witness_display(void(*prnt)(const char *fmt, ...))
10030cde2e34SJason Evans {
10040cde2e34SJason Evans 	struct witness *w, *w1;
1005e910ba59SJohn Baldwin 	int level, found;
10060cde2e34SJason Evans 
10070cde2e34SJason Evans 	KASSERT(!witness_cold, ("%s: witness_cold\n", __FUNCTION__));
10080cde2e34SJason Evans 	witness_levelall();
10090cde2e34SJason Evans 
1010e910ba59SJohn Baldwin 	/*
1011e910ba59SJohn Baldwin 	 * First, handle sleep mutexes which have been acquired at least
1012e910ba59SJohn Baldwin 	 * once.
1013e910ba59SJohn Baldwin 	 */
1014e910ba59SJohn Baldwin 	prnt("Sleep mutexes:\n");
10150cde2e34SJason Evans 	for (w = w_all; w; w = w->w_next) {
1016e910ba59SJohn Baldwin 		if (w->w_file == NULL || w->w_spin)
10170cde2e34SJason Evans 			continue;
10180cde2e34SJason Evans 		for (w1 = w_all; w1; w1 = w1->w_next) {
10190cde2e34SJason Evans 			if (isitmychild(w1, w))
10200cde2e34SJason Evans 				break;
10210cde2e34SJason Evans 		}
10220cde2e34SJason Evans 		if (w1 != NULL)
10230cde2e34SJason Evans 			continue;
10240cde2e34SJason Evans 		/*
10250cde2e34SJason Evans 		 * This lock has no anscestors, display its descendants.
10260cde2e34SJason Evans 		 */
10270cde2e34SJason Evans 		witness_displaydescendants(prnt, w);
10280cde2e34SJason Evans 	}
1029e910ba59SJohn Baldwin 
1030e910ba59SJohn Baldwin 	/*
1031e910ba59SJohn Baldwin 	 * Now do spin mutexes which have been acquired at least once.
1032e910ba59SJohn Baldwin 	 */
1033e910ba59SJohn Baldwin 	prnt("\nSpin mutexes:\n");
1034e910ba59SJohn Baldwin 	level = 0;
1035e910ba59SJohn Baldwin 	while (level < sizeof(spin_order_list) / sizeof(char *)) {
1036e910ba59SJohn Baldwin 		found = 0;
1037e910ba59SJohn Baldwin 		for (w = w_all; w; w = w->w_next) {
1038e910ba59SJohn Baldwin 			if (w->w_file == NULL || !w->w_spin)
1039e910ba59SJohn Baldwin 				continue;
1040e910ba59SJohn Baldwin 			if (w->w_level == 1 << level) {
1041e910ba59SJohn Baldwin 				witness_displaydescendants(prnt, w);
1042e910ba59SJohn Baldwin 				level++;
1043e910ba59SJohn Baldwin 				found = 1;
1044e910ba59SJohn Baldwin 			}
1045e910ba59SJohn Baldwin 		}
1046e910ba59SJohn Baldwin 		if (found == 0)
1047e910ba59SJohn Baldwin 			level++;
1048e910ba59SJohn Baldwin 	}
1049e910ba59SJohn Baldwin 
1050e910ba59SJohn Baldwin 	/*
1051e910ba59SJohn Baldwin 	 * Finally, any mutexes which have not been acquired yet.
1052e910ba59SJohn Baldwin 	 */
1053e910ba59SJohn Baldwin 	prnt("\nMutexes which were never acquired:\n");
10540cde2e34SJason Evans 	for (w = w_all; w; w = w->w_next) {
10550cde2e34SJason Evans 		if (w->w_file != NULL)
10560cde2e34SJason Evans 			continue;
10570cde2e34SJason Evans 		prnt("%s\n", w->w_description);
10580cde2e34SJason Evans 	}
10590cde2e34SJason Evans }
10600cde2e34SJason Evans 
10610384fff8SJason Evans void
1062606f8eb2SJohn Baldwin witness_enter(struct mtx *m, int flags, const char *file, int line)
10630384fff8SJason Evans {
1064606f8eb2SJohn Baldwin 	struct witness *w, *w1;
1065606f8eb2SJohn Baldwin 	struct mtx *m1;
10660384fff8SJason Evans 	struct proc *p;
10670384fff8SJason Evans 	int i;
1068a5a96a19SJohn Baldwin #ifdef DDB
1069a5a96a19SJohn Baldwin 	int go_into_ddb = 0;
1070a5a96a19SJohn Baldwin #endif /* DDB */
10710384fff8SJason Evans 
10720cde2e34SJason Evans 	if (witness_cold || m->mtx_witness == NULL || panicstr)
1073562e4ffeSJohn Baldwin 		return;
10740384fff8SJason Evans 	w = m->mtx_witness;
10750384fff8SJason Evans 	p = CURPROC;
10760384fff8SJason Evans 
10770384fff8SJason Evans 	if (flags & MTX_SPIN) {
10788484de75SJohn Baldwin 		if ((m->mtx_flags & MTX_SPIN) == 0)
10795340642aSJason Evans 			panic("mutex_enter: MTX_SPIN on MTX_DEF mutex %s @"
10805340642aSJason Evans 			    " %s:%d", m->mtx_description, file, line);
108108812b39SBosko Milekic 		if (mtx_recursed(m)) {
10828484de75SJohn Baldwin 			if ((m->mtx_flags & MTX_RECURSE) == 0)
108308812b39SBosko Milekic 				panic("mutex_enter: recursion on non-recursive"
108408812b39SBosko Milekic 				    " mutex %s @ %s:%d", m->mtx_description,
108508812b39SBosko Milekic 				    file, line);
10860384fff8SJason Evans 			return;
108708812b39SBosko Milekic 		}
10889ed346baSBosko Milekic 		mtx_lock_spin_flags(&w_mtx, MTX_QUIET);
1089ef73ae4bSJake Burkholder 		i = PCPU_GET(witness_spin_check);
10900384fff8SJason Evans 		if (i != 0 && w->w_level < i) {
10919ed346baSBosko Milekic 			mtx_unlock_spin_flags(&w_mtx, MTX_QUIET);
10925340642aSJason Evans 			panic("mutex_enter(%s:%x, MTX_SPIN) out of order @"
10935340642aSJason Evans 			    " %s:%d already holding %s:%x",
10940384fff8SJason Evans 			    m->mtx_description, w->w_level, file, line,
10950384fff8SJason Evans 			    spin_order_list[ffs(i)-1], i);
10960384fff8SJason Evans 		}
10970384fff8SJason Evans 		PCPU_SET(witness_spin_check, i | w->w_level);
10989ed346baSBosko Milekic 		mtx_unlock_spin_flags(&w_mtx, MTX_QUIET);
1099bbc7a98aSJohn Baldwin 		w->w_file = file;
1100bbc7a98aSJohn Baldwin 		w->w_line = line;
1101bbc7a98aSJohn Baldwin 		m->mtx_line = line;
1102bbc7a98aSJohn Baldwin 		m->mtx_file = file;
11030384fff8SJason Evans 		return;
11040384fff8SJason Evans 	}
11058484de75SJohn Baldwin 	if ((m->mtx_flags & MTX_SPIN) != 0)
11060384fff8SJason Evans 		panic("mutex_enter: MTX_DEF on MTX_SPIN mutex %s @ %s:%d",
11070384fff8SJason Evans 		    m->mtx_description, file, line);
11080384fff8SJason Evans 
110908812b39SBosko Milekic 	if (mtx_recursed(m)) {
11108484de75SJohn Baldwin 		if ((m->mtx_flags & MTX_RECURSE) == 0)
111108812b39SBosko Milekic 			panic("mutex_enter: recursion on non-recursive"
111208812b39SBosko Milekic 			    " mutex %s @ %s:%d", m->mtx_description,
111308812b39SBosko Milekic 			    file, line);
11140384fff8SJason Evans 		return;
111508812b39SBosko Milekic 	}
11160384fff8SJason Evans 	if (witness_dead)
11170384fff8SJason Evans 		goto out;
1118562e4ffeSJohn Baldwin 	if (cold)
11190384fff8SJason Evans 		goto out;
11200384fff8SJason Evans 
11210384fff8SJason Evans 	if (!mtx_legal2block())
11229ed346baSBosko Milekic 		panic("blockable mtx_lock() of %s when not legal @ %s:%d",
11230384fff8SJason Evans 			    m->mtx_description, file, line);
11240384fff8SJason Evans 	/*
11250384fff8SJason Evans 	 * Is this the first mutex acquired
11260384fff8SJason Evans 	 */
11270384fff8SJason Evans 	if ((m1 = LIST_FIRST(&p->p_heldmtx)) == NULL)
11280384fff8SJason Evans 		goto out;
11290384fff8SJason Evans 
11300384fff8SJason Evans 	if ((w1 = m1->mtx_witness) == w) {
11310384fff8SJason Evans 		if (w->w_same_squawked || dup_ok(w))
11320384fff8SJason Evans 			goto out;
11330384fff8SJason Evans 		w->w_same_squawked = 1;
11340384fff8SJason Evans 		printf("acquring duplicate lock of same type: \"%s\"\n",
11350384fff8SJason Evans 			m->mtx_description);
11360384fff8SJason Evans 		printf(" 1st @ %s:%d\n", w->w_file, w->w_line);
11370384fff8SJason Evans 		printf(" 2nd @ %s:%d\n", file, line);
1138a5a96a19SJohn Baldwin #ifdef DDB
1139a5a96a19SJohn Baldwin 		go_into_ddb = 1;
1140a5a96a19SJohn Baldwin #endif /* DDB */
11410384fff8SJason Evans 		goto out;
11420384fff8SJason Evans 	}
11430384fff8SJason Evans 	MPASS(!mtx_owned(&w_mtx));
11449ed346baSBosko Milekic 	mtx_lock_spin_flags(&w_mtx, MTX_QUIET);
11450384fff8SJason Evans 	/*
11460384fff8SJason Evans 	 * If we have a known higher number just say ok
11470384fff8SJason Evans 	 */
11480384fff8SJason Evans 	if (witness_watch > 1 && w->w_level > w1->w_level) {
11499ed346baSBosko Milekic 		mtx_unlock_spin_flags(&w_mtx, MTX_QUIET);
11500384fff8SJason Evans 		goto out;
11510384fff8SJason Evans 	}
11520384fff8SJason Evans 	if (isitmydescendant(m1->mtx_witness, w)) {
11539ed346baSBosko Milekic 		mtx_unlock_spin_flags(&w_mtx, MTX_QUIET);
11540384fff8SJason Evans 		goto out;
11550384fff8SJason Evans 	}
11560384fff8SJason Evans 	for (i = 0; m1 != NULL; m1 = LIST_NEXT(m1, mtx_held), i++) {
11570384fff8SJason Evans 
115836412d79SJohn Baldwin 		MPASS(i < 200);
11590384fff8SJason Evans 		w1 = m1->mtx_witness;
11600384fff8SJason Evans 		if (isitmydescendant(w, w1)) {
11619ed346baSBosko Milekic 			mtx_unlock_spin_flags(&w_mtx, MTX_QUIET);
11620384fff8SJason Evans 			if (blessed(w, w1))
11630384fff8SJason Evans 				goto out;
11640384fff8SJason Evans 			if (m1 == &Giant) {
11650384fff8SJason Evans 				if (w1->w_Giant_squawked)
11660384fff8SJason Evans 					goto out;
11670384fff8SJason Evans 				else
11680384fff8SJason Evans 					w1->w_Giant_squawked = 1;
11690384fff8SJason Evans 			} else {
11700384fff8SJason Evans 				if (w1->w_other_squawked)
11710384fff8SJason Evans 					goto out;
11720384fff8SJason Evans 				else
11730384fff8SJason Evans 					w1->w_other_squawked = 1;
11740384fff8SJason Evans 			}
11750384fff8SJason Evans 			printf("lock order reversal\n");
11760384fff8SJason Evans 			printf(" 1st %s last acquired @ %s:%d\n",
11770384fff8SJason Evans 			    w->w_description, w->w_file, w->w_line);
11780384fff8SJason Evans 			printf(" 2nd %p %s @ %s:%d\n",
11790384fff8SJason Evans 			    m1, w1->w_description, w1->w_file, w1->w_line);
11800384fff8SJason Evans 			printf(" 3rd %p %s @ %s:%d\n",
11810384fff8SJason Evans 			    m, w->w_description, file, line);
1182a5a96a19SJohn Baldwin #ifdef DDB
1183a5a96a19SJohn Baldwin 			go_into_ddb = 1;
1184a5a96a19SJohn Baldwin #endif /* DDB */
11850384fff8SJason Evans 			goto out;
11860384fff8SJason Evans 		}
11870384fff8SJason Evans 	}
11880384fff8SJason Evans 	m1 = LIST_FIRST(&p->p_heldmtx);
11890384fff8SJason Evans 	if (!itismychild(m1->mtx_witness, w))
11909ed346baSBosko Milekic 		mtx_unlock_spin_flags(&w_mtx, MTX_QUIET);
11910384fff8SJason Evans 
11920384fff8SJason Evans out:
1193a5a96a19SJohn Baldwin #ifdef DDB
1194a5a96a19SJohn Baldwin 	if (witness_ddb && go_into_ddb)
1195a5a96a19SJohn Baldwin 		Debugger("witness_enter");
1196a5a96a19SJohn Baldwin #endif /* DDB */
11970384fff8SJason Evans 	w->w_file = file;
11980384fff8SJason Evans 	w->w_line = line;
11990384fff8SJason Evans 	m->mtx_line = line;
12000384fff8SJason Evans 	m->mtx_file = file;
12010384fff8SJason Evans 
12020384fff8SJason Evans 	/*
12030384fff8SJason Evans 	 * If this pays off it likely means that a mutex being witnessed
12040384fff8SJason Evans 	 * is acquired in hardclock. Put it in the ignore list. It is
12050384fff8SJason Evans 	 * likely not the mutex this assert fails on.
12060384fff8SJason Evans 	 */
120736412d79SJohn Baldwin 	MPASS(m->mtx_held.le_prev == NULL);
12080384fff8SJason Evans 	LIST_INSERT_HEAD(&p->p_heldmtx, (struct mtx*)m, mtx_held);
12090384fff8SJason Evans }
12100384fff8SJason Evans 
12110384fff8SJason Evans void
1212606f8eb2SJohn Baldwin witness_try_enter(struct mtx *m, int flags, const char *file, int line)
12130384fff8SJason Evans {
12140384fff8SJason Evans 	struct proc *p;
1215606f8eb2SJohn Baldwin 	struct witness *w = m->mtx_witness;
12160384fff8SJason Evans 
1217d1c1b841SJason Evans 	if (witness_cold)
1218d1c1b841SJason Evans 		return;
1219562e4ffeSJohn Baldwin 	if (panicstr)
1220562e4ffeSJohn Baldwin 		return;
12210384fff8SJason Evans 	if (flags & MTX_SPIN) {
12228484de75SJohn Baldwin 		if ((m->mtx_flags & MTX_SPIN) == 0)
12230384fff8SJason Evans 			panic("mutex_try_enter: "
12240384fff8SJason Evans 			    "MTX_SPIN on MTX_DEF mutex %s @ %s:%d",
12250384fff8SJason Evans 			    m->mtx_description, file, line);
122608812b39SBosko Milekic 		if (mtx_recursed(m)) {
12278484de75SJohn Baldwin 			if ((m->mtx_flags & MTX_RECURSE) == 0)
122808812b39SBosko Milekic 				panic("mutex_try_enter: recursion on"
122908812b39SBosko Milekic 				    " non-recursive mutex %s @ %s:%d",
123008812b39SBosko Milekic 				    m->mtx_description, file, line);
12310384fff8SJason Evans 			return;
123208812b39SBosko Milekic 		}
12339ed346baSBosko Milekic 		mtx_lock_spin_flags(&w_mtx, MTX_QUIET);
1234ef73ae4bSJake Burkholder 		PCPU_SET(witness_spin_check,
1235ef73ae4bSJake Burkholder 		    PCPU_GET(witness_spin_check) | w->w_level);
12369ed346baSBosko Milekic 		mtx_unlock_spin_flags(&w_mtx, MTX_QUIET);
1237bbc7a98aSJohn Baldwin 		w->w_file = file;
1238bbc7a98aSJohn Baldwin 		w->w_line = line;
1239bbc7a98aSJohn Baldwin 		m->mtx_line = line;
1240bbc7a98aSJohn Baldwin 		m->mtx_file = file;
12410384fff8SJason Evans 		return;
12420384fff8SJason Evans 	}
12430384fff8SJason Evans 
12448484de75SJohn Baldwin 	if ((m->mtx_flags & MTX_SPIN) != 0)
12450384fff8SJason Evans 		panic("mutex_try_enter: MTX_DEF on MTX_SPIN mutex %s @ %s:%d",
12460384fff8SJason Evans 		    m->mtx_description, file, line);
12470384fff8SJason Evans 
124808812b39SBosko Milekic 	if (mtx_recursed(m)) {
12498484de75SJohn Baldwin 		if ((m->mtx_flags & MTX_RECURSE) == 0)
125008812b39SBosko Milekic 			panic("mutex_try_enter: recursion on non-recursive"
125108812b39SBosko Milekic 			    " mutex %s @ %s:%d", m->mtx_description, file,
125208812b39SBosko Milekic 			    line);
12530384fff8SJason Evans 		return;
125408812b39SBosko Milekic 	}
12550384fff8SJason Evans 	w->w_file = file;
12560384fff8SJason Evans 	w->w_line = line;
12570384fff8SJason Evans 	m->mtx_line = line;
12580384fff8SJason Evans 	m->mtx_file = file;
12590384fff8SJason Evans 	p = CURPROC;
126036412d79SJohn Baldwin 	MPASS(m->mtx_held.le_prev == NULL);
12610384fff8SJason Evans 	LIST_INSERT_HEAD(&p->p_heldmtx, (struct mtx*)m, mtx_held);
12620384fff8SJason Evans }
12630384fff8SJason Evans 
12640384fff8SJason Evans void
12650cde2e34SJason Evans witness_exit(struct mtx *m, int flags, const char *file, int line)
12660384fff8SJason Evans {
12670cde2e34SJason Evans 	struct witness *w;
12680384fff8SJason Evans 
12690cde2e34SJason Evans 	if (witness_cold || m->mtx_witness == NULL || panicstr)
12700cde2e34SJason Evans 		return;
12710cde2e34SJason Evans 	w = m->mtx_witness;
12720384fff8SJason Evans 
12730cde2e34SJason Evans 	if (flags & MTX_SPIN) {
12748484de75SJohn Baldwin 		if ((m->mtx_flags & MTX_SPIN) == 0)
12750cde2e34SJason Evans 			panic("mutex_exit: MTX_SPIN on MTX_DEF mutex %s @"
12760cde2e34SJason Evans 			    " %s:%d", m->mtx_description, file, line);
12770cde2e34SJason Evans 		if (mtx_recursed(m)) {
12788484de75SJohn Baldwin 			if ((m->mtx_flags & MTX_RECURSE) == 0)
12790cde2e34SJason Evans 				panic("mutex_exit: recursion on non-recursive"
12800cde2e34SJason Evans 				    " mutex %s @ %s:%d", m->mtx_description,
12810cde2e34SJason Evans 				    file, line);
12820cde2e34SJason Evans 			return;
12830384fff8SJason Evans 		}
12849ed346baSBosko Milekic 		mtx_lock_spin_flags(&w_mtx, MTX_QUIET);
12850cde2e34SJason Evans 		PCPU_SET(witness_spin_check,
12860cde2e34SJason Evans 		    PCPU_GET(witness_spin_check) & ~w->w_level);
12879ed346baSBosko Milekic 		mtx_unlock_spin_flags(&w_mtx, MTX_QUIET);
12880cde2e34SJason Evans 		return;
12890384fff8SJason Evans 	}
12908484de75SJohn Baldwin 	if ((m->mtx_flags & MTX_SPIN) != 0)
12910cde2e34SJason Evans 		panic("mutex_exit: MTX_DEF on MTX_SPIN mutex %s @ %s:%d",
12920cde2e34SJason Evans 		    m->mtx_description, file, line);
12930cde2e34SJason Evans 
12940cde2e34SJason Evans 	if (mtx_recursed(m)) {
12958484de75SJohn Baldwin 		if ((m->mtx_flags & MTX_RECURSE) == 0)
12960cde2e34SJason Evans 			panic("mutex_exit: recursion on non-recursive"
12970cde2e34SJason Evans 			    " mutex %s @ %s:%d", m->mtx_description,
12980cde2e34SJason Evans 			    file, line);
12990cde2e34SJason Evans 		return;
13000384fff8SJason Evans 	}
13010cde2e34SJason Evans 
13020cde2e34SJason Evans 	if ((flags & MTX_NOSWITCH) == 0 && !mtx_legal2block() && !cold)
13039ed346baSBosko Milekic 		panic("switchable mtx_unlock() of %s when not legal @ %s:%d",
13040cde2e34SJason Evans 			    m->mtx_description, file, line);
13050cde2e34SJason Evans 	LIST_REMOVE(m, mtx_held);
13060cde2e34SJason Evans 	m->mtx_held.le_prev = NULL;
13070384fff8SJason Evans }
13080384fff8SJason Evans 
13090384fff8SJason Evans int
1310606f8eb2SJohn Baldwin witness_sleep(int check_only, struct mtx *mtx, const char *file, int line)
13110384fff8SJason Evans {
1312606f8eb2SJohn Baldwin 	struct mtx *m;
13130384fff8SJason Evans 	struct proc *p;
13140384fff8SJason Evans 	char **sleep;
13150384fff8SJason Evans 	int n = 0;
13160384fff8SJason Evans 
1317d1c1b841SJason Evans 	KASSERT(!witness_cold, ("%s: witness_cold\n", __FUNCTION__));
13180384fff8SJason Evans 	p = CURPROC;
1319e910ba59SJohn Baldwin 	LIST_FOREACH(m, &p->p_heldmtx, mtx_held) {
13200384fff8SJason Evans 		if (m == mtx)
13210384fff8SJason Evans 			continue;
13220384fff8SJason Evans 		for (sleep = sleep_list; *sleep!= NULL; sleep++)
13230384fff8SJason Evans 			if (strcmp(m->mtx_description, *sleep) == 0)
13240384fff8SJason Evans 				goto next;
1325e910ba59SJohn Baldwin 		if (n == 0)
1326e910ba59SJohn Baldwin 			printf("Whee!\n");
13270384fff8SJason Evans 		printf("%s:%d: %s with \"%s\" locked from %s:%d\n",
13280384fff8SJason Evans 			file, line, check_only ? "could sleep" : "sleeping",
13290384fff8SJason Evans 			m->mtx_description,
13300384fff8SJason Evans 			m->mtx_witness->w_file, m->mtx_witness->w_line);
13310384fff8SJason Evans 		n++;
13320384fff8SJason Evans 	next:
13330384fff8SJason Evans 	}
1334a5a96a19SJohn Baldwin #ifdef DDB
1335a5a96a19SJohn Baldwin 	if (witness_ddb && n)
1336a5a96a19SJohn Baldwin 		Debugger("witness_sleep");
1337a5a96a19SJohn Baldwin #endif /* DDB */
13380384fff8SJason Evans 	return (n);
13390384fff8SJason Evans }
13400384fff8SJason Evans 
1341606f8eb2SJohn Baldwin static struct witness *
1342b67a3e6eSJohn Baldwin enroll(const char *description, int flag)
13430384fff8SJason Evans {
13440384fff8SJason Evans 	int i;
1345606f8eb2SJohn Baldwin 	struct witness *w, *w1;
13460384fff8SJason Evans 	char **ignore;
13470384fff8SJason Evans 	char **order;
13480384fff8SJason Evans 
13490384fff8SJason Evans 	if (!witness_watch)
13500384fff8SJason Evans 		return (NULL);
13510384fff8SJason Evans 	for (ignore = ignore_list; *ignore != NULL; ignore++)
13520384fff8SJason Evans 		if (strcmp(description, *ignore) == 0)
13530384fff8SJason Evans 			return (NULL);
13540384fff8SJason Evans 
13550384fff8SJason Evans 	if (w_inited == 0) {
1356d1c1b841SJason Evans 		mtx_init(&w_mtx, "witness lock", MTX_SPIN);
13570384fff8SJason Evans 		for (i = 0; i < WITNESS_COUNT; i++) {
13580384fff8SJason Evans 			w = &w_data[i];
13590384fff8SJason Evans 			witness_free(w);
13600384fff8SJason Evans 		}
13610384fff8SJason Evans 		w_inited = 1;
13620384fff8SJason Evans 		for (order = order_list; *order != NULL; order++) {
13630384fff8SJason Evans 			w = enroll(*order, MTX_DEF);
13640384fff8SJason Evans 			w->w_file = "order list";
13650384fff8SJason Evans 			for (order++; *order != NULL; order++) {
13660384fff8SJason Evans 				w1 = enroll(*order, MTX_DEF);
13670384fff8SJason Evans 				w1->w_file = "order list";
13680384fff8SJason Evans 				itismychild(w, w1);
13690384fff8SJason Evans 				w = w1;
13700384fff8SJason Evans     	    	    	}
13710384fff8SJason Evans 		}
13720384fff8SJason Evans 	}
13730384fff8SJason Evans 	if ((flag & MTX_SPIN) && witness_skipspin)
13740384fff8SJason Evans 		return (NULL);
13759ed346baSBosko Milekic 	mtx_lock_spin_flags(&w_mtx, MTX_QUIET);
13760384fff8SJason Evans 	for (w = w_all; w; w = w->w_next) {
13770384fff8SJason Evans 		if (strcmp(description, w->w_description) == 0) {
13789ed346baSBosko Milekic 			mtx_unlock_spin_flags(&w_mtx, MTX_QUIET);
13790384fff8SJason Evans 			return (w);
13800384fff8SJason Evans 		}
13810384fff8SJason Evans 	}
13820384fff8SJason Evans 	if ((w = witness_get()) == NULL)
13830384fff8SJason Evans 		return (NULL);
13840384fff8SJason Evans 	w->w_next = w_all;
13850384fff8SJason Evans 	w_all = w;
13860384fff8SJason Evans 	w->w_description = description;
13879ed346baSBosko Milekic 	mtx_unlock_spin_flags(&w_mtx, MTX_QUIET);
13880384fff8SJason Evans 	if (flag & MTX_SPIN) {
13890384fff8SJason Evans 		w->w_spin = 1;
13900384fff8SJason Evans 
13910384fff8SJason Evans 		i = 1;
13920384fff8SJason Evans 		for (order = spin_order_list; *order != NULL; order++) {
13930384fff8SJason Evans 			if (strcmp(description, *order) == 0)
13940384fff8SJason Evans 				break;
13950384fff8SJason Evans 			i <<= 1;
13960384fff8SJason Evans 		}
13970384fff8SJason Evans 		if (*order == NULL)
13980384fff8SJason Evans 			panic("spin lock %s not in order list", description);
13990384fff8SJason Evans 		w->w_level = i;
14008484de75SJohn Baldwin 	}
140108812b39SBosko Milekic 
14020384fff8SJason Evans 	return (w);
14030384fff8SJason Evans }
14040384fff8SJason Evans 
14050384fff8SJason Evans static int
1406606f8eb2SJohn Baldwin itismychild(struct witness *parent, struct witness *child)
14070384fff8SJason Evans {
14080384fff8SJason Evans 	static int recursed;
14090384fff8SJason Evans 
14100384fff8SJason Evans 	/*
14110384fff8SJason Evans 	 * Insert "child" after "parent"
14120384fff8SJason Evans 	 */
14130384fff8SJason Evans 	while (parent->w_morechildren)
14140384fff8SJason Evans 		parent = parent->w_morechildren;
14150384fff8SJason Evans 
14160384fff8SJason Evans 	if (parent->w_childcnt == WITNESS_NCHILDREN) {
14170384fff8SJason Evans 		if ((parent->w_morechildren = witness_get()) == NULL)
14180384fff8SJason Evans 			return (1);
14190384fff8SJason Evans 		parent = parent->w_morechildren;
14200384fff8SJason Evans 	}
142136412d79SJohn Baldwin 	MPASS(child != NULL);
14220384fff8SJason Evans 	parent->w_children[parent->w_childcnt++] = child;
14230384fff8SJason Evans 	/*
14240384fff8SJason Evans 	 * now prune whole tree
14250384fff8SJason Evans 	 */
14260384fff8SJason Evans 	if (recursed)
14270384fff8SJason Evans 		return (0);
14280384fff8SJason Evans 	recursed = 1;
14290384fff8SJason Evans 	for (child = w_all; child != NULL; child = child->w_next) {
14300384fff8SJason Evans 		for (parent = w_all; parent != NULL;
14310384fff8SJason Evans 		    parent = parent->w_next) {
14320384fff8SJason Evans 			if (!isitmychild(parent, child))
14330384fff8SJason Evans 				continue;
14340384fff8SJason Evans 			removechild(parent, child);
14350384fff8SJason Evans 			if (isitmydescendant(parent, child))
14360384fff8SJason Evans 				continue;
14370384fff8SJason Evans 			itismychild(parent, child);
14380384fff8SJason Evans 		}
14390384fff8SJason Evans 	}
14400384fff8SJason Evans 	recursed = 0;
14410384fff8SJason Evans 	witness_levelall();
14420384fff8SJason Evans 	return (0);
14430384fff8SJason Evans }
14440384fff8SJason Evans 
14450384fff8SJason Evans static void
1446606f8eb2SJohn Baldwin removechild(struct witness *parent, struct witness *child)
14470384fff8SJason Evans {
1448606f8eb2SJohn Baldwin 	struct witness *w, *w1;
14490384fff8SJason Evans 	int i;
14500384fff8SJason Evans 
14510384fff8SJason Evans 	for (w = parent; w != NULL; w = w->w_morechildren)
14520384fff8SJason Evans 		for (i = 0; i < w->w_childcnt; i++)
14530384fff8SJason Evans 			if (w->w_children[i] == child)
14540384fff8SJason Evans 				goto found;
14550384fff8SJason Evans 	return;
14560384fff8SJason Evans found:
14570384fff8SJason Evans 	for (w1 = w; w1->w_morechildren != NULL; w1 = w1->w_morechildren)
14580384fff8SJason Evans 		continue;
14590384fff8SJason Evans 	w->w_children[i] = w1->w_children[--w1->w_childcnt];
146036412d79SJohn Baldwin 	MPASS(w->w_children[i] != NULL);
14610384fff8SJason Evans 
14620384fff8SJason Evans 	if (w1->w_childcnt != 0)
14630384fff8SJason Evans 		return;
14640384fff8SJason Evans 
14650384fff8SJason Evans 	if (w1 == parent)
14660384fff8SJason Evans 		return;
14670384fff8SJason Evans 	for (w = parent; w->w_morechildren != w1; w = w->w_morechildren)
14680384fff8SJason Evans 		continue;
14690384fff8SJason Evans 	w->w_morechildren = 0;
14700384fff8SJason Evans 	witness_free(w1);
14710384fff8SJason Evans }
14720384fff8SJason Evans 
14730384fff8SJason Evans static int
1474606f8eb2SJohn Baldwin isitmychild(struct witness *parent, struct witness *child)
14750384fff8SJason Evans {
1476606f8eb2SJohn Baldwin 	struct witness *w;
14770384fff8SJason Evans 	int i;
14780384fff8SJason Evans 
14790384fff8SJason Evans 	for (w = parent; w != NULL; w = w->w_morechildren) {
14800384fff8SJason Evans 		for (i = 0; i < w->w_childcnt; i++) {
14810384fff8SJason Evans 			if (w->w_children[i] == child)
14820384fff8SJason Evans 				return (1);
14830384fff8SJason Evans 		}
14840384fff8SJason Evans 	}
14850384fff8SJason Evans 	return (0);
14860384fff8SJason Evans }
14870384fff8SJason Evans 
14880384fff8SJason Evans static int
1489606f8eb2SJohn Baldwin isitmydescendant(struct witness *parent, struct witness *child)
14900384fff8SJason Evans {
1491606f8eb2SJohn Baldwin 	struct witness *w;
14920384fff8SJason Evans 	int i;
14930384fff8SJason Evans 	int j;
14940384fff8SJason Evans 
14950384fff8SJason Evans 	for (j = 0, w = parent; w != NULL; w = w->w_morechildren, j++) {
149636412d79SJohn Baldwin 		MPASS(j < 1000);
14970384fff8SJason Evans 		for (i = 0; i < w->w_childcnt; i++) {
14980384fff8SJason Evans 			if (w->w_children[i] == child)
14990384fff8SJason Evans 				return (1);
15000384fff8SJason Evans 		}
15010384fff8SJason Evans 		for (i = 0; i < w->w_childcnt; i++) {
15020384fff8SJason Evans 			if (isitmydescendant(w->w_children[i], child))
15030384fff8SJason Evans 				return (1);
15040384fff8SJason Evans 		}
15050384fff8SJason Evans 	}
15060384fff8SJason Evans 	return (0);
15070384fff8SJason Evans }
15080384fff8SJason Evans 
15090384fff8SJason Evans void
15100384fff8SJason Evans witness_levelall (void)
15110384fff8SJason Evans {
1512606f8eb2SJohn Baldwin 	struct witness *w, *w1;
15130384fff8SJason Evans 
15140384fff8SJason Evans 	for (w = w_all; w; w = w->w_next)
151508812b39SBosko Milekic 		if (!(w->w_spin))
15160384fff8SJason Evans 			w->w_level = 0;
15170384fff8SJason Evans 	for (w = w_all; w; w = w->w_next) {
15180384fff8SJason Evans 		if (w->w_spin)
15190384fff8SJason Evans 			continue;
15200384fff8SJason Evans 		for (w1 = w_all; w1; w1 = w1->w_next) {
15210384fff8SJason Evans 			if (isitmychild(w1, w))
15220384fff8SJason Evans 				break;
15230384fff8SJason Evans 		}
15240384fff8SJason Evans 		if (w1 != NULL)
15250384fff8SJason Evans 			continue;
15260384fff8SJason Evans 		witness_leveldescendents(w, 0);
15270384fff8SJason Evans 	}
15280384fff8SJason Evans }
15290384fff8SJason Evans 
15300384fff8SJason Evans static void
1531606f8eb2SJohn Baldwin witness_leveldescendents(struct witness *parent, int level)
15320384fff8SJason Evans {
15330384fff8SJason Evans 	int i;
1534606f8eb2SJohn Baldwin 	struct witness *w;
15350384fff8SJason Evans 
15360384fff8SJason Evans 	if (parent->w_level < level)
15370384fff8SJason Evans 		parent->w_level = level;
15380384fff8SJason Evans 	level++;
15390384fff8SJason Evans 	for (w = parent; w != NULL; w = w->w_morechildren)
15400384fff8SJason Evans 		for (i = 0; i < w->w_childcnt; i++)
15410384fff8SJason Evans 			witness_leveldescendents(w->w_children[i], level);
15420384fff8SJason Evans }
15430384fff8SJason Evans 
15440384fff8SJason Evans static void
1545606f8eb2SJohn Baldwin witness_displaydescendants(void(*prnt)(const char *fmt, ...),
1546606f8eb2SJohn Baldwin 			   struct witness *parent)
15470384fff8SJason Evans {
1548606f8eb2SJohn Baldwin 	struct witness *w;
15490384fff8SJason Evans 	int i;
1550e910ba59SJohn Baldwin 	int level;
1551e910ba59SJohn Baldwin 
1552e910ba59SJohn Baldwin 	level = parent->w_spin ? ffs(parent->w_level) : parent->w_level;
15530384fff8SJason Evans 
15540384fff8SJason Evans 	prnt("%d", level);
15550384fff8SJason Evans 	if (level < 10)
15560384fff8SJason Evans 		prnt(" ");
15570384fff8SJason Evans 	for (i = 0; i < level; i++)
15580384fff8SJason Evans 		prnt(" ");
15590384fff8SJason Evans 	prnt("%s", parent->w_description);
1560e910ba59SJohn Baldwin 	if (parent->w_file != NULL)
1561e910ba59SJohn Baldwin 		prnt(" -- last acquired @ %s:%d\n", parent->w_file,
1562e910ba59SJohn Baldwin 		    parent->w_line);
15630384fff8SJason Evans 
15640384fff8SJason Evans 	for (w = parent; w != NULL; w = w->w_morechildren)
15650384fff8SJason Evans 		for (i = 0; i < w->w_childcnt; i++)
15660384fff8SJason Evans 			    witness_displaydescendants(prnt, w->w_children[i]);
15670384fff8SJason Evans     }
15680384fff8SJason Evans 
15690384fff8SJason Evans static int
1570606f8eb2SJohn Baldwin dup_ok(struct witness *w)
15710384fff8SJason Evans {
15720384fff8SJason Evans 	char **dup;
15730384fff8SJason Evans 
15740384fff8SJason Evans 	for (dup = dup_list; *dup!= NULL; dup++)
15750384fff8SJason Evans 		if (strcmp(w->w_description, *dup) == 0)
15760384fff8SJason Evans 			return (1);
15770384fff8SJason Evans 	return (0);
15780384fff8SJason Evans }
15790384fff8SJason Evans 
15800384fff8SJason Evans static int
1581606f8eb2SJohn Baldwin blessed(struct witness *w1, struct witness *w2)
15820384fff8SJason Evans {
15830384fff8SJason Evans 	int i;
1584606f8eb2SJohn Baldwin 	struct witness_blessed *b;
15850384fff8SJason Evans 
15860384fff8SJason Evans 	for (i = 0; i < blessed_count; i++) {
15870384fff8SJason Evans 		b = &blessed_list[i];
15880384fff8SJason Evans 		if (strcmp(w1->w_description, b->b_lock1) == 0) {
15890384fff8SJason Evans 			if (strcmp(w2->w_description, b->b_lock2) == 0)
15900384fff8SJason Evans 				return (1);
15910384fff8SJason Evans 			continue;
15920384fff8SJason Evans 		}
15930384fff8SJason Evans 		if (strcmp(w1->w_description, b->b_lock2) == 0)
15940384fff8SJason Evans 			if (strcmp(w2->w_description, b->b_lock1) == 0)
15950384fff8SJason Evans 				return (1);
15960384fff8SJason Evans 	}
15970384fff8SJason Evans 	return (0);
15980384fff8SJason Evans }
15990384fff8SJason Evans 
1600606f8eb2SJohn Baldwin static struct witness *
16010384fff8SJason Evans witness_get()
16020384fff8SJason Evans {
1603606f8eb2SJohn Baldwin 	struct witness *w;
16040384fff8SJason Evans 
16050384fff8SJason Evans 	if ((w = w_free) == NULL) {
16060384fff8SJason Evans 		witness_dead = 1;
16079ed346baSBosko Milekic 		mtx_unlock_spin_flags(&w_mtx, MTX_QUIET);
16080384fff8SJason Evans 		printf("witness exhausted\n");
16090384fff8SJason Evans 		return (NULL);
16100384fff8SJason Evans 	}
16110384fff8SJason Evans 	w_free = w->w_next;
16120384fff8SJason Evans 	bzero(w, sizeof(*w));
16130384fff8SJason Evans 	return (w);
16140384fff8SJason Evans }
16150384fff8SJason Evans 
16160384fff8SJason Evans static void
1617606f8eb2SJohn Baldwin witness_free(struct witness *w)
16180384fff8SJason Evans {
16190384fff8SJason Evans 	w->w_next = w_free;
16200384fff8SJason Evans 	w_free = w;
16210384fff8SJason Evans }
16220384fff8SJason Evans 
162392cf772dSJake Burkholder int
16240384fff8SJason Evans witness_list(struct proc *p)
16250384fff8SJason Evans {
1626606f8eb2SJohn Baldwin 	struct mtx *m;
162792cf772dSJake Burkholder 	int nheld;
16280384fff8SJason Evans 
1629d1c1b841SJason Evans 	KASSERT(!witness_cold, ("%s: witness_cold\n", __FUNCTION__));
163092cf772dSJake Burkholder 	nheld = 0;
1631e910ba59SJohn Baldwin 	LIST_FOREACH(m, &p->p_heldmtx, mtx_held) {
16320384fff8SJason Evans 		printf("\t\"%s\" (%p) locked at %s:%d\n",
16330384fff8SJason Evans 		    m->mtx_description, m,
16340384fff8SJason Evans 		    m->mtx_witness->w_file, m->mtx_witness->w_line);
163592cf772dSJake Burkholder 		nheld++;
16360384fff8SJason Evans 	}
163792cf772dSJake Burkholder 
163892cf772dSJake Burkholder 	return (nheld);
16390384fff8SJason Evans }
16400384fff8SJason Evans 
1641d38b8dbfSJohn Baldwin #ifdef DDB
1642d38b8dbfSJohn Baldwin 
1643e910ba59SJohn Baldwin DB_SHOW_COMMAND(mutexes, db_witness_list)
1644d38b8dbfSJohn Baldwin {
1645d38b8dbfSJohn Baldwin 
1646d38b8dbfSJohn Baldwin 	witness_list(CURPROC);
1647d38b8dbfSJohn Baldwin }
1648d38b8dbfSJohn Baldwin 
1649e910ba59SJohn Baldwin DB_SHOW_COMMAND(witness, db_witness_display)
1650e910ba59SJohn Baldwin {
1651e910ba59SJohn Baldwin 
1652e910ba59SJohn Baldwin 	witness_display(db_printf);
1653e910ba59SJohn Baldwin }
1654d38b8dbfSJohn Baldwin #endif
1655d38b8dbfSJohn Baldwin 
16560384fff8SJason Evans void
1657606f8eb2SJohn Baldwin witness_save(struct mtx *m, const char **filep, int *linep)
16580384fff8SJason Evans {
1659d1c1b841SJason Evans 
1660d1c1b841SJason Evans 	KASSERT(!witness_cold, ("%s: witness_cold\n", __FUNCTION__));
16610cde2e34SJason Evans 	if (m->mtx_witness == NULL)
16620cde2e34SJason Evans 		return;
16630cde2e34SJason Evans 
16640384fff8SJason Evans 	*filep = m->mtx_witness->w_file;
16650384fff8SJason Evans 	*linep = m->mtx_witness->w_line;
16660384fff8SJason Evans }
16670384fff8SJason Evans 
16680384fff8SJason Evans void
1669606f8eb2SJohn Baldwin witness_restore(struct mtx *m, const char *file, int line)
16700384fff8SJason Evans {
1671d1c1b841SJason Evans 
1672d1c1b841SJason Evans 	KASSERT(!witness_cold, ("%s: witness_cold\n", __FUNCTION__));
16730cde2e34SJason Evans 	if (m->mtx_witness == NULL)
16740cde2e34SJason Evans 		return;
16750cde2e34SJason Evans 
16760384fff8SJason Evans 	m->mtx_witness->w_file = file;
16770384fff8SJason Evans 	m->mtx_witness->w_line = line;
16780384fff8SJason Evans }
16790384fff8SJason Evans 
16806936206eSJohn Baldwin #endif	/* WITNESS */
1681