xref: /dragonfly/sys/kern/kern_lock.c (revision cfd1aba3)
1 /*
2  * Copyright (c) 1995
3  *	The Regents of the University of California.  All rights reserved.
4  * Copyright (C) 1997
5  *	John S. Dyson.  All rights reserved.
6  * Copyright (C) 2013
7  *	Matthew Dillon, All rights reserved.
8  *
9  * This code contains ideas from software contributed to Berkeley by
10  * Avadis Tevanian, Jr., Michael Wayne Young, and the Mach Operating
11  * System project at Carnegie-Mellon University.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 #include "opt_lint.h"
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/proc.h>
44 #include <sys/lock.h>
45 #include <sys/sysctl.h>
46 #include <sys/spinlock.h>
47 #include <sys/thread2.h>
48 #include <sys/spinlock2.h>
49 
50 static void undo_upreq(struct lock *lkp);
51 
52 /*
53  * Locking primitives implementation.
54  * Locks provide shared/exclusive sychronization.
55  */
56 
57 #ifdef DEBUG_LOCKS
58 #define COUNT(td, x) (td)->td_locks += (x)
59 #else
60 #define COUNT(td, x)
61 #endif
62 
63 #define LOCK_WAIT_TIME 100
64 #define LOCK_SAMPLE_WAIT 7
65 
66 /*
67  * Set, change, or release a lock.
68  *
69  */
70 int
71 #ifndef	DEBUG_LOCKS
72 lockmgr(struct lock *lkp, u_int flags)
73 #else
74 debuglockmgr(struct lock *lkp, u_int flags,
75 	     const char *name, const char *file, int line)
76 #endif
77 {
78 	thread_t td;
79 	thread_t otd;
80 	int error;
81 	int extflags;
82 	int count;
83 	int pflags;
84 	int wflags;
85 	int timo;
86 #ifdef DEBUG_LOCKS
87 	int i;
88 #endif
89 
90 	error = 0;
91 
92 	if (mycpu->gd_intr_nesting_level &&
93 	    (flags & LK_NOWAIT) == 0 &&
94 	    (flags & LK_TYPE_MASK) != LK_RELEASE &&
95 	    panic_cpu_gd != mycpu
96 	) {
97 
98 #ifndef DEBUG_LOCKS
99 		panic("lockmgr %s from %p: called from interrupt, ipi, "
100 		      "or hard code section",
101 		      lkp->lk_wmesg, ((int **)&lkp)[-1]);
102 #else
103 		panic("lockmgr %s from %s:%d: called from interrupt, ipi, "
104 		      "or hard code section",
105 		      lkp->lk_wmesg, file, line);
106 #endif
107 	}
108 
109 #ifdef DEBUG_LOCKS
110 	if (mycpu->gd_spinlocks && ((flags & LK_NOWAIT) == 0)) {
111 		panic("lockmgr %s from %s:%d: called with %d spinlocks held",
112 		      lkp->lk_wmesg, file, line, mycpu->gd_spinlocks);
113 	}
114 #endif
115 
116 	extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK;
117 	td = curthread;
118 
119 again:
120 	count = lkp->lk_count;
121 	cpu_ccfence();
122 
123 	switch (flags & LK_TYPE_MASK) {
124 	case LK_SHARED:
125 		/*
126 		 * Shared lock critical path case
127 		 */
128 		if ((count & (LKC_EXREQ|LKC_UPREQ|LKC_EXCL)) == 0) {
129 			if (atomic_cmpset_int(&lkp->lk_count,
130 					      count, count + 1)) {
131 				COUNT(td, 1);
132 				break;
133 			}
134 			goto again;
135 		}
136 
137 		/*
138 		 * If the caller already holds the lock exclusively then
139 		 * we silently obtain another count on the exclusive lock.
140 		 *
141 		 * WARNING!  The old FreeBSD behavior was to downgrade,
142 		 *	     but this creates a problem when recursions
143 		 *	     return to the caller and the caller expects
144 		 *	     its original exclusive lock to remain exclusively
145 		 *	     locked.
146 		 */
147 		if (lkp->lk_lockholder == td) {
148 			KKASSERT(count & LKC_EXCL);
149 			if ((extflags & LK_CANRECURSE) == 0) {
150 				if (extflags & LK_NOWAIT) {
151 					error = EBUSY;
152 					break;
153 				}
154 				panic("lockmgr: locking against myself");
155 			}
156 			atomic_add_int(&lkp->lk_count, 1);
157 			COUNT(td, 1);
158 			break;
159 		}
160 
161 		/*
162 		 * Slow path
163 		 */
164 		pflags = (extflags & LK_PCATCH) ? PCATCH : 0;
165 		timo = (extflags & LK_TIMELOCK) ? lkp->lk_timo : 0;
166 		wflags = (td->td_flags & TDF_DEADLKTREAT) ?
167 				LKC_EXCL : (LKC_EXCL|LKC_EXREQ|LKC_UPREQ);
168 
169 		/*
170 		 * Block while the lock is held exclusively or, conditionally,
171 		 * if other threads are tring to obtain an exclusive lock or
172 		 * upgrade to one.
173 		 */
174 		if (count & wflags) {
175 			if (extflags & LK_NOWAIT) {
176 				error = EBUSY;
177 				break;
178 			}
179 			tsleep_interlock(lkp, pflags);
180 			if (!atomic_cmpset_int(&lkp->lk_count, count,
181 					      count | LKC_SHREQ)) {
182 				goto again;
183 			}
184 
185 			mycpu->gd_cnt.v_lock_name[0] = 'S';
186 			strncpy(mycpu->gd_cnt.v_lock_name + 1,
187 				lkp->lk_wmesg,
188 				sizeof(mycpu->gd_cnt.v_lock_name) - 2);
189 			++mycpu->gd_cnt.v_lock_colls;
190 
191 			error = tsleep(lkp, pflags | PINTERLOCKED,
192 				       lkp->lk_wmesg, timo);
193 			if (error)
194 				break;
195 			if (extflags & LK_SLEEPFAIL) {
196 				error = ENOLCK;
197 				break;
198 			}
199 			goto again;
200 		}
201 
202 		/*
203 		 * Otherwise we can bump the count
204 		 */
205 		if (atomic_cmpset_int(&lkp->lk_count, count, count + 1)) {
206 			COUNT(td, 1);
207 			break;
208 		}
209 		goto again;
210 
211 	case LK_EXCLUSIVE:
212 		/*
213 		 * Exclusive lock critical path.
214 		 */
215 		if (count == 0) {
216 			if (atomic_cmpset_int(&lkp->lk_count, count,
217 					      LKC_EXCL | (count + 1))) {
218 				lkp->lk_lockholder = td;
219 				COUNT(td, 1);
220 				break;
221 			}
222 			goto again;
223 		}
224 
225 		/*
226 		 * Recursive lock if we already hold it exclusively.
227 		 */
228 		if (lkp->lk_lockholder == td) {
229 			KKASSERT(count & LKC_EXCL);
230 			if ((extflags & LK_CANRECURSE) == 0) {
231 				if (extflags & LK_NOWAIT) {
232 					error = EBUSY;
233 					break;
234 				}
235 				panic("lockmgr: locking against myself");
236 			}
237 			atomic_add_int(&lkp->lk_count, 1);
238 			COUNT(td, 1);
239 			break;
240 		}
241 
242 		/*
243 		 * We will block, handle LK_NOWAIT
244 		 */
245 		if (extflags & LK_NOWAIT) {
246 			error = EBUSY;
247 			break;
248 		}
249 
250 		/*
251 		 * Wait until we can obtain the exclusive lock.  EXREQ is
252 		 * automatically cleared when all current holders release
253 		 * so if we abort the operation we can safely leave it set.
254 		 * There might be other exclusive requesters.
255 		 */
256 		pflags = (extflags & LK_PCATCH) ? PCATCH : 0;
257 		timo = (extflags & LK_TIMELOCK) ? lkp->lk_timo : 0;
258 
259 		tsleep_interlock(lkp, pflags);
260 		if (!atomic_cmpset_int(&lkp->lk_count, count,
261 				       count | LKC_EXREQ)) {
262 			goto again;
263 		}
264 
265 		mycpu->gd_cnt.v_lock_name[0] = 'X';
266 		strncpy(mycpu->gd_cnt.v_lock_name + 1,
267 			lkp->lk_wmesg,
268 			sizeof(mycpu->gd_cnt.v_lock_name) - 2);
269 		++mycpu->gd_cnt.v_lock_colls;
270 
271 		error = tsleep(lkp, pflags | PINTERLOCKED,
272 			       lkp->lk_wmesg, timo);
273 		if (error)
274 			break;
275 		if (extflags & LK_SLEEPFAIL) {
276 			error = ENOLCK;
277 			break;
278 		}
279 		goto again;
280 
281 	case LK_DOWNGRADE:
282 		/*
283 		 * Downgrade an exclusive lock into a shared lock.  All
284 		 * counts on a recursive exclusive lock become shared.
285 		 *
286 		 * This function always succeeds.
287 		 */
288 		if (lkp->lk_lockholder != td ||
289 		    (count & (LKC_EXCL|LKC_MASK)) != (LKC_EXCL|1)) {
290 			panic("lockmgr: not holding exclusive lock");
291 		}
292 
293 #ifdef DEBUG_LOCKS
294 		for (i = 0; i < LOCKMGR_DEBUG_ARRAY_SIZE; i++) {
295 			if (td->td_lockmgr_stack[i] == lkp &&
296 			    td->td_lockmgr_stack_id[i] > 0
297 			) {
298 				td->td_lockmgr_stack_id[i]--;
299 				break;
300 			}
301 		}
302 #endif
303 		/*
304 		 * NOTE! Must NULL-out lockholder before releasing LKC_EXCL.
305 		 */
306 		otd = lkp->lk_lockholder;
307 		lkp->lk_lockholder = NULL;
308 		if (atomic_cmpset_int(&lkp->lk_count, count,
309 				      count & ~(LKC_EXCL|LKC_SHREQ))) {
310 			if (count & LKC_SHREQ)
311 				wakeup(lkp);
312 			break;
313 		}
314 		lkp->lk_lockholder = otd;
315 		goto again;
316 
317 	case LK_EXCLUPGRADE:
318 		/*
319 		 * Upgrade from a single shared lock to an exclusive lock.
320 		 *
321 		 * If another process is ahead of us to get an upgrade,
322 		 * then we want to fail rather than have an intervening
323 		 * exclusive access.  The shared lock is released on
324 		 * failure.
325 		 */
326 		if (count & LKC_UPREQ) {
327 			flags = LK_RELEASE;
328 			error = EBUSY;
329 			goto again;
330 		}
331 		/* fall through into normal upgrade */
332 
333 	case LK_UPGRADE:
334 		/*
335 		 * Upgrade a shared lock to an exclusive one.  This can cause
336 		 * the lock to be temporarily released and stolen by other
337 		 * threads.  LK_SLEEPFAIL or LK_NOWAIT may be used to detect
338 		 * this case, or use LK_EXCLUPGRADE.
339 		 *
340 		 * If the lock is already exclusively owned by us, this
341 		 * operation is a NOP.
342 		 *
343 		 * If we return an error (even NOWAIT), the current lock will
344 		 * be released.
345 		 *
346 		 * Start with the critical path.
347 		 */
348 		if ((count & (LKC_UPREQ|LKC_EXCL|LKC_MASK)) == 1) {
349 			if (atomic_cmpset_int(&lkp->lk_count, count,
350 					      count | LKC_EXCL)) {
351 				lkp->lk_lockholder = td;
352 				break;
353 			}
354 			goto again;
355 		}
356 
357 		/*
358 		 * If we already hold the lock exclusively this operation
359 		 * succeeds and is a NOP.
360 		 */
361 		if (count & LKC_EXCL) {
362 			if (lkp->lk_lockholder == td)
363 				break;
364 			panic("lockmgr: upgrade unowned lock");
365 		}
366 		if ((count & LKC_MASK) == 0)
367 			panic("lockmgr: upgrade unowned lock");
368 
369 		/*
370 		 * We cannot upgrade without blocking at this point.
371 		 */
372 		if (extflags & LK_NOWAIT) {
373 			flags = LK_RELEASE;
374 			error = EBUSY;
375 			goto again;
376 		}
377 
378 		/*
379 		 * Release the shared lock and request the upgrade.
380 		 */
381 		pflags = (extflags & LK_PCATCH) ? PCATCH : 0;
382 		timo = (extflags & LK_TIMELOCK) ? lkp->lk_timo : 0;
383 		tsleep_interlock(lkp, pflags);
384 		wflags = (count & LKC_UPREQ) ? LKC_EXREQ : LKC_UPREQ;
385 
386 		/*
387 		 * If someone else owns UPREQ and this transition would
388 		 * allow it to be granted, we have to grant it.  Otherwise
389 		 * we release the shared lock.
390 		 */
391 		if ((count & (LKC_UPREQ|LKC_MASK)) == (LKC_UPREQ | 1)) {
392 			wflags |= LKC_EXCL | LKC_UPGRANT;
393 			wflags |= count;
394 			wflags &= ~LKC_UPREQ;
395 		} else {
396 			wflags |= (count - 1);
397 		}
398 
399 		if (atomic_cmpset_int(&lkp->lk_count, count, wflags)) {
400 			COUNT(td, -1);
401 
402 			/*
403 			 * Must wakeup the thread granted the upgrade.
404 			 */
405 			if ((count & (LKC_UPREQ|LKC_MASK)) == (LKC_UPREQ | 1))
406 				wakeup(lkp);
407 
408 			mycpu->gd_cnt.v_lock_name[0] = 'U';
409 			strncpy(mycpu->gd_cnt.v_lock_name + 1,
410 				lkp->lk_wmesg,
411 				sizeof(mycpu->gd_cnt.v_lock_name) - 2);
412 			++mycpu->gd_cnt.v_lock_colls;
413 
414 			error = tsleep(lkp, pflags | PINTERLOCKED,
415 				       lkp->lk_wmesg, timo);
416 			if (error)
417 				break;
418 			if (extflags & LK_SLEEPFAIL) {
419 				error = ENOLCK;
420 				break;
421 			}
422 
423 			/*
424 			 * Refactor to either LK_EXCLUSIVE or LK_WAITUPGRADE,
425 			 * depending on whether we were able to acquire the
426 			 * LKC_UPREQ bit.
427 			 */
428 			if (count & LKC_UPREQ)
429 				flags = LK_EXCLUSIVE;	/* someone else */
430 			else
431 				flags = LK_WAITUPGRADE;	/* we own the bit */
432 		}
433 		goto again;
434 
435 	case LK_WAITUPGRADE:
436 		/*
437 		 * We own the LKC_UPREQ bit, wait until we are granted the
438 		 * exclusive lock (LKC_UPGRANT is set).
439 		 *
440 		 * IF THE OPERATION FAILS (tsleep error tsleep+LK_SLEEPFAIL),
441 		 * we have to undo the upgrade request and clean up any lock
442 		 * that might have been granted via a race.
443 		 */
444 		if (count & LKC_UPGRANT) {
445 			if (atomic_cmpset_int(&lkp->lk_count, count,
446 					      count & ~LKC_UPGRANT)) {
447 				lkp->lk_lockholder = td;
448 				KKASSERT(count & LKC_EXCL);
449 				break;
450 			}
451 			/* retry */
452 		} else {
453 			pflags = (extflags & LK_PCATCH) ? PCATCH : 0;
454 			timo = (extflags & LK_TIMELOCK) ? lkp->lk_timo : 0;
455 			tsleep_interlock(lkp, pflags);
456 			if (atomic_cmpset_int(&lkp->lk_count, count, count)) {
457 
458 				mycpu->gd_cnt.v_lock_name[0] = 'U';
459 				strncpy(mycpu->gd_cnt.v_lock_name + 1,
460 					lkp->lk_wmesg,
461 					sizeof(mycpu->gd_cnt.v_lock_name) - 2);
462 				++mycpu->gd_cnt.v_lock_colls;
463 
464 				error = tsleep(lkp, pflags | PINTERLOCKED,
465 					       lkp->lk_wmesg, timo);
466 				if (error) {
467 					undo_upreq(lkp);
468 					break;
469 				}
470 				if (extflags & LK_SLEEPFAIL) {
471 					error = ENOLCK;
472 					undo_upreq(lkp);
473 					break;
474 				}
475 			}
476 			/* retry */
477 		}
478 		goto again;
479 
480 	case LK_RELEASE:
481 		/*
482 		 * Release the currently held lock.  If releasing the current
483 		 * lock as part of an error return, error will ALREADY be
484 		 * non-zero.
485 		 *
486 		 * When releasing the last lock we automatically transition
487 		 * LKC_UPREQ to LKC_EXCL|1.
488 		 *
489 		 * WARNING! We cannot detect when there are multiple exclusive
490 		 *	    requests pending.  We clear EXREQ unconditionally
491 		 *	    on the 1->0 transition so it is possible for
492 		 *	    shared requests to race the next exclusive
493 		 *	    request.
494 		 *
495 		 * Always succeeds.
496 		 */
497 		if ((count & LKC_MASK) == 0)
498 			panic("lockmgr: LK_RELEASE: no lock held");
499 
500 		if (count & LKC_EXCL) {
501 			if (lkp->lk_lockholder != LK_KERNTHREAD &&
502 			    lkp->lk_lockholder != td) {
503 				panic("lockmgr: pid %d, not exlusive "
504 				      "lock holder thr %p/%p unlocking",
505 				    (td->td_proc ? td->td_proc->p_pid : -1),
506 				    td, lkp->lk_lockholder);
507 			}
508 			if ((count & (LKC_UPREQ|LKC_MASK)) == 1) {
509 				/*
510 				 * Last exclusive count is being released
511 				 */
512 				otd = lkp->lk_lockholder;
513 				lkp->lk_lockholder = NULL;
514 				if (!atomic_cmpset_int(&lkp->lk_count, count,
515 					      (count - 1) &
516 					   ~(LKC_EXCL|LKC_EXREQ|LKC_SHREQ))) {
517 					lkp->lk_lockholder = otd;
518 					goto again;
519 				}
520 				if (count & (LKC_EXREQ|LKC_SHREQ))
521 					wakeup(lkp);
522 				/* success */
523 			} else if ((count & (LKC_UPREQ|LKC_MASK)) ==
524 				   (LKC_UPREQ | 1)) {
525 				/*
526 				 * Last exclusive count is being released but
527 				 * an upgrade request is present, automatically
528 				 * grant an exclusive state to the owner of
529 				 * the upgrade request.
530 				 */
531 				otd = lkp->lk_lockholder;
532 				lkp->lk_lockholder = NULL;
533 				if (!atomic_cmpset_int(&lkp->lk_count, count,
534 						(count & ~LKC_UPREQ) |
535 						LKC_UPGRANT)) {
536 					lkp->lk_lockholder = otd;
537 				}
538 				wakeup(lkp);
539 				/* success */
540 			} else {
541 				otd = lkp->lk_lockholder;
542 				if (!atomic_cmpset_int(&lkp->lk_count, count,
543 						       count - 1)) {
544 					goto again;
545 				}
546 				/* success */
547 			}
548 			/* success */
549 			if (otd != LK_KERNTHREAD)
550 				COUNT(td, -1);
551 		} else {
552 			if ((count & (LKC_UPREQ|LKC_MASK)) == 1) {
553 				/*
554 				 * Last shared count is being released.
555 				 */
556 				if (!atomic_cmpset_int(&lkp->lk_count, count,
557 					      (count - 1) &
558 					       ~(LKC_EXREQ|LKC_SHREQ))) {
559 					goto again;
560 				}
561 				if (count & (LKC_EXREQ|LKC_SHREQ))
562 					wakeup(lkp);
563 				/* success */
564 			} else if ((count & (LKC_UPREQ|LKC_MASK)) ==
565 				   (LKC_UPREQ | 1)) {
566 				/*
567 				 * Last shared count is being released but
568 				 * an upgrade request is present, automatically
569 				 * grant an exclusive state to the owner of
570 				 * the upgrade request.
571 				 */
572 				if (!atomic_cmpset_int(&lkp->lk_count, count,
573 					      (count & ~LKC_UPREQ) |
574 					      LKC_EXCL | LKC_UPGRANT)) {
575 					goto again;
576 				}
577 				wakeup(lkp);
578 			} else {
579 				if (!atomic_cmpset_int(&lkp->lk_count, count,
580 						       count - 1)) {
581 					goto again;
582 				}
583 			}
584 			/* success */
585 			COUNT(td, -1);
586 		}
587 		break;
588 
589 	default:
590 		panic("lockmgr: unknown locktype request %d",
591 		    flags & LK_TYPE_MASK);
592 		/* NOTREACHED */
593 	}
594 	return (error);
595 }
596 
597 /*
598  * Undo an upgrade request
599  */
600 static
601 void
602 undo_upreq(struct lock *lkp)
603 {
604 	int count;
605 
606 	for (;;) {
607 		count = lkp->lk_count;
608 		cpu_ccfence();
609 		if (count & LKC_UPGRANT) {
610 			/*
611 			 * UPREQ was shifted to UPGRANT.  We own UPGRANT now,
612 			 * another thread might own UPREQ.  Clear UPGRANT
613 			 * and release the granted lock.
614 			 */
615 			if (atomic_cmpset_int(&lkp->lk_count, count,
616 					      count & ~LKC_UPGRANT)) {
617 				lockmgr(lkp, LK_RELEASE);
618 				break;
619 			}
620 		} else if (count & LKC_EXCL) {
621 			/*
622 			 * Clear the UPREQ we still own.  Nobody to wakeup
623 			 * here because there is an existing exclusive
624 			 * holder.
625 			 */
626 			KKASSERT(count & LKC_UPREQ);
627 			KKASSERT((count & LKC_MASK) > 0);
628 			if (atomic_cmpset_int(&lkp->lk_count, count,
629 					      count & ~LKC_UPREQ)) {
630 				wakeup(lkp);
631 				break;
632 			}
633 		} else if (count & LKC_EXREQ) {
634 			/*
635 			 * Clear the UPREQ we still own.  We cannot wakeup any
636 			 * shared waiters because there is an exclusive
637 			 * request pending.
638 			 */
639 			KKASSERT(count & LKC_UPREQ);
640 			KKASSERT((count & LKC_MASK) > 0);
641 			if (atomic_cmpset_int(&lkp->lk_count, count,
642 					      count & ~LKC_UPREQ)) {
643 				break;
644 			}
645 		} else {
646 			/*
647 			 * Clear the UPREQ we still own.  Wakeup any shared
648 			 * waiters.
649 			 */
650 			KKASSERT(count & LKC_UPREQ);
651 			KKASSERT((count & LKC_MASK) > 0);
652 			if (atomic_cmpset_int(&lkp->lk_count, count,
653 					      count &
654 					      ~(LKC_UPREQ | LKC_SHREQ))) {
655 				if (count & LKC_SHREQ)
656 					wakeup(lkp);
657 				break;
658 			}
659 		}
660 		/* retry */
661 	}
662 }
663 
664 void
665 lockmgr_kernproc(struct lock *lp)
666 {
667 	struct thread *td __debugvar = curthread;
668 
669 	if (lp->lk_lockholder != LK_KERNTHREAD) {
670 		KASSERT(lp->lk_lockholder == td,
671 		    ("lockmgr_kernproc: lock not owned by curthread %p", td));
672 		lp->lk_lockholder = LK_KERNTHREAD;
673 		COUNT(td, -1);
674 	}
675 }
676 
677 /*
678  * Initialize a lock; required before use.
679  */
680 void
681 lockinit(struct lock *lkp, const char *wmesg, int timo, int flags)
682 {
683 	lkp->lk_flags = (flags & LK_EXTFLG_MASK);
684 	lkp->lk_count = 0;
685 	lkp->lk_wmesg = wmesg;
686 	lkp->lk_timo = timo;
687 	lkp->lk_lockholder = LK_NOTHREAD;
688 }
689 
690 /*
691  * Reinitialize a lock that is being reused for a different purpose, but
692  * which may have pending (blocked) threads sitting on it.  The caller
693  * must already hold the interlock.
694  */
695 void
696 lockreinit(struct lock *lkp, const char *wmesg, int timo, int flags)
697 {
698 	lkp->lk_wmesg = wmesg;
699 	lkp->lk_timo = timo;
700 }
701 
702 /*
703  * De-initialize a lock.  The structure must no longer be used by anyone.
704  */
705 void
706 lockuninit(struct lock *lkp)
707 {
708 	KKASSERT((lkp->lk_count & (LKC_EXREQ|LKC_SHREQ|LKC_UPREQ)) == 0);
709 }
710 
711 /*
712  * Determine the status of a lock.
713  */
714 int
715 lockstatus(struct lock *lkp, struct thread *td)
716 {
717 	int lock_type = 0;
718 	int count;
719 
720 	count = lkp->lk_count;
721 	cpu_ccfence();
722 
723 	if (count & LKC_EXCL) {
724 		if (td == NULL || lkp->lk_lockholder == td)
725 			lock_type = LK_EXCLUSIVE;
726 		else
727 			lock_type = LK_EXCLOTHER;
728 	} else if (count & LKC_MASK) {
729 		lock_type = LK_SHARED;
730 	}
731 	return (lock_type);
732 }
733 
734 /*
735  * Return non-zero if the caller owns the lock shared or exclusive.
736  * We can only guess re: shared locks.
737  */
738 int
739 lockowned(struct lock *lkp)
740 {
741 	thread_t td = curthread;
742 	int count;
743 
744 	count = lkp->lk_count;
745 	cpu_ccfence();
746 
747 	if (count & LKC_EXCL)
748 		return(lkp->lk_lockholder == td);
749 	else
750 		return((count & LKC_MASK) != 0);
751 }
752 
753 /*
754  * Determine the number of holders of a lock.
755  *
756  * The non-blocking version can usually be used for assertions.
757  */
758 int
759 lockcount(struct lock *lkp)
760 {
761 	return(lkp->lk_count & LKC_MASK);
762 }
763 
764 int
765 lockcountnb(struct lock *lkp)
766 {
767 	return(lkp->lk_count & LKC_MASK);
768 }
769 
770 /*
771  * Print out information about state of a lock. Used by VOP_PRINT
772  * routines to display status about contained locks.
773  */
774 void
775 lockmgr_printinfo(struct lock *lkp)
776 {
777 	struct thread *td = lkp->lk_lockholder;
778 	struct proc *p;
779 	int count;
780 
781 	count = lkp->lk_count;
782 	cpu_ccfence();
783 
784 	if (td && td != LK_KERNTHREAD && td != LK_NOTHREAD)
785 		p = td->td_proc;
786 	else
787 		p = NULL;
788 
789 	if (count & LKC_EXCL) {
790 		kprintf(" lock type %s: EXCLUS (count %08x) by td %p pid %d",
791 		    lkp->lk_wmesg, count, td,
792 		    p ? p->p_pid : -99);
793 	} else if (count & LKC_MASK) {
794 		kprintf(" lock type %s: SHARED (count %08x)",
795 		    lkp->lk_wmesg, count);
796 	} else {
797 		kprintf(" lock type %s: NOTHELD", lkp->lk_wmesg);
798 	}
799 	if (count & (LKC_EXREQ|LKC_SHREQ))
800 		kprintf(" with waiters\n");
801 	else
802 		kprintf("\n");
803 }
804 
805 void
806 lock_sysinit(struct lock_args *arg)
807 {
808 	lockinit(arg->la_lock, arg->la_desc, 0, arg->la_flags);
809 }
810