xref: /freebsd/sys/kern/kern_lock.c (revision d7a7e17968db9bf1510a8b0915e20e6c7f3b9178)
19454b2d8SWarner Losh /*-
253bf4bb2SPeter Wemm  * Copyright (c) 1995
353bf4bb2SPeter Wemm  *	The Regents of the University of California.  All rights reserved.
453bf4bb2SPeter Wemm  *
503e9c6c1SJohn Dyson  * Copyright (C) 1997
603e9c6c1SJohn Dyson  *	John S. Dyson.  All rights reserved.
703e9c6c1SJohn Dyson  *
853bf4bb2SPeter Wemm  * This code contains ideas from software contributed to Berkeley by
953bf4bb2SPeter Wemm  * Avadis Tevanian, Jr., Michael Wayne Young, and the Mach Operating
1053bf4bb2SPeter Wemm  * System project at Carnegie-Mellon University.
1153bf4bb2SPeter Wemm  *
1253bf4bb2SPeter Wemm  * Redistribution and use in source and binary forms, with or without
1353bf4bb2SPeter Wemm  * modification, are permitted provided that the following conditions
1453bf4bb2SPeter Wemm  * are met:
1553bf4bb2SPeter Wemm  * 1. Redistributions of source code must retain the above copyright
1653bf4bb2SPeter Wemm  *    notice, this list of conditions and the following disclaimer.
1753bf4bb2SPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
1853bf4bb2SPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
1953bf4bb2SPeter Wemm  *    documentation and/or other materials provided with the distribution.
2053bf4bb2SPeter Wemm  * 3. All advertising materials mentioning features or use of this software
2153bf4bb2SPeter Wemm  *    must display the following acknowledgement:
2253bf4bb2SPeter Wemm  *	This product includes software developed by the University of
2353bf4bb2SPeter Wemm  *	California, Berkeley and its contributors.
2453bf4bb2SPeter Wemm  * 4. Neither the name of the University nor the names of its contributors
2553bf4bb2SPeter Wemm  *    may be used to endorse or promote products derived from this software
2653bf4bb2SPeter Wemm  *    without specific prior written permission.
2753bf4bb2SPeter Wemm  *
2853bf4bb2SPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2953bf4bb2SPeter Wemm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3053bf4bb2SPeter Wemm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3153bf4bb2SPeter Wemm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3253bf4bb2SPeter Wemm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3353bf4bb2SPeter Wemm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3453bf4bb2SPeter Wemm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3553bf4bb2SPeter Wemm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3653bf4bb2SPeter Wemm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3753bf4bb2SPeter Wemm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3853bf4bb2SPeter Wemm  * SUCH DAMAGE.
3953bf4bb2SPeter Wemm  *
4053bf4bb2SPeter Wemm  *	@(#)kern_lock.c	8.18 (Berkeley) 5/21/95
4153bf4bb2SPeter Wemm  */
4253bf4bb2SPeter Wemm 
43677b542eSDavid E. O'Brien #include <sys/cdefs.h>
44677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
45677b542eSDavid E. O'Brien 
46be6847d7SJohn Baldwin #include "opt_ddb.h"
477c0435b9SKip Macy #include "opt_global.h"
48be6847d7SJohn Baldwin 
4953bf4bb2SPeter Wemm #include <sys/param.h>
50c30bf5c3SRobert Watson #include <sys/kdb.h>
519722d88fSJason Evans #include <sys/kernel.h>
5261d80e90SJohn Baldwin #include <sys/ktr.h>
5353bf4bb2SPeter Wemm #include <sys/lock.h>
548302d183SBruce Evans #include <sys/lockmgr.h>
55d8881ca3SJohn Baldwin #include <sys/mutex.h>
568302d183SBruce Evans #include <sys/proc.h>
574bdb9b11SPeter Wemm #include <sys/systm.h>
587c0435b9SKip Macy #include <sys/lock_profile.h>
59e8ddb61dSJeff Roberson #ifdef DEBUG_LOCKS
60e8ddb61dSJeff Roberson #include <sys/stack.h>
61e8ddb61dSJeff Roberson #endif
6253bf4bb2SPeter Wemm 
63f9721b43SAttilio Rao static void	assert_lockmgr(struct lock_object *lock, int what);
64be6847d7SJohn Baldwin #ifdef DDB
65be6847d7SJohn Baldwin #include <ddb/ddb.h>
6661bd5e21SKip Macy static void	db_show_lockmgr(struct lock_object *lock);
67be6847d7SJohn Baldwin #endif
686e21afd4SJohn Baldwin static void	lock_lockmgr(struct lock_object *lock, int how);
696e21afd4SJohn Baldwin static int	unlock_lockmgr(struct lock_object *lock);
7061bd5e21SKip Macy 
7161bd5e21SKip Macy struct lock_class lock_class_lockmgr = {
723ff6d229SJohn Baldwin 	.lc_name = "lockmgr",
733ff6d229SJohn Baldwin 	.lc_flags = LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE | LC_UPGRADABLE,
74f9721b43SAttilio Rao 	.lc_assert = assert_lockmgr,
7561bd5e21SKip Macy #ifdef DDB
766e21afd4SJohn Baldwin 	.lc_ddb_show = db_show_lockmgr,
7761bd5e21SKip Macy #endif
786e21afd4SJohn Baldwin 	.lc_lock = lock_lockmgr,
796e21afd4SJohn Baldwin 	.lc_unlock = unlock_lockmgr,
8061bd5e21SKip Macy };
8161bd5e21SKip Macy 
8253bf4bb2SPeter Wemm /*
8353bf4bb2SPeter Wemm  * Locking primitives implementation.
8453bf4bb2SPeter Wemm  * Locks provide shared/exclusive sychronization.
8553bf4bb2SPeter Wemm  */
8653bf4bb2SPeter Wemm 
876e21afd4SJohn Baldwin void
88f9721b43SAttilio Rao assert_lockmgr(struct lock_object *lock, int what)
89f9721b43SAttilio Rao {
90f9721b43SAttilio Rao 
91f9721b43SAttilio Rao 	panic("lockmgr locks do not support assertions");
92f9721b43SAttilio Rao }
93f9721b43SAttilio Rao 
94f9721b43SAttilio Rao void
956e21afd4SJohn Baldwin lock_lockmgr(struct lock_object *lock, int how)
966e21afd4SJohn Baldwin {
976e21afd4SJohn Baldwin 
986e21afd4SJohn Baldwin 	panic("lockmgr locks do not support sleep interlocking");
996e21afd4SJohn Baldwin }
1006e21afd4SJohn Baldwin 
1016e21afd4SJohn Baldwin int
1026e21afd4SJohn Baldwin unlock_lockmgr(struct lock_object *lock)
1036e21afd4SJohn Baldwin {
1046e21afd4SJohn Baldwin 
1056e21afd4SJohn Baldwin 	panic("lockmgr locks do not support sleep interlocking");
1066e21afd4SJohn Baldwin }
1076e21afd4SJohn Baldwin 
108d7a7e179SAttilio Rao #define	COUNT(td, x)	((td)->td_locks += (x))
10999448ed1SJohn Dyson #define LK_ALL (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE | \
11099448ed1SJohn Dyson 	LK_SHARE_NONZERO | LK_WAIT_NONZERO)
11199448ed1SJohn Dyson 
112fe68a916SKip Macy static int acquire(struct lock **lkpp, int extflags, int wanted, int *contested, uint64_t *waittime);
11399448ed1SJohn Dyson static int acquiredrain(struct lock *lkp, int extflags) ;
11403e9c6c1SJohn Dyson 
115a96ab770SJeff Roberson static __inline void
116f158df07SJeff Roberson sharelock(struct thread *td, struct lock *lkp, int incr) {
11703e9c6c1SJohn Dyson 	lkp->lk_flags |= LK_SHARE_NONZERO;
11803e9c6c1SJohn Dyson 	lkp->lk_sharecount += incr;
119f158df07SJeff Roberson 	COUNT(td, incr);
12003e9c6c1SJohn Dyson }
12103e9c6c1SJohn Dyson 
122a96ab770SJeff Roberson static __inline void
123f158df07SJeff Roberson shareunlock(struct thread *td, struct lock *lkp, int decr) {
124219cbf59SEivind Eklund 
1255526d2d9SEivind Eklund 	KASSERT(lkp->lk_sharecount >= decr, ("shareunlock: count < decr"));
12603e9c6c1SJohn Dyson 
127f158df07SJeff Roberson 	COUNT(td, -decr);
1289b2e5badSJohn Dyson 	if (lkp->lk_sharecount == decr) {
12903e9c6c1SJohn Dyson 		lkp->lk_flags &= ~LK_SHARE_NONZERO;
1309b2e5badSJohn Dyson 		if (lkp->lk_flags & (LK_WANT_UPGRADE | LK_WANT_EXCL)) {
1319b2e5badSJohn Dyson 			wakeup(lkp);
1329b2e5badSJohn Dyson 		}
1339b2e5badSJohn Dyson 		lkp->lk_sharecount = 0;
1349b2e5badSJohn Dyson 	} else {
1359b2e5badSJohn Dyson 		lkp->lk_sharecount -= decr;
1369b2e5badSJohn Dyson 	}
13703e9c6c1SJohn Dyson }
13803e9c6c1SJohn Dyson 
13903e9c6c1SJohn Dyson static int
140fe68a916SKip Macy acquire(struct lock **lkpp, int extflags, int wanted, int *contested, uint64_t *waittime)
14141bd6c15SJeff Roberson {
142c6964d3bSKirk McKusick 	struct lock *lkp = *lkpp;
14320728d8fSJeff Roberson 	int error;
144c06394f5SJohn Baldwin 	CTR3(KTR_LOCK,
145ff381670SRobert Watson 	    "acquire(): lkp == %p, extflags == 0x%x, wanted == 0x%x",
146a18b1f1dSJason Evans 	    lkp, extflags, wanted);
147a18b1f1dSJason Evans 
14820728d8fSJeff Roberson 	if ((extflags & LK_NOWAIT) && (lkp->lk_flags & wanted))
14903e9c6c1SJohn Dyson 		return EBUSY;
15020728d8fSJeff Roberson 	error = 0;
151fe68a916SKip Macy 	if ((lkp->lk_flags & wanted) != 0)
152fe68a916SKip Macy 		lock_profile_obtain_lock_failed(&lkp->lk_object, contested, waittime);
153fe68a916SKip Macy 
15403e9c6c1SJohn Dyson 	while ((lkp->lk_flags & wanted) != 0) {
15520728d8fSJeff Roberson 		CTR2(KTR_LOCK,
15620728d8fSJeff Roberson 		    "acquire(): lkp == %p, lk_flags == 0x%x sleeping",
15720728d8fSJeff Roberson 		    lkp, lkp->lk_flags);
15803e9c6c1SJohn Dyson 		lkp->lk_flags |= LK_WAIT_NONZERO;
15903e9c6c1SJohn Dyson 		lkp->lk_waitcount++;
16096fde7daSJake Burkholder 		error = msleep(lkp, lkp->lk_interlock, lkp->lk_prio,
16123b59018SMatthew Dillon 		    lkp->lk_wmesg,
16223b59018SMatthew Dillon 		    ((extflags & LK_TIMELOCK) ? lkp->lk_timo : 0));
1639b2e5badSJohn Dyson 		lkp->lk_waitcount--;
16420728d8fSJeff Roberson 		if (lkp->lk_waitcount == 0)
16520728d8fSJeff Roberson 			lkp->lk_flags &= ~LK_WAIT_NONZERO;
16620728d8fSJeff Roberson 		if (error)
16720728d8fSJeff Roberson 			break;
16803e9c6c1SJohn Dyson 		if (extflags & LK_SLEEPFAIL) {
16920728d8fSJeff Roberson 			error = ENOLCK;
17020728d8fSJeff Roberson 			break;
17103e9c6c1SJohn Dyson 		}
172c6964d3bSKirk McKusick 		if (lkp->lk_newlock != NULL) {
173c6964d3bSKirk McKusick 			mtx_lock(lkp->lk_newlock->lk_interlock);
174c6964d3bSKirk McKusick 			mtx_unlock(lkp->lk_interlock);
175c6964d3bSKirk McKusick 			if (lkp->lk_waitcount == 0)
176c6964d3bSKirk McKusick 				wakeup((void *)(&lkp->lk_newlock));
177c6964d3bSKirk McKusick 			*lkpp = lkp = lkp->lk_newlock;
178c6964d3bSKirk McKusick 		}
17903e9c6c1SJohn Dyson 	}
18020728d8fSJeff Roberson 	mtx_assert(lkp->lk_interlock, MA_OWNED);
18120728d8fSJeff Roberson 	return (error);
18203e9c6c1SJohn Dyson }
18303e9c6c1SJohn Dyson 
18453bf4bb2SPeter Wemm /*
18553bf4bb2SPeter Wemm  * Set, change, or release a lock.
18653bf4bb2SPeter Wemm  *
18753bf4bb2SPeter Wemm  * Shared requests increment the shared count. Exclusive requests set the
18853bf4bb2SPeter Wemm  * LK_WANT_EXCL flag (preventing further shared locks), and wait for already
18953bf4bb2SPeter Wemm  * accepted shared locks and shared-to-exclusive upgrades to go away.
19053bf4bb2SPeter Wemm  */
19153bf4bb2SPeter Wemm int
192ab2dab16SJohn Baldwin _lockmgr(struct lock *lkp, u_int flags, struct mtx *interlkp,
1937c0435b9SKip Macy 	 struct thread *td, char *file, int line)
1947c0435b9SKip Macy 
19553bf4bb2SPeter Wemm {
19653bf4bb2SPeter Wemm 	int error;
197635962afSJohn Baldwin 	int extflags, lockflags;
198fe68a916SKip Macy 	int contested = 0;
199fe68a916SKip Macy 	uint64_t waitstart = 0;
20053bf4bb2SPeter Wemm 
2017a1d78faSAttilio Rao 	/*
202d7a7e179SAttilio Rao 	 * Lock owner can only be curthread in order to have a deadlock
203d7a7e179SAttilio Rao 	 * free implementation of the primitive.
2047a1d78faSAttilio Rao 	 */
205d7a7e179SAttilio Rao 	KASSERT(td == curthread,
206d7a7e179SAttilio Rao 	    ("lockmgr: owner thread (%p) cannot differ from curthread", td));
2077a1d78faSAttilio Rao 
20853bf4bb2SPeter Wemm 	error = 0;
20903e9c6c1SJohn Dyson 
21017661e5aSJeff Roberson 	if ((flags & LK_INTERNAL) == 0)
2119ed346baSBosko Milekic 		mtx_lock(lkp->lk_interlock);
21241bd6c15SJeff Roberson 	CTR6(KTR_LOCK,
21341bd6c15SJeff Roberson 	    "lockmgr(): lkp == %p (lk_wmesg == \"%s\"), owner == %p, exclusivecount == %d, flags == 0x%x, "
21441bd6c15SJeff Roberson 	    "td == %p", lkp, lkp->lk_wmesg, lkp->lk_lockholder,
21541bd6c15SJeff Roberson 	    lkp->lk_exclusivecount, flags, td);
216e8ddb61dSJeff Roberson #ifdef DEBUG_LOCKS
217e8ddb61dSJeff Roberson 	{
218e8ddb61dSJeff Roberson 		struct stack stack; /* XXX */
219e8ddb61dSJeff Roberson 		stack_save(&stack);
220e37a4994SPawel Jakub Dawidek 		CTRSTACK(KTR_LOCK, &stack, 0, 1);
221e8ddb61dSJeff Roberson 	}
22241bd6c15SJeff Roberson #endif
22341bd6c15SJeff Roberson 
22498689e1eSAlfred Perlstein 	if (flags & LK_INTERLOCK) {
2256157b69fSAlfred Perlstein 		mtx_assert(interlkp, MA_OWNED | MA_NOTRECURSED);
2269ed346baSBosko Milekic 		mtx_unlock(interlkp);
22798689e1eSAlfred Perlstein 	}
22803e9c6c1SJohn Dyson 
22917661e5aSJeff Roberson 	if ((flags & (LK_NOWAIT|LK_RELEASE)) == 0)
23026306795SJohn Baldwin 		WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK,
231aa89d8cdSJohn Baldwin 		    &lkp->lk_interlock->lock_object,
23226306795SJohn Baldwin 		    "Acquiring lockmgr lock \"%s\"", lkp->lk_wmesg);
23317661e5aSJeff Roberson 
2343f085c22SJohn Baldwin 	if (panicstr != NULL) {
2353f085c22SJohn Baldwin 		mtx_unlock(lkp->lk_interlock);
2363f085c22SJohn Baldwin 		return (0);
2373f085c22SJohn Baldwin 	}
238c4c0ec5bSJeff Roberson 	if ((lkp->lk_flags & LK_NOSHARE) &&
239c4c0ec5bSJeff Roberson 	    (flags & LK_TYPE_MASK) == LK_SHARED) {
240c4c0ec5bSJeff Roberson 		flags &= ~LK_TYPE_MASK;
241c4c0ec5bSJeff Roberson 		flags |= LK_EXCLUSIVE;
242c4c0ec5bSJeff Roberson 	}
24353bf4bb2SPeter Wemm 	extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK;
24453bf4bb2SPeter Wemm 
24553bf4bb2SPeter Wemm 	switch (flags & LK_TYPE_MASK) {
24653bf4bb2SPeter Wemm 
24753bf4bb2SPeter Wemm 	case LK_SHARED:
248beef8a36SJulian Elischer 		/*
249beef8a36SJulian Elischer 		 * If we are not the exclusive lock holder, we have to block
250beef8a36SJulian Elischer 		 * while there is an exclusive lock holder or while an
251beef8a36SJulian Elischer 		 * exclusive lock request or upgrade request is in progress.
252beef8a36SJulian Elischer 		 *
253fa2a4d05STim J. Robbins 		 * However, if TDP_DEADLKTREAT is set, we override exclusive
254beef8a36SJulian Elischer 		 * lock requests or upgrade requests ( but not the exclusive
255beef8a36SJulian Elischer 		 * lock itself ).
256beef8a36SJulian Elischer 		 */
257d7a7e179SAttilio Rao 		if (lkp->lk_lockholder != td) {
258635962afSJohn Baldwin 			lockflags = LK_HAVE_EXCL;
259fa2a4d05STim J. Robbins 			if (td != NULL && !(td->td_pflags & TDP_DEADLKTREAT))
260bce98419SJohn Baldwin 				lockflags |= LK_WANT_EXCL | LK_WANT_UPGRADE;
261fe68a916SKip Macy 			error = acquire(&lkp, extflags, lockflags, &contested, &waitstart);
26253bf4bb2SPeter Wemm 			if (error)
26353bf4bb2SPeter Wemm 				break;
264f158df07SJeff Roberson 			sharelock(td, lkp, 1);
2657c0435b9SKip Macy 			if (lkp->lk_sharecount == 1)
266fe68a916SKip Macy 				lock_profile_obtain_lock_success(&lkp->lk_object, contested, waitstart, file, line);
2677c0435b9SKip Macy 
2687181624aSJeff Roberson #if defined(DEBUG_LOCKS)
2697499fd8dSJeff Roberson 			stack_save(&lkp->lk_stack);
2707181624aSJeff Roberson #endif
27153bf4bb2SPeter Wemm 			break;
27253bf4bb2SPeter Wemm 		}
27353bf4bb2SPeter Wemm 		/*
27453bf4bb2SPeter Wemm 		 * We hold an exclusive lock, so downgrade it to shared.
27553bf4bb2SPeter Wemm 		 * An alternative would be to fail with EDEADLK.
27653bf4bb2SPeter Wemm 		 */
277f158df07SJeff Roberson 		sharelock(td, lkp, 1);
2787c0435b9SKip Macy 		if (lkp->lk_sharecount == 1)
279fe68a916SKip Macy 			lock_profile_obtain_lock_success(&lkp->lk_object, contested, waitstart, file, line);
28093b0017fSPhilippe Charnier 		/* FALLTHROUGH downgrade */
28153bf4bb2SPeter Wemm 
28253bf4bb2SPeter Wemm 	case LK_DOWNGRADE:
283d7a7e179SAttilio Rao 		KASSERT(lkp->lk_lockholder == td && lkp->lk_exclusivecount != 0,
2841375ed7eSAlfred Perlstein 			("lockmgr: not holding exclusive lock "
285822ded67SJulian Elischer 			"(owner thread (%p) != thread (%p), exlcnt (%d) != 0",
286d7a7e179SAttilio Rao 			lkp->lk_lockholder, td, lkp->lk_exclusivecount));
287f158df07SJeff Roberson 		sharelock(td, lkp, lkp->lk_exclusivecount);
288f158df07SJeff Roberson 		COUNT(td, -lkp->lk_exclusivecount);
28953bf4bb2SPeter Wemm 		lkp->lk_exclusivecount = 0;
29053bf4bb2SPeter Wemm 		lkp->lk_flags &= ~LK_HAVE_EXCL;
2916f8132a8SJulian Elischer 		lkp->lk_lockholder = LK_NOPROC;
29253bf4bb2SPeter Wemm 		if (lkp->lk_waitcount)
29353bf4bb2SPeter Wemm 			wakeup((void *)lkp);
29453bf4bb2SPeter Wemm 		break;
29553bf4bb2SPeter Wemm 
29653bf4bb2SPeter Wemm 	case LK_UPGRADE:
29753bf4bb2SPeter Wemm 		/*
29853bf4bb2SPeter Wemm 		 * Upgrade a shared lock to an exclusive one. If another
29953bf4bb2SPeter Wemm 		 * shared lock has already requested an upgrade to an
30053bf4bb2SPeter Wemm 		 * exclusive lock, our shared lock is released and an
30153bf4bb2SPeter Wemm 		 * exclusive lock is requested (which will be granted
30253bf4bb2SPeter Wemm 		 * after the upgrade). If we return an error, the file
30353bf4bb2SPeter Wemm 		 * will always be unlocked.
30453bf4bb2SPeter Wemm 		 */
305d7a7e179SAttilio Rao 		if (lkp->lk_lockholder == td)
30653bf4bb2SPeter Wemm 			panic("lockmgr: upgrade exclusive lock");
307436901a8SJeff Roberson 		if (lkp->lk_sharecount <= 0)
308436901a8SJeff Roberson 			panic("lockmgr: upgrade without shared");
309f158df07SJeff Roberson 		shareunlock(td, lkp, 1);
3107c0435b9SKip Macy 		if (lkp->lk_sharecount == 0)
3117c0435b9SKip Macy 			lock_profile_release_lock(&lkp->lk_object);
31253bf4bb2SPeter Wemm 		/*
31353bf4bb2SPeter Wemm 		 * If we are just polling, check to see if we will block.
31453bf4bb2SPeter Wemm 		 */
31553bf4bb2SPeter Wemm 		if ((extflags & LK_NOWAIT) &&
31653bf4bb2SPeter Wemm 		    ((lkp->lk_flags & LK_WANT_UPGRADE) ||
31753bf4bb2SPeter Wemm 		     lkp->lk_sharecount > 1)) {
31853bf4bb2SPeter Wemm 			error = EBUSY;
31953bf4bb2SPeter Wemm 			break;
32053bf4bb2SPeter Wemm 		}
32153bf4bb2SPeter Wemm 		if ((lkp->lk_flags & LK_WANT_UPGRADE) == 0) {
32253bf4bb2SPeter Wemm 			/*
32353bf4bb2SPeter Wemm 			 * We are first shared lock to request an upgrade, so
32453bf4bb2SPeter Wemm 			 * request upgrade and wait for the shared count to
32553bf4bb2SPeter Wemm 			 * drop to zero, then take exclusive lock.
32653bf4bb2SPeter Wemm 			 */
32753bf4bb2SPeter Wemm 			lkp->lk_flags |= LK_WANT_UPGRADE;
328fe68a916SKip Macy 			error = acquire(&lkp, extflags, LK_SHARE_NONZERO, &contested, &waitstart);
32953bf4bb2SPeter Wemm 			lkp->lk_flags &= ~LK_WANT_UPGRADE;
3309b2e5badSJohn Dyson 
3314cef6d5aSAlexander Kabaev 			if (error) {
3324cef6d5aSAlexander Kabaev 			         if ((lkp->lk_flags & ( LK_WANT_EXCL | LK_WAIT_NONZERO)) == (LK_WANT_EXCL | LK_WAIT_NONZERO))
3334cef6d5aSAlexander Kabaev 			                   wakeup((void *)lkp);
33453bf4bb2SPeter Wemm 			         break;
3354cef6d5aSAlexander Kabaev 			}
33653bf4bb2SPeter Wemm 			if (lkp->lk_exclusivecount != 0)
33753bf4bb2SPeter Wemm 				panic("lockmgr: non-zero exclusive count");
338d8b8e875SPaul Saab 			lkp->lk_flags |= LK_HAVE_EXCL;
339d7a7e179SAttilio Rao 			lkp->lk_lockholder = td;
34053bf4bb2SPeter Wemm 			lkp->lk_exclusivecount = 1;
341f158df07SJeff Roberson 			COUNT(td, 1);
342fe68a916SKip Macy 			lock_profile_obtain_lock_success(&lkp->lk_object, contested, waitstart, file, line);
34315a1057cSEivind Eklund #if defined(DEBUG_LOCKS)
3447499fd8dSJeff Roberson 			stack_save(&lkp->lk_stack);
34515a1057cSEivind Eklund #endif
34653bf4bb2SPeter Wemm 			break;
34753bf4bb2SPeter Wemm 		}
34853bf4bb2SPeter Wemm 		/*
34953bf4bb2SPeter Wemm 		 * Someone else has requested upgrade. Release our shared
35053bf4bb2SPeter Wemm 		 * lock, awaken upgrade requestor if we are the last shared
35153bf4bb2SPeter Wemm 		 * lock, then request an exclusive lock.
35253bf4bb2SPeter Wemm 		 */
35303e9c6c1SJohn Dyson 		if ( (lkp->lk_flags & (LK_SHARE_NONZERO|LK_WAIT_NONZERO)) ==
35403e9c6c1SJohn Dyson 			LK_WAIT_NONZERO)
35553bf4bb2SPeter Wemm 			wakeup((void *)lkp);
35693b0017fSPhilippe Charnier 		/* FALLTHROUGH exclusive request */
35753bf4bb2SPeter Wemm 
35853bf4bb2SPeter Wemm 	case LK_EXCLUSIVE:
359d7a7e179SAttilio Rao 		if (lkp->lk_lockholder == td) {
36053bf4bb2SPeter Wemm 			/*
36153bf4bb2SPeter Wemm 			 *	Recursive lock.
36253bf4bb2SPeter Wemm 			 */
36333638e93SKirk McKusick 			if ((extflags & (LK_NOWAIT | LK_CANRECURSE)) == 0)
36453bf4bb2SPeter Wemm 				panic("lockmgr: locking against myself");
36533638e93SKirk McKusick 			if ((extflags & LK_CANRECURSE) != 0) {
36653bf4bb2SPeter Wemm 				lkp->lk_exclusivecount++;
367f158df07SJeff Roberson 				COUNT(td, 1);
36853bf4bb2SPeter Wemm 				break;
36953bf4bb2SPeter Wemm 			}
37033638e93SKirk McKusick 		}
37153bf4bb2SPeter Wemm 		/*
37253bf4bb2SPeter Wemm 		 * If we are just polling, check to see if we will sleep.
37353bf4bb2SPeter Wemm 		 */
37403e9c6c1SJohn Dyson 		if ((extflags & LK_NOWAIT) &&
37503e9c6c1SJohn Dyson 		    (lkp->lk_flags & (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE | LK_SHARE_NONZERO))) {
37653bf4bb2SPeter Wemm 			error = EBUSY;
37753bf4bb2SPeter Wemm 			break;
37853bf4bb2SPeter Wemm 		}
37953bf4bb2SPeter Wemm 		/*
38053bf4bb2SPeter Wemm 		 * Try to acquire the want_exclusive flag.
38153bf4bb2SPeter Wemm 		 */
382fe68a916SKip Macy 		error = acquire(&lkp, extflags, (LK_HAVE_EXCL | LK_WANT_EXCL), &contested, &waitstart);
38353bf4bb2SPeter Wemm 		if (error)
38453bf4bb2SPeter Wemm 			break;
38553bf4bb2SPeter Wemm 		lkp->lk_flags |= LK_WANT_EXCL;
38653bf4bb2SPeter Wemm 		/*
38753bf4bb2SPeter Wemm 		 * Wait for shared locks and upgrades to finish.
38853bf4bb2SPeter Wemm 		 */
389fe68a916SKip Macy 		error = acquire(&lkp, extflags, LK_HAVE_EXCL | LK_WANT_UPGRADE | LK_SHARE_NONZERO, &contested, &waitstart);
39053bf4bb2SPeter Wemm 		lkp->lk_flags &= ~LK_WANT_EXCL;
3914cef6d5aSAlexander Kabaev 		if (error) {
3924cef6d5aSAlexander Kabaev 			if (lkp->lk_flags & LK_WAIT_NONZERO)
3934cef6d5aSAlexander Kabaev 			         wakeup((void *)lkp);
39453bf4bb2SPeter Wemm 			break;
3954cef6d5aSAlexander Kabaev 		}
39653bf4bb2SPeter Wemm 		lkp->lk_flags |= LK_HAVE_EXCL;
397d7a7e179SAttilio Rao 		lkp->lk_lockholder = td;
39853bf4bb2SPeter Wemm 		if (lkp->lk_exclusivecount != 0)
39953bf4bb2SPeter Wemm 			panic("lockmgr: non-zero exclusive count");
40053bf4bb2SPeter Wemm 		lkp->lk_exclusivecount = 1;
401f158df07SJeff Roberson 		COUNT(td, 1);
402fe68a916SKip Macy 		lock_profile_obtain_lock_success(&lkp->lk_object, contested, waitstart, file, line);
40315a1057cSEivind Eklund #if defined(DEBUG_LOCKS)
4047499fd8dSJeff Roberson 		stack_save(&lkp->lk_stack);
40515a1057cSEivind Eklund #endif
40653bf4bb2SPeter Wemm 		break;
40753bf4bb2SPeter Wemm 
40853bf4bb2SPeter Wemm 	case LK_RELEASE:
40953bf4bb2SPeter Wemm 		if (lkp->lk_exclusivecount != 0) {
410d7a7e179SAttilio Rao 			if (lkp->lk_lockholder != td &&
411e701df7dSMatthew Dillon 			    lkp->lk_lockholder != LK_KERNPROC) {
412822ded67SJulian Elischer 				panic("lockmgr: thread %p, not %s %p unlocking",
413d7a7e179SAttilio Rao 				    td, "exclusive lock holder",
41453bf4bb2SPeter Wemm 				    lkp->lk_lockholder);
415e701df7dSMatthew Dillon 			}
416f158df07SJeff Roberson 			if (lkp->lk_lockholder != LK_KERNPROC)
417f158df07SJeff Roberson 				COUNT(td, -1);
4189b2e5badSJohn Dyson 			if (lkp->lk_exclusivecount == 1) {
41953bf4bb2SPeter Wemm 				lkp->lk_flags &= ~LK_HAVE_EXCL;
42053bf4bb2SPeter Wemm 				lkp->lk_lockholder = LK_NOPROC;
4219b2e5badSJohn Dyson 				lkp->lk_exclusivecount = 0;
4227c0435b9SKip Macy 				lock_profile_release_lock(&lkp->lk_object);
4239b2e5badSJohn Dyson 			} else {
4249b2e5badSJohn Dyson 				lkp->lk_exclusivecount--;
42553bf4bb2SPeter Wemm 			}
4261b367556SJason Evans 		} else if (lkp->lk_flags & LK_SHARE_NONZERO)
427f158df07SJeff Roberson 			shareunlock(td, lkp, 1);
4281f71de49SSuleiman Souhlal 		else  {
4291f71de49SSuleiman Souhlal 			printf("lockmgr: thread %p unlocking unheld lock\n",
430d7a7e179SAttilio Rao 			    td);
4311f71de49SSuleiman Souhlal 			kdb_backtrace();
4321f71de49SSuleiman Souhlal 		}
4331f71de49SSuleiman Souhlal 
43403e9c6c1SJohn Dyson 		if (lkp->lk_flags & LK_WAIT_NONZERO)
43553bf4bb2SPeter Wemm 			wakeup((void *)lkp);
43653bf4bb2SPeter Wemm 		break;
43753bf4bb2SPeter Wemm 
43853bf4bb2SPeter Wemm 	case LK_DRAIN:
43953bf4bb2SPeter Wemm 		/*
44053bf4bb2SPeter Wemm 		 * Check that we do not already hold the lock, as it can
44153bf4bb2SPeter Wemm 		 * never drain if we do. Unfortunately, we have no way to
44253bf4bb2SPeter Wemm 		 * check for holding a shared lock, but at least we can
44353bf4bb2SPeter Wemm 		 * check for an exclusive one.
44453bf4bb2SPeter Wemm 		 */
445d7a7e179SAttilio Rao 		if (lkp->lk_lockholder == td)
44653bf4bb2SPeter Wemm 			panic("lockmgr: draining against myself");
44703e9c6c1SJohn Dyson 
44803e9c6c1SJohn Dyson 		error = acquiredrain(lkp, extflags);
44903e9c6c1SJohn Dyson 		if (error)
45053bf4bb2SPeter Wemm 			break;
45153bf4bb2SPeter Wemm 		lkp->lk_flags |= LK_DRAINING | LK_HAVE_EXCL;
452d7a7e179SAttilio Rao 		lkp->lk_lockholder = td;
45353bf4bb2SPeter Wemm 		lkp->lk_exclusivecount = 1;
454f158df07SJeff Roberson 		COUNT(td, 1);
45515a1057cSEivind Eklund #if defined(DEBUG_LOCKS)
4567499fd8dSJeff Roberson 		stack_save(&lkp->lk_stack);
45715a1057cSEivind Eklund #endif
45853bf4bb2SPeter Wemm 		break;
45953bf4bb2SPeter Wemm 
46053bf4bb2SPeter Wemm 	default:
4619ed346baSBosko Milekic 		mtx_unlock(lkp->lk_interlock);
46253bf4bb2SPeter Wemm 		panic("lockmgr: unknown locktype request %d",
46353bf4bb2SPeter Wemm 		    flags & LK_TYPE_MASK);
46453bf4bb2SPeter Wemm 		/* NOTREACHED */
46553bf4bb2SPeter Wemm 	}
46603e9c6c1SJohn Dyson 	if ((lkp->lk_flags & LK_WAITDRAIN) &&
46703e9c6c1SJohn Dyson 	    (lkp->lk_flags & (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE |
46803e9c6c1SJohn Dyson 		LK_SHARE_NONZERO | LK_WAIT_NONZERO)) == 0) {
46953bf4bb2SPeter Wemm 		lkp->lk_flags &= ~LK_WAITDRAIN;
47053bf4bb2SPeter Wemm 		wakeup((void *)&lkp->lk_flags);
47153bf4bb2SPeter Wemm 	}
4729ed346baSBosko Milekic 	mtx_unlock(lkp->lk_interlock);
47353bf4bb2SPeter Wemm 	return (error);
47453bf4bb2SPeter Wemm }
47553bf4bb2SPeter Wemm 
47699448ed1SJohn Dyson static int
47799448ed1SJohn Dyson acquiredrain(struct lock *lkp, int extflags) {
47899448ed1SJohn Dyson 	int error;
47999448ed1SJohn Dyson 
48099448ed1SJohn Dyson 	if ((extflags & LK_NOWAIT) && (lkp->lk_flags & LK_ALL)) {
48199448ed1SJohn Dyson 		return EBUSY;
48299448ed1SJohn Dyson 	}
48399448ed1SJohn Dyson 	while (lkp->lk_flags & LK_ALL) {
48499448ed1SJohn Dyson 		lkp->lk_flags |= LK_WAITDRAIN;
48596fde7daSJake Burkholder 		error = msleep(&lkp->lk_flags, lkp->lk_interlock, lkp->lk_prio,
48623b59018SMatthew Dillon 			lkp->lk_wmesg,
48723b59018SMatthew Dillon 			((extflags & LK_TIMELOCK) ? lkp->lk_timo : 0));
48899448ed1SJohn Dyson 		if (error)
48999448ed1SJohn Dyson 			return error;
49099448ed1SJohn Dyson 		if (extflags & LK_SLEEPFAIL) {
49199448ed1SJohn Dyson 			return ENOLCK;
49299448ed1SJohn Dyson 		}
49399448ed1SJohn Dyson 	}
49499448ed1SJohn Dyson 	return 0;
49599448ed1SJohn Dyson }
49699448ed1SJohn Dyson 
49799448ed1SJohn Dyson /*
49899448ed1SJohn Dyson  * Initialize a lock; required before use.
49999448ed1SJohn Dyson  */
50099448ed1SJohn Dyson void
50199448ed1SJohn Dyson lockinit(lkp, prio, wmesg, timo, flags)
50299448ed1SJohn Dyson 	struct lock *lkp;
50399448ed1SJohn Dyson 	int prio;
50404858e7eSEivind Eklund 	const char *wmesg;
50599448ed1SJohn Dyson 	int timo;
50699448ed1SJohn Dyson 	int flags;
50799448ed1SJohn Dyson {
508c06394f5SJohn Baldwin 	CTR5(KTR_LOCK, "lockinit(): lkp == %p, prio == %d, wmesg == \"%s\", "
509a18b1f1dSJason Evans 	    "timo == %d, flags = 0x%x\n", lkp, prio, wmesg, timo, flags);
51099448ed1SJohn Dyson 
511857d9c60SDon Lewis 	lkp->lk_interlock = mtx_pool_alloc(mtxpool_lockbuilder);
5129722d88fSJason Evans 	lkp->lk_flags = (flags & LK_EXTFLG_MASK);
51399448ed1SJohn Dyson 	lkp->lk_sharecount = 0;
51499448ed1SJohn Dyson 	lkp->lk_waitcount = 0;
51599448ed1SJohn Dyson 	lkp->lk_exclusivecount = 0;
51699448ed1SJohn Dyson 	lkp->lk_prio = prio;
51799448ed1SJohn Dyson 	lkp->lk_timo = timo;
51899448ed1SJohn Dyson 	lkp->lk_lockholder = LK_NOPROC;
519c6964d3bSKirk McKusick 	lkp->lk_newlock = NULL;
5203a096f6cSKirk McKusick #ifdef DEBUG_LOCKS
5217499fd8dSJeff Roberson 	stack_zero(&lkp->lk_stack);
5223a096f6cSKirk McKusick #endif
523ab2dab16SJohn Baldwin 	lock_init(&lkp->lk_object, &lock_class_lockmgr, wmesg, NULL,
524ab2dab16SJohn Baldwin 	    LO_RECURSABLE | LO_SLEEPABLE | LO_UPGRADABLE);
52599448ed1SJohn Dyson }
52699448ed1SJohn Dyson 
52799448ed1SJohn Dyson /*
528a18b1f1dSJason Evans  * Destroy a lock.
529a18b1f1dSJason Evans  */
530a18b1f1dSJason Evans void
531a18b1f1dSJason Evans lockdestroy(lkp)
532a18b1f1dSJason Evans 	struct lock *lkp;
533a18b1f1dSJason Evans {
534c91fcee7SJohn Baldwin 
535c06394f5SJohn Baldwin 	CTR2(KTR_LOCK, "lockdestroy(): lkp == %p (lk_wmesg == \"%s\")",
536a18b1f1dSJason Evans 	    lkp, lkp->lk_wmesg);
537ab2dab16SJohn Baldwin 	lock_destroy(&lkp->lk_object);
538a18b1f1dSJason Evans }
539a18b1f1dSJason Evans 
540a18b1f1dSJason Evans /*
541d7a7e179SAttilio Rao  * Disown the lockmgr.
542d7a7e179SAttilio Rao  */
543d7a7e179SAttilio Rao void
544d7a7e179SAttilio Rao lockmgr_disown(struct lock *lkp)
545d7a7e179SAttilio Rao {
546d7a7e179SAttilio Rao 	struct thread *td;
547d7a7e179SAttilio Rao 
548d7a7e179SAttilio Rao 	td = curthread;
549d7a7e179SAttilio Rao 	KASSERT(lkp->lk_exclusivecount || lkp->lk_lockholder == LK_KERNPROC,
550d7a7e179SAttilio Rao 	    ("%s: %p lockmgr must be exclusively locked", __func__, lkp));
551d7a7e179SAttilio Rao 	KASSERT(lkp->lk_lockholder == td,
552d7a7e179SAttilio Rao 	    ("%s: %p lockmgr must be locked by curthread (%p)", __func__, lkp,
553d7a7e179SAttilio Rao 	    td));
554d7a7e179SAttilio Rao 
555d7a7e179SAttilio Rao 	/*
556d7a7e179SAttilio Rao 	 * Drop the lock reference and switch the owner.  This will result
557d7a7e179SAttilio Rao 	 * in an atomic operation like td_lock is only accessed by curthread
558d7a7e179SAttilio Rao 	 * and lk_lockholder only needs one write.
559d7a7e179SAttilio Rao 	 */
560d7a7e179SAttilio Rao 	if (lkp->lk_lockholder == td)
561d7a7e179SAttilio Rao 		td->td_locks--;
562d7a7e179SAttilio Rao 	lkp->lk_lockholder = LK_KERNPROC;
563d7a7e179SAttilio Rao }
564d7a7e179SAttilio Rao 
565d7a7e179SAttilio Rao /*
56699448ed1SJohn Dyson  * Determine the status of a lock.
56799448ed1SJohn Dyson  */
56899448ed1SJohn Dyson int
569b40ce416SJulian Elischer lockstatus(lkp, td)
57099448ed1SJohn Dyson 	struct lock *lkp;
571b40ce416SJulian Elischer 	struct thread *td;
57299448ed1SJohn Dyson {
57399448ed1SJohn Dyson 	int lock_type = 0;
5742b59d50cSRobert Watson 	int interlocked;
57599448ed1SJohn Dyson 
5762b59d50cSRobert Watson 	if (!kdb_active) {
5772b59d50cSRobert Watson 		interlocked = 1;
5789ed346baSBosko Milekic 		mtx_lock(lkp->lk_interlock);
5792b59d50cSRobert Watson 	} else
5802b59d50cSRobert Watson 		interlocked = 0;
5816bdfe06aSEivind Eklund 	if (lkp->lk_exclusivecount != 0) {
582822ded67SJulian Elischer 		if (td == NULL || lkp->lk_lockholder == td)
58399448ed1SJohn Dyson 			lock_type = LK_EXCLUSIVE;
5846bdfe06aSEivind Eklund 		else
5856bdfe06aSEivind Eklund 			lock_type = LK_EXCLOTHER;
5866bdfe06aSEivind Eklund 	} else if (lkp->lk_sharecount != 0)
58799448ed1SJohn Dyson 		lock_type = LK_SHARED;
5882b59d50cSRobert Watson 	if (interlocked)
5899ed346baSBosko Milekic 		mtx_unlock(lkp->lk_interlock);
59099448ed1SJohn Dyson 	return (lock_type);
59199448ed1SJohn Dyson }
59299448ed1SJohn Dyson 
59353bf4bb2SPeter Wemm /*
59467812eacSKirk McKusick  * Determine the number of holders of a lock.
59567812eacSKirk McKusick  */
59667812eacSKirk McKusick int
59767812eacSKirk McKusick lockcount(lkp)
59867812eacSKirk McKusick 	struct lock *lkp;
59967812eacSKirk McKusick {
60067812eacSKirk McKusick 	int count;
60167812eacSKirk McKusick 
6029ed346baSBosko Milekic 	mtx_lock(lkp->lk_interlock);
60367812eacSKirk McKusick 	count = lkp->lk_exclusivecount + lkp->lk_sharecount;
6049ed346baSBosko Milekic 	mtx_unlock(lkp->lk_interlock);
60567812eacSKirk McKusick 	return (count);
60667812eacSKirk McKusick }
60767812eacSKirk McKusick 
60867812eacSKirk McKusick /*
60904aa807cSTor Egge  * Determine the number of waiters on a lock.
61004aa807cSTor Egge  */
61104aa807cSTor Egge int
61204aa807cSTor Egge lockwaiters(lkp)
61304aa807cSTor Egge 	struct lock *lkp;
61404aa807cSTor Egge {
61504aa807cSTor Egge 	int count;
61604aa807cSTor Egge 
61704aa807cSTor Egge 	mtx_lock(lkp->lk_interlock);
61804aa807cSTor Egge 	count = lkp->lk_waitcount;
61904aa807cSTor Egge 	mtx_unlock(lkp->lk_interlock);
62004aa807cSTor Egge 	return (count);
62104aa807cSTor Egge }
62204aa807cSTor Egge 
62304aa807cSTor Egge /*
62453bf4bb2SPeter Wemm  * Print out information about state of a lock. Used by VOP_PRINT
6250e61ac7bSPoul-Henning Kamp  * routines to display status about contained locks.
62653bf4bb2SPeter Wemm  */
627a1ce9d5cSPeter Wemm void
62853bf4bb2SPeter Wemm lockmgr_printinfo(lkp)
62953bf4bb2SPeter Wemm 	struct lock *lkp;
63053bf4bb2SPeter Wemm {
63153bf4bb2SPeter Wemm 
63253bf4bb2SPeter Wemm 	if (lkp->lk_sharecount)
63353bf4bb2SPeter Wemm 		printf(" lock type %s: SHARED (count %d)", lkp->lk_wmesg,
63453bf4bb2SPeter Wemm 		    lkp->lk_sharecount);
63553bf4bb2SPeter Wemm 	else if (lkp->lk_flags & LK_HAVE_EXCL)
636c969c60cSAlexander Kabaev 		printf(" lock type %s: EXCL (count %d) by thread %p (pid %d)",
637c969c60cSAlexander Kabaev 		    lkp->lk_wmesg, lkp->lk_exclusivecount,
638c969c60cSAlexander Kabaev 		    lkp->lk_lockholder, lkp->lk_lockholder->td_proc->p_pid);
63953bf4bb2SPeter Wemm 	if (lkp->lk_waitcount > 0)
64053bf4bb2SPeter Wemm 		printf(" with %d pending", lkp->lk_waitcount);
6417499fd8dSJeff Roberson #ifdef DEBUG_LOCKS
6429ccca7d1SRobert Watson 	stack_print_ddb(&lkp->lk_stack);
6437499fd8dSJeff Roberson #endif
64453bf4bb2SPeter Wemm }
645be6847d7SJohn Baldwin 
646be6847d7SJohn Baldwin #ifdef DDB
647462a7addSJohn Baldwin /*
648462a7addSJohn Baldwin  * Check to see if a thread that is blocked on a sleep queue is actually
649462a7addSJohn Baldwin  * blocked on a 'struct lock'.  If so, output some details and return true.
650462a7addSJohn Baldwin  * If the lock has an exclusive owner, return that in *ownerp.
651462a7addSJohn Baldwin  */
652462a7addSJohn Baldwin int
653462a7addSJohn Baldwin lockmgr_chain(struct thread *td, struct thread **ownerp)
654462a7addSJohn Baldwin {
655462a7addSJohn Baldwin 	struct lock *lkp;
656462a7addSJohn Baldwin 
657462a7addSJohn Baldwin 	lkp = td->td_wchan;
658462a7addSJohn Baldwin 
659462a7addSJohn Baldwin 	/* Simple test to see if wchan points to a lockmgr lock. */
660ab2dab16SJohn Baldwin 	if (LOCK_CLASS(&lkp->lk_object) == &lock_class_lockmgr &&
661ab2dab16SJohn Baldwin 	    lkp->lk_wmesg == td->td_wmesg)
6626d257b6eSJohn Baldwin 		goto ok;
6636d257b6eSJohn Baldwin 
6646d257b6eSJohn Baldwin 	/*
6656d257b6eSJohn Baldwin 	 * If this thread is doing a DRAIN, then it would be asleep on
6666d257b6eSJohn Baldwin 	 * &lkp->lk_flags rather than lkp.
6676d257b6eSJohn Baldwin 	 */
6686d257b6eSJohn Baldwin 	lkp = (struct lock *)((char *)td->td_wchan -
6696d257b6eSJohn Baldwin 	    offsetof(struct lock, lk_flags));
670ab2dab16SJohn Baldwin 	if (LOCK_CLASS(&lkp->lk_object) == &lock_class_lockmgr &&
671ab2dab16SJohn Baldwin 	    lkp->lk_wmesg == td->td_wmesg && (lkp->lk_flags & LK_WAITDRAIN))
6726d257b6eSJohn Baldwin 		goto ok;
6736d257b6eSJohn Baldwin 
6746d257b6eSJohn Baldwin 	/* Doen't seem to be a lockmgr lock. */
675462a7addSJohn Baldwin 	return (0);
676462a7addSJohn Baldwin 
6776d257b6eSJohn Baldwin ok:
678462a7addSJohn Baldwin 	/* Ok, we think we have a lockmgr lock, so output some details. */
679462a7addSJohn Baldwin 	db_printf("blocked on lk \"%s\" ", lkp->lk_wmesg);
680462a7addSJohn Baldwin 	if (lkp->lk_sharecount) {
681462a7addSJohn Baldwin 		db_printf("SHARED (count %d)\n", lkp->lk_sharecount);
682462a7addSJohn Baldwin 		*ownerp = NULL;
683462a7addSJohn Baldwin 	} else {
684462a7addSJohn Baldwin 		db_printf("EXCL (count %d)\n", lkp->lk_exclusivecount);
685462a7addSJohn Baldwin 		*ownerp = lkp->lk_lockholder;
686462a7addSJohn Baldwin 	}
687462a7addSJohn Baldwin 	return (1);
688462a7addSJohn Baldwin }
689462a7addSJohn Baldwin 
69061bd5e21SKip Macy void
69161bd5e21SKip Macy db_show_lockmgr(struct lock_object *lock)
692be6847d7SJohn Baldwin {
693be6847d7SJohn Baldwin 	struct thread *td;
694be6847d7SJohn Baldwin 	struct lock *lkp;
695be6847d7SJohn Baldwin 
69661bd5e21SKip Macy 	lkp = (struct lock *)lock;
697be6847d7SJohn Baldwin 
698be6847d7SJohn Baldwin 	db_printf(" lock type: %s\n", lkp->lk_wmesg);
699be6847d7SJohn Baldwin 	db_printf(" state: ");
700be6847d7SJohn Baldwin 	if (lkp->lk_sharecount)
701be6847d7SJohn Baldwin 		db_printf("SHARED (count %d)\n", lkp->lk_sharecount);
702be6847d7SJohn Baldwin 	else if (lkp->lk_flags & LK_HAVE_EXCL) {
703be6847d7SJohn Baldwin 		td = lkp->lk_lockholder;
704be6847d7SJohn Baldwin 		db_printf("EXCL (count %d) %p ", lkp->lk_exclusivecount, td);
705be6847d7SJohn Baldwin 		db_printf("(tid %d, pid %d, \"%s\")\n", td->td_tid,
706431f8906SJulian Elischer 		    td->td_proc->p_pid, td->td_name);
707be6847d7SJohn Baldwin 	} else
708be6847d7SJohn Baldwin 		db_printf("UNLOCKED\n");
709be6847d7SJohn Baldwin 	if (lkp->lk_waitcount > 0)
710be6847d7SJohn Baldwin 		db_printf(" waiters: %d\n", lkp->lk_waitcount);
711be6847d7SJohn Baldwin }
712be6847d7SJohn Baldwin #endif
713