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