1 /* 2 * Copyright (c) 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Copyright (C) 1997 6 * John S. Dyson. All rights reserved. 7 * 8 * This code contains ideas from software contributed to Berkeley by 9 * Avadis Tevanian, Jr., Michael Wayne Young, and the Mach Operating 10 * System project at Carnegie-Mellon University. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)kern_lock.c 8.18 (Berkeley) 5/21/95 41 * $FreeBSD: src/sys/kern/kern_lock.c,v 1.31.2.3 2001/12/25 01:44:44 dillon Exp $ 42 * $DragonFly: src/sys/kern/kern_lock.c,v 1.27 2008/01/09 10:59:12 corecode Exp $ 43 */ 44 45 #include "opt_lint.h" 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/kernel.h> 50 #include <sys/proc.h> 51 #include <sys/lock.h> 52 #include <sys/sysctl.h> 53 #include <sys/spinlock.h> 54 #include <sys/thread2.h> 55 #include <sys/spinlock2.h> 56 57 /* 58 * Locking primitives implementation. 59 * Locks provide shared/exclusive sychronization. 60 */ 61 62 #ifdef DEBUG_LOCKS 63 #define COUNT(td, x) (td)->td_locks += (x) 64 #else 65 #define COUNT(td, x) 66 #endif 67 68 #define LOCK_WAIT_TIME 100 69 #define LOCK_SAMPLE_WAIT 7 70 71 #if defined(DIAGNOSTIC) 72 #define LOCK_INLINE 73 #else 74 #define LOCK_INLINE __inline 75 #endif 76 77 #define LK_ALL (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE | \ 78 LK_SHARE_NONZERO | LK_WAIT_NONZERO) 79 80 static int acquire(struct lock *lkp, int extflags, int wanted); 81 82 static LOCK_INLINE void 83 sharelock(struct lock *lkp, int incr) 84 { 85 lkp->lk_flags |= LK_SHARE_NONZERO; 86 lkp->lk_sharecount += incr; 87 } 88 89 static LOCK_INLINE int 90 shareunlock(struct lock *lkp, int decr) 91 { 92 int dowakeup = 0; 93 94 KASSERT(lkp->lk_sharecount >= decr, ("shareunlock: count < decr")); 95 96 if (lkp->lk_sharecount == decr) { 97 lkp->lk_flags &= ~LK_SHARE_NONZERO; 98 if (lkp->lk_flags & (LK_WANT_UPGRADE | LK_WANT_EXCL)) { 99 dowakeup = 1; 100 } 101 lkp->lk_sharecount = 0; 102 } else { 103 lkp->lk_sharecount -= decr; 104 } 105 return(dowakeup); 106 } 107 108 /* 109 * lock acquisition helper routine. Called with the lock's spinlock held. 110 */ 111 static int 112 acquire(struct lock *lkp, int extflags, int wanted) 113 { 114 int error; 115 116 if ((extflags & LK_NOWAIT) && (lkp->lk_flags & wanted)) { 117 return EBUSY; 118 } 119 120 while ((lkp->lk_flags & wanted) != 0) { 121 lkp->lk_flags |= LK_WAIT_NONZERO; 122 lkp->lk_waitcount++; 123 124 /* 125 * Atomic spinlock release/sleep/reacquire. 126 */ 127 error = ssleep(lkp, &lkp->lk_spinlock, 128 ((extflags & LK_PCATCH) ? PCATCH : 0), 129 lkp->lk_wmesg, 130 ((extflags & LK_TIMELOCK) ? lkp->lk_timo : 0)); 131 if (lkp->lk_waitcount == 1) { 132 lkp->lk_flags &= ~LK_WAIT_NONZERO; 133 lkp->lk_waitcount = 0; 134 } else { 135 lkp->lk_waitcount--; 136 } 137 if (error) 138 return error; 139 if (extflags & LK_SLEEPFAIL) 140 return ENOLCK; 141 } 142 return 0; 143 } 144 145 /* 146 * Set, change, or release a lock. 147 * 148 * Shared requests increment the shared count. Exclusive requests set the 149 * LK_WANT_EXCL flag (preventing further shared locks), and wait for already 150 * accepted shared locks and shared-to-exclusive upgrades to go away. 151 * 152 * A spinlock is held for most of the procedure. We must not do anything 153 * fancy while holding the spinlock. 154 */ 155 int 156 #ifndef DEBUG_LOCKS 157 lockmgr(struct lock *lkp, u_int flags) 158 #else 159 debuglockmgr(struct lock *lkp, u_int flags, 160 const char *name, const char *file, int line) 161 #endif 162 { 163 thread_t td; 164 int error; 165 int extflags; 166 int dowakeup; 167 #ifdef DEBUG_LOCKS 168 int i; 169 #endif 170 171 error = 0; 172 dowakeup = 0; 173 174 if (mycpu->gd_intr_nesting_level && 175 (flags & LK_NOWAIT) == 0 && 176 (flags & LK_TYPE_MASK) != LK_RELEASE && 177 panic_cpu_gd != mycpu 178 ) { 179 180 #ifndef DEBUG_LOCKS 181 panic("lockmgr %s from %p: called from interrupt, ipi, " 182 "or hard code section", 183 lkp->lk_wmesg, ((int **)&lkp)[-1]); 184 #else 185 panic("lockmgr %s from %s:%d: called from interrupt, ipi, " 186 "or hard code section", 187 lkp->lk_wmesg, file, line); 188 #endif 189 } 190 191 #ifdef DEBUG_LOCKS 192 if (mycpu->gd_spinlocks_wr && 193 ((flags & LK_NOWAIT) == 0) 194 ) { 195 panic("lockmgr %s from %s:%d: called with %d spinlocks held", 196 lkp->lk_wmesg, file, line, mycpu->gd_spinlocks_wr); 197 } 198 #endif 199 200 spin_lock(&lkp->lk_spinlock); 201 202 extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK; 203 td = curthread; 204 205 switch (flags & LK_TYPE_MASK) { 206 case LK_SHARED: 207 /* 208 * If we are not the exclusive lock holder, we have to block 209 * while there is an exclusive lock holder or while an 210 * exclusive lock request or upgrade request is in progress. 211 * 212 * However, if TDF_DEADLKTREAT is set, we override exclusive 213 * lock requests or upgrade requests ( but not the exclusive 214 * lock itself ). 215 */ 216 if (lkp->lk_lockholder != td) { 217 if (td->td_flags & TDF_DEADLKTREAT) { 218 error = acquire( 219 lkp, 220 extflags, 221 LK_HAVE_EXCL 222 ); 223 } else { 224 error = acquire( 225 lkp, 226 extflags, 227 LK_HAVE_EXCL | LK_WANT_EXCL | 228 LK_WANT_UPGRADE 229 ); 230 } 231 if (error) 232 break; 233 sharelock(lkp, 1); 234 COUNT(td, 1); 235 break; 236 } 237 238 /* 239 * If we already hold an exclusive lock we bump the 240 * exclusive count instead of downgrading to a shared 241 * lock. 242 * 243 * WARNING! The old FreeBSD behavior was to downgrade, 244 * but this creates a problem when recursions 245 * return to the caller and the caller expects 246 * its original exclusive lock to remain exclusively 247 * locked. 248 */ 249 if (extflags & LK_CANRECURSE) { 250 lkp->lk_exclusivecount++; 251 COUNT(td, 1); 252 break; 253 } 254 if (extflags & LK_NOWAIT) { 255 error = EBUSY; 256 break; 257 } 258 spin_unlock(&lkp->lk_spinlock); 259 panic("lockmgr: locking against myself"); 260 #if 0 261 /* 262 * old code queued a shared lock request fell into 263 * a downgrade. 264 */ 265 sharelock(lkp, 1); 266 COUNT(td, 1); 267 /* fall into downgrade */ 268 #endif 269 270 case LK_DOWNGRADE: 271 if (lkp->lk_lockholder != td || lkp->lk_exclusivecount == 0) { 272 spin_unlock(&lkp->lk_spinlock); 273 panic("lockmgr: not holding exclusive lock"); 274 } 275 276 #ifdef DEBUG_LOCKS 277 for (i = 0; i < LOCKMGR_DEBUG_ARRAY_SIZE; i++) { 278 if (td->td_lockmgr_stack[i] == lkp && 279 td->td_lockmgr_stack_id[i] > 0 280 ) { 281 td->td_lockmgr_stack_id[i]--; 282 break; 283 } 284 } 285 #endif 286 287 sharelock(lkp, lkp->lk_exclusivecount); 288 lkp->lk_exclusivecount = 0; 289 lkp->lk_flags &= ~LK_HAVE_EXCL; 290 lkp->lk_lockholder = LK_NOTHREAD; 291 if (lkp->lk_waitcount) 292 dowakeup = 1; 293 break; 294 295 case LK_EXCLUPGRADE: 296 /* 297 * If another process is ahead of us to get an upgrade, 298 * then we want to fail rather than have an intervening 299 * exclusive access. 300 */ 301 if (lkp->lk_flags & LK_WANT_UPGRADE) { 302 dowakeup = shareunlock(lkp, 1); 303 COUNT(td, -1); 304 error = EBUSY; 305 break; 306 } 307 /* fall into normal upgrade */ 308 309 case LK_UPGRADE: 310 /* 311 * Upgrade a shared lock to an exclusive one. If another 312 * shared lock has already requested an upgrade to an 313 * exclusive lock, our shared lock is released and an 314 * exclusive lock is requested (which will be granted 315 * after the upgrade). If we return an error, the file 316 * will always be unlocked. 317 */ 318 if ((lkp->lk_lockholder == td) || (lkp->lk_sharecount <= 0)) { 319 spin_unlock(&lkp->lk_spinlock); 320 panic("lockmgr: upgrade exclusive lock"); 321 } 322 dowakeup += shareunlock(lkp, 1); 323 COUNT(td, -1); 324 /* 325 * If we are just polling, check to see if we will block. 326 */ 327 if ((extflags & LK_NOWAIT) && 328 ((lkp->lk_flags & LK_WANT_UPGRADE) || 329 lkp->lk_sharecount > 1)) { 330 error = EBUSY; 331 break; 332 } 333 if ((lkp->lk_flags & LK_WANT_UPGRADE) == 0) { 334 /* 335 * We are first shared lock to request an upgrade, so 336 * request upgrade and wait for the shared count to 337 * drop to zero, then take exclusive lock. 338 * 339 * Although I don't think this can occur for 340 * robustness we also wait for any exclusive locks 341 * to be released. LK_WANT_UPGRADE is supposed to 342 * prevent new exclusive locks but might not in the 343 * future. 344 */ 345 lkp->lk_flags |= LK_WANT_UPGRADE; 346 error = acquire(lkp, extflags, 347 LK_HAVE_EXCL | LK_SHARE_NONZERO); 348 lkp->lk_flags &= ~LK_WANT_UPGRADE; 349 350 if (error) 351 break; 352 lkp->lk_flags |= LK_HAVE_EXCL; 353 lkp->lk_lockholder = td; 354 if (lkp->lk_exclusivecount != 0) { 355 spin_unlock(&lkp->lk_spinlock); 356 panic("lockmgr(1): non-zero exclusive count"); 357 } 358 lkp->lk_exclusivecount = 1; 359 #if defined(DEBUG_LOCKS) 360 lkp->lk_filename = file; 361 lkp->lk_lineno = line; 362 lkp->lk_lockername = name; 363 364 for (i = 0; i < LOCKMGR_DEBUG_ARRAY_SIZE; i++) { 365 /* 366 * Recursive lockmgr path 367 */ 368 if (td->td_lockmgr_stack[i] == lkp && 369 td->td_lockmgr_stack_id[i] != 0 370 ) { 371 td->td_lockmgr_stack_id[i]++; 372 goto lkmatch2; 373 } 374 } 375 376 for (i = 0; i < LOCKMGR_DEBUG_ARRAY_SIZE; i++) { 377 /* 378 * Use new lockmgr tracking slot 379 */ 380 if (td->td_lockmgr_stack_id[i] == 0) { 381 td->td_lockmgr_stack_id[i]++; 382 td->td_lockmgr_stack[i] = lkp; 383 break; 384 } 385 } 386 lkmatch2: 387 ; 388 #endif 389 COUNT(td, 1); 390 break; 391 } 392 /* 393 * Someone else has requested upgrade. Release our shared 394 * lock, awaken upgrade requestor if we are the last shared 395 * lock, then request an exclusive lock. 396 */ 397 if ((lkp->lk_flags & (LK_SHARE_NONZERO|LK_WAIT_NONZERO)) == 398 LK_WAIT_NONZERO) { 399 ++dowakeup; 400 } 401 /* fall into exclusive request */ 402 403 case LK_EXCLUSIVE: 404 if (lkp->lk_lockholder == td && td != LK_KERNTHREAD) { 405 /* 406 * Recursive lock. 407 */ 408 if ((extflags & (LK_NOWAIT | LK_CANRECURSE)) == 0) { 409 spin_unlock(&lkp->lk_spinlock); 410 panic("lockmgr: locking against myself"); 411 } 412 if ((extflags & LK_CANRECURSE) != 0) { 413 lkp->lk_exclusivecount++; 414 COUNT(td, 1); 415 break; 416 } 417 } 418 /* 419 * If we are just polling, check to see if we will sleep. 420 */ 421 if ((extflags & LK_NOWAIT) && 422 (lkp->lk_flags & (LK_HAVE_EXCL | LK_WANT_EXCL | 423 LK_WANT_UPGRADE | LK_SHARE_NONZERO))) { 424 error = EBUSY; 425 break; 426 } 427 /* 428 * Wait for exclusive lock holders to release and try to 429 * acquire the want_exclusive flag. 430 */ 431 error = acquire(lkp, extflags, (LK_HAVE_EXCL | LK_WANT_EXCL)); 432 if (error) 433 break; 434 lkp->lk_flags |= LK_WANT_EXCL; 435 436 /* 437 * Wait for shared locks and upgrades to finish. We can lose 438 * the race against a successful shared lock upgrade in which 439 * case LK_HAVE_EXCL will get set regardless of our 440 * acquisition of LK_WANT_EXCL, so we have to acquire 441 * LK_HAVE_EXCL here as well. 442 */ 443 error = acquire(lkp, extflags, LK_HAVE_EXCL | 444 LK_WANT_UPGRADE | 445 LK_SHARE_NONZERO); 446 lkp->lk_flags &= ~LK_WANT_EXCL; 447 if (error) 448 break; 449 lkp->lk_flags |= LK_HAVE_EXCL; 450 lkp->lk_lockholder = td; 451 if (lkp->lk_exclusivecount != 0) { 452 spin_unlock(&lkp->lk_spinlock); 453 panic("lockmgr(2): non-zero exclusive count"); 454 } 455 lkp->lk_exclusivecount = 1; 456 #if defined(DEBUG_LOCKS) 457 lkp->lk_filename = file; 458 lkp->lk_lineno = line; 459 lkp->lk_lockername = name; 460 461 for (i = 0; i < LOCKMGR_DEBUG_ARRAY_SIZE; i++) { 462 /* 463 * Recursive lockmgr path 464 */ 465 if (td->td_lockmgr_stack[i] == lkp && 466 td->td_lockmgr_stack_id[i] != 0 467 ) { 468 td->td_lockmgr_stack_id[i]++; 469 goto lkmatch1; 470 } 471 } 472 473 for (i = 0; i < LOCKMGR_DEBUG_ARRAY_SIZE; i++) { 474 /* 475 * Use new lockmgr tracking slot 476 */ 477 if (td->td_lockmgr_stack_id[i] == 0) { 478 td->td_lockmgr_stack_id[i]++; 479 td->td_lockmgr_stack[i] = lkp; 480 break; 481 } 482 } 483 lkmatch1: 484 ; 485 #endif 486 COUNT(td, 1); 487 break; 488 489 case LK_RELEASE: 490 if (lkp->lk_exclusivecount != 0) { 491 if (lkp->lk_lockholder != td && 492 lkp->lk_lockholder != LK_KERNTHREAD) { 493 spin_unlock(&lkp->lk_spinlock); 494 panic("lockmgr: pid %d, not %s thr %p/%p unlocking", 495 (td->td_proc ? td->td_proc->p_pid : -1), 496 "exclusive lock holder", 497 td, lkp->lk_lockholder); 498 } 499 if (lkp->lk_lockholder != LK_KERNTHREAD) { 500 COUNT(td, -1); 501 } 502 if (lkp->lk_exclusivecount == 1) { 503 lkp->lk_flags &= ~LK_HAVE_EXCL; 504 lkp->lk_lockholder = LK_NOTHREAD; 505 lkp->lk_exclusivecount = 0; 506 } else { 507 lkp->lk_exclusivecount--; 508 } 509 #ifdef DEBUG_LOCKS 510 for (i = 0; i < LOCKMGR_DEBUG_ARRAY_SIZE; i++) { 511 if (td->td_lockmgr_stack[i] == lkp && 512 td->td_lockmgr_stack_id[i] > 0 513 ) { 514 td->td_lockmgr_stack_id[i]--; 515 lkp->lk_filename = file; 516 lkp->lk_lineno = line; 517 break; 518 } 519 } 520 #endif 521 } else if (lkp->lk_flags & LK_SHARE_NONZERO) { 522 dowakeup += shareunlock(lkp, 1); 523 COUNT(td, -1); 524 } else { 525 panic("lockmgr: LK_RELEASE: no lock held"); 526 } 527 if (lkp->lk_flags & LK_WAIT_NONZERO) 528 ++dowakeup; 529 break; 530 531 default: 532 spin_unlock(&lkp->lk_spinlock); 533 panic("lockmgr: unknown locktype request %d", 534 flags & LK_TYPE_MASK); 535 /* NOTREACHED */ 536 } 537 spin_unlock(&lkp->lk_spinlock); 538 if (dowakeup) 539 wakeup(lkp); 540 return (error); 541 } 542 543 void 544 lockmgr_kernproc(struct lock *lp) 545 { 546 struct thread *td __debugvar = curthread; 547 548 if (lp->lk_lockholder != LK_KERNTHREAD) { 549 KASSERT(lp->lk_lockholder == td, 550 ("lockmgr_kernproc: lock not owned by curthread %p", td)); 551 COUNT(td, -1); 552 lp->lk_lockholder = LK_KERNTHREAD; 553 } 554 } 555 556 #if 0 557 /* 558 * Set the lock to be exclusively held. The caller is holding the lock's 559 * spinlock and the spinlock remains held on return. A panic will occur 560 * if the lock cannot be set to exclusive. 561 * 562 * XXX not only unused but these functions also break EXCLUPGRADE's 563 * atomicy. 564 */ 565 void 566 lockmgr_setexclusive_interlocked(struct lock *lkp) 567 { 568 thread_t td = curthread; 569 570 KKASSERT((lkp->lk_flags & (LK_HAVE_EXCL|LK_SHARE_NONZERO)) == 0); 571 KKASSERT(lkp->lk_exclusivecount == 0); 572 lkp->lk_flags |= LK_HAVE_EXCL; 573 lkp->lk_lockholder = td; 574 lkp->lk_exclusivecount = 1; 575 COUNT(td, 1); 576 } 577 578 /* 579 * Clear the caller's exclusive lock. The caller is holding the lock's 580 * spinlock. THIS FUNCTION WILL UNLOCK THE SPINLOCK. 581 * 582 * A panic will occur if the caller does not hold the lock. 583 */ 584 void 585 lockmgr_clrexclusive_interlocked(struct lock *lkp) 586 { 587 thread_t td __debugvar = curthread; 588 int dowakeup = 0; 589 590 KKASSERT((lkp->lk_flags & LK_HAVE_EXCL) && lkp->lk_exclusivecount == 1 591 && lkp->lk_lockholder == td); 592 lkp->lk_lockholder = LK_NOTHREAD; 593 lkp->lk_flags &= ~LK_HAVE_EXCL; 594 lkp->lk_exclusivecount = 0; 595 if (lkp->lk_flags & LK_WAIT_NONZERO) 596 dowakeup = 1; 597 COUNT(td, -1); 598 spin_unlock(&lkp->lk_spinlock); 599 if (dowakeup) 600 wakeup((void *)lkp); 601 } 602 603 #endif 604 605 /* 606 * Initialize a lock; required before use. 607 */ 608 void 609 lockinit(struct lock *lkp, const char *wmesg, int timo, int flags) 610 { 611 spin_init(&lkp->lk_spinlock); 612 lkp->lk_flags = (flags & LK_EXTFLG_MASK); 613 lkp->lk_sharecount = 0; 614 lkp->lk_waitcount = 0; 615 lkp->lk_exclusivecount = 0; 616 lkp->lk_wmesg = wmesg; 617 lkp->lk_timo = timo; 618 lkp->lk_lockholder = LK_NOTHREAD; 619 } 620 621 /* 622 * Reinitialize a lock that is being reused for a different purpose, but 623 * which may have pending (blocked) threads sitting on it. The caller 624 * must already hold the interlock. 625 */ 626 void 627 lockreinit(struct lock *lkp, const char *wmesg, int timo, int flags) 628 { 629 spin_lock(&lkp->lk_spinlock); 630 lkp->lk_flags = (lkp->lk_flags & ~LK_EXTFLG_MASK) | 631 (flags & LK_EXTFLG_MASK); 632 lkp->lk_wmesg = wmesg; 633 lkp->lk_timo = timo; 634 spin_unlock(&lkp->lk_spinlock); 635 } 636 637 /* 638 * Requires that the caller is the exclusive owner of this lock. 639 */ 640 void 641 lockuninit(struct lock *l) 642 { 643 /* 644 * At this point we should have removed all the references to this lock 645 * so there can't be anyone waiting on it. 646 */ 647 KKASSERT(l->lk_waitcount == 0); 648 649 spin_uninit(&l->lk_spinlock); 650 } 651 652 /* 653 * Determine the status of a lock. 654 */ 655 int 656 lockstatus(struct lock *lkp, struct thread *td) 657 { 658 int lock_type = 0; 659 660 spin_lock(&lkp->lk_spinlock); 661 if (lkp->lk_exclusivecount != 0) { 662 if (td == NULL || lkp->lk_lockholder == td) 663 lock_type = LK_EXCLUSIVE; 664 else 665 lock_type = LK_EXCLOTHER; 666 } else if (lkp->lk_sharecount != 0) { 667 lock_type = LK_SHARED; 668 } 669 spin_unlock(&lkp->lk_spinlock); 670 return (lock_type); 671 } 672 673 /* 674 * Return non-zero if the caller owns the lock shared or exclusive. 675 * We can only guess re: shared locks. 676 */ 677 int 678 lockowned(struct lock *lkp) 679 { 680 thread_t td = curthread; 681 682 if (lkp->lk_exclusivecount) 683 return(lkp->lk_lockholder == td); 684 return(lkp->lk_sharecount != 0); 685 } 686 687 /* 688 * Determine the number of holders of a lock. 689 * 690 * The non-blocking version can usually be used for assertions. 691 */ 692 int 693 lockcount(struct lock *lkp) 694 { 695 int count; 696 697 spin_lock(&lkp->lk_spinlock); 698 count = lkp->lk_exclusivecount + lkp->lk_sharecount; 699 spin_unlock(&lkp->lk_spinlock); 700 return (count); 701 } 702 703 int 704 lockcountnb(struct lock *lkp) 705 { 706 return (lkp->lk_exclusivecount + lkp->lk_sharecount); 707 } 708 709 /* 710 * Print out information about state of a lock. Used by VOP_PRINT 711 * routines to display status about contained locks. 712 */ 713 void 714 lockmgr_printinfo(struct lock *lkp) 715 { 716 struct thread *td = lkp->lk_lockholder; 717 struct proc *p; 718 719 if (td && td != LK_KERNTHREAD && td != LK_NOTHREAD) 720 p = td->td_proc; 721 else 722 p = NULL; 723 724 if (lkp->lk_sharecount) 725 kprintf(" lock type %s: SHARED (count %d)", lkp->lk_wmesg, 726 lkp->lk_sharecount); 727 else if (lkp->lk_flags & LK_HAVE_EXCL) 728 kprintf(" lock type %s: EXCL (count %d) by td %p pid %d", 729 lkp->lk_wmesg, lkp->lk_exclusivecount, td, 730 p ? p->p_pid : -99); 731 if (lkp->lk_waitcount > 0) 732 kprintf(" with %d pending", lkp->lk_waitcount); 733 } 734 735 void 736 lock_sysinit(struct lock_args *arg) 737 { 738 lockinit(arg->la_lock, arg->la_desc, 0, arg->la_flags); 739 } 740