kernel - Change lockmgr LK_SHARED behavior to fix improper recursion return
[dragonfly.git] / sys / kern / kern_lock.c
... / ...
CommitLineData
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
80static int acquire(struct lock *lkp, int extflags, int wanted);
81
82static LOCK_INLINE void
83sharelock(struct lock *lkp, int incr)
84{
85 lkp->lk_flags |= LK_SHARE_NONZERO;
86 lkp->lk_sharecount += incr;
87}
88
89static LOCK_INLINE int
90shareunlock(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 */
111static int
112acquire(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 */
155int
156#ifndef DEBUG_LOCKS
157lockmgr(struct lock *lkp, u_int flags)
158#else
159debuglockmgr(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 }
386lkmatch2:
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 }
483lkmatch1:
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
543void
544lockmgr_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 */
565void
566lockmgr_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 */
584void
585lockmgr_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 */
608void
609lockinit(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 */
626void
627lockreinit(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 */
640void
641lockuninit(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 */
655int
656lockstatus(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 */
677int
678lockowned(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 */
692int
693lockcount(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
703int
704lockcountnb(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 */
713void
714lockmgr_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
735void
736lock_sysinit(struct lock_args *arg)
737{
738 lockinit(arg->la_lock, arg->la_desc, 0, arg->la_flags);
739}