kern_lock.c revision 1.130 1 /* $NetBSD: kern_lock.c,v 1.130 2008/01/02 11:48:50 ad Exp $ */
2
3 /*-
4 * Copyright (c) 1999, 2000, 2006, 2007 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center, and by Andrew Doran.
10 *
11 * This code is derived from software contributed to The NetBSD Foundation
12 * by Ross Harvey.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by the NetBSD
25 * Foundation, Inc. and its contributors.
26 * 4. Neither the name of The NetBSD Foundation nor the names of its
27 * contributors may be used to endorse or promote products derived
28 * from this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
31 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
32 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
34 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40 * POSSIBILITY OF SUCH DAMAGE.
41 */
42
43 /*
44 * Copyright (c) 1995
45 * The Regents of the University of California. All rights reserved.
46 *
47 * This code contains ideas from software contributed to Berkeley by
48 * Avadis Tevanian, Jr., Michael Wayne Young, and the Mach Operating
49 * System project at Carnegie-Mellon University.
50 *
51 * Redistribution and use in source and binary forms, with or without
52 * modification, are permitted provided that the following conditions
53 * are met:
54 * 1. Redistributions of source code must retain the above copyright
55 * notice, this list of conditions and the following disclaimer.
56 * 2. Redistributions in binary form must reproduce the above copyright
57 * notice, this list of conditions and the following disclaimer in the
58 * documentation and/or other materials provided with the distribution.
59 * 3. Neither the name of the University nor the names of its contributors
60 * may be used to endorse or promote products derived from this software
61 * without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73 * SUCH DAMAGE.
74 *
75 * @(#)kern_lock.c 8.18 (Berkeley) 5/21/95
76 */
77
78 #include <sys/cdefs.h>
79 __KERNEL_RCSID(0, "$NetBSD: kern_lock.c,v 1.130 2008/01/02 11:48:50 ad Exp $");
80
81 #include "opt_multiprocessor.h"
82
83 #include <sys/param.h>
84 #include <sys/proc.h>
85 #include <sys/lock.h>
86 #include <sys/systm.h>
87 #include <sys/kernel.h>
88 #include <sys/lockdebug.h>
89 #include <sys/cpu.h>
90 #include <sys/syslog.h>
91 #include <sys/atomic.h>
92
93 #include <machine/stdarg.h>
94
95 #include <dev/lockstat.h>
96
97 /*
98 * note that stdarg.h and the ansi style va_start macro is used for both
99 * ansi and traditional c compiles.
100 * XXX: this requires that stdarg.h define: va_alist and va_dcl
101 */
102 void lock_printf(const char *fmt, ...)
103 __attribute__((__format__(__printf__,1,2)));
104
105 static int acquire(struct lock **, int *, int, int, int, uintptr_t);
106
107 int lock_debug_syslog = 0; /* defaults to printf, but can be patched */
108 bool kernel_lock_dodebug;
109 __cpu_simple_lock_t kernel_lock;
110
111 #ifdef LOCKDEBUG
112 static lockops_t lockmgr_lockops = {
113 "lockmgr",
114 1,
115 (void *)nullop
116 };
117 #endif
118
119 #if defined(LOCKDEBUG) || defined(DIAGNOSTIC) /* { */
120 #define COUNT(lkp, l, cpu_id, x) (l)->l_locks += (x)
121 #else
122 #define COUNT(lkp, p, cpu_id, x)
123 #endif /* LOCKDEBUG || DIAGNOSTIC */ /* } */
124
125 #define RETURN_ADDRESS ((uintptr_t)__builtin_return_address(0))
126
127 /*
128 * Acquire a resource.
129 */
130 static int
131 acquire(struct lock **lkpp, int *s, int extflags,
132 int drain, int wanted, uintptr_t ra)
133 {
134 int error;
135 struct lock *lkp = *lkpp;
136 LOCKSTAT_TIMER(slptime);
137 LOCKSTAT_FLAG(lsflag);
138
139 KASSERT(drain || (wanted & LK_WAIT_NONZERO) == 0);
140
141 LOCKSTAT_ENTER(lsflag);
142
143 for (error = 0; (lkp->lk_flags & wanted) != 0; ) {
144 if (drain)
145 lkp->lk_flags |= LK_WAITDRAIN;
146 else {
147 lkp->lk_waitcount++;
148 lkp->lk_flags |= LK_WAIT_NONZERO;
149 }
150 LOCKSTAT_START_TIMER(lsflag, slptime);
151 error = mtsleep(drain ? (void *)&lkp->lk_flags : (void *)lkp,
152 lkp->lk_prio, lkp->lk_wmesg, lkp->lk_timo,
153 __UNVOLATILE(&lkp->lk_interlock));
154 LOCKSTAT_STOP_TIMER(lsflag, slptime);
155 LOCKSTAT_EVENT_RA(lsflag, (void *)(uintptr_t)lkp,
156 LB_LOCKMGR | LB_SLEEP1, 1, slptime, ra);
157 if (!drain) {
158 lkp->lk_waitcount--;
159 if (lkp->lk_waitcount == 0)
160 lkp->lk_flags &= ~LK_WAIT_NONZERO;
161 }
162 if (error)
163 break;
164 if (extflags & LK_SLEEPFAIL) {
165 error = ENOLCK;
166 break;
167 }
168 }
169
170 LOCKSTAT_EXIT(lsflag);
171
172 return error;
173 }
174
175 #define SETHOLDER(lkp, pid, lid, cpu_id) \
176 do { \
177 (lkp)->lk_lockholder = pid; \
178 (lkp)->lk_locklwp = lid; \
179 } while (/*CONSTCOND*/0)
180
181 #define WEHOLDIT(lkp, pid, lid, cpu_id) \
182 ((lkp)->lk_lockholder == (pid) && (lkp)->lk_locklwp == (lid))
183
184 #define WAKEUP_WAITER(lkp) \
185 do { \
186 if (((lkp)->lk_flags & LK_WAIT_NONZERO) != 0) { \
187 wakeup((lkp)); \
188 } \
189 } while (/*CONSTCOND*/0)
190
191 #if defined(LOCKDEBUG)
192 /*
193 * Lock debug printing routine; can be configured to print to console
194 * or log to syslog.
195 */
196 void
197 lock_printf(const char *fmt, ...)
198 {
199 char b[150];
200 va_list ap;
201
202 va_start(ap, fmt);
203 if (lock_debug_syslog)
204 vlog(LOG_DEBUG, fmt, ap);
205 else {
206 vsnprintf(b, sizeof(b), fmt, ap);
207 printf_nolog("%s", b);
208 }
209 va_end(ap);
210 }
211 #endif /* LOCKDEBUG */
212
213 static void
214 lockpanic(struct lock *lkp, const char *fmt, ...)
215 {
216 char s[150], b[150];
217 static const char *locktype[] = {
218 "*0*", "shared", "exclusive", "*3*", "*4*", "downgrade",
219 "*release*", "drain", "exclother", "*9*", "*10*",
220 "*11*", "*12*", "*13*", "*14*", "*15*"
221 };
222 va_list ap;
223 va_start(ap, fmt);
224 vsnprintf(s, sizeof(s), fmt, ap);
225 va_end(ap);
226 bitmask_snprintf(lkp->lk_flags, __LK_FLAG_BITS, b, sizeof(b));
227 panic("%s ("
228 "type %s flags %s, sharecount %d, exclusivecount %d, "
229 "recurselevel %d, waitcount %d, wmesg %s"
230 ", lock_addr %p, unlock_addr %p"
231 ")\n",
232 s, locktype[lkp->lk_flags & LK_TYPE_MASK],
233 b, lkp->lk_sharecount, lkp->lk_exclusivecount,
234 lkp->lk_recurselevel, lkp->lk_waitcount, lkp->lk_wmesg,
235 (void *)lkp->lk_lock_addr, (void *)lkp->lk_unlock_addr
236 );
237 }
238
239 /*
240 * Initialize a lock; required before use.
241 */
242 void
243 lockinit(struct lock *lkp, pri_t prio, const char *wmesg, int timo, int flags)
244 {
245
246 memset(lkp, 0, sizeof(struct lock));
247 lkp->lk_flags = flags & LK_EXTFLG_MASK;
248 mutex_init(&lkp->lk_interlock, MUTEX_DEFAULT, IPL_NONE);
249 lkp->lk_lockholder = LK_NOPROC;
250 lkp->lk_prio = prio;
251 lkp->lk_timo = timo;
252 lkp->lk_wmesg = wmesg;
253 lkp->lk_lock_addr = 0;
254 lkp->lk_unlock_addr = 0;
255
256 if (LOCKDEBUG_ALLOC(lkp, &lockmgr_lockops,
257 (uintptr_t)__builtin_return_address(0))) {
258 lkp->lk_flags |= LK_DODEBUG;
259 }
260 }
261
262 void
263 lockdestroy(struct lock *lkp)
264 {
265
266 LOCKDEBUG_FREE(((lkp->lk_flags & LK_DODEBUG) != 0), lkp);
267 mutex_destroy(&lkp->lk_interlock);
268 }
269
270 /*
271 * Determine the status of a lock.
272 */
273 int
274 lockstatus(struct lock *lkp)
275 {
276 int lock_type = 0;
277 struct lwp *l = curlwp; /* XXX */
278 pid_t pid;
279 lwpid_t lid;
280 cpuid_t cpu_num;
281
282 if (l == NULL) {
283 cpu_num = cpu_number();
284 pid = LK_KERNPROC;
285 lid = 0;
286 } else {
287 cpu_num = LK_NOCPU;
288 pid = l->l_proc->p_pid;
289 lid = l->l_lid;
290 }
291
292 mutex_enter(&lkp->lk_interlock);
293 if (lkp->lk_exclusivecount != 0) {
294 if (WEHOLDIT(lkp, pid, lid, cpu_num))
295 lock_type = LK_EXCLUSIVE;
296 else
297 lock_type = LK_EXCLOTHER;
298 } else if (lkp->lk_sharecount != 0)
299 lock_type = LK_SHARED;
300 else if (lkp->lk_flags & LK_WANT_EXCL)
301 lock_type = LK_EXCLOTHER;
302 mutex_exit(&lkp->lk_interlock);
303 return (lock_type);
304 }
305
306 /*
307 * XXX XXX kludge around another kludge..
308 *
309 * vfs_shutdown() may be called from interrupt context, either as a result
310 * of a panic, or from the debugger. It proceeds to call
311 * sys_sync(&proc0, ...), pretending its running on behalf of proc0
312 *
313 * We would like to make an attempt to sync the filesystems in this case, so
314 * if this happens, we treat attempts to acquire locks specially.
315 * All locks are acquired on behalf of proc0.
316 *
317 * If we've already paniced, we don't block waiting for locks, but
318 * just barge right ahead since we're already going down in flames.
319 */
320
321 /*
322 * Set, change, or release a lock.
323 *
324 * Shared requests increment the shared count. Exclusive requests set the
325 * LK_WANT_EXCL flag (preventing further shared locks), and wait for already
326 * accepted shared locks to go away.
327 */
328 int
329 lockmgr(struct lock *lkp, u_int flags, kmutex_t *interlkp)
330 {
331 int error;
332 pid_t pid;
333 lwpid_t lid;
334 int extflags;
335 cpuid_t cpu_num;
336 struct lwp *l = curlwp;
337 int lock_shutdown_noblock = 0;
338 int s = 0;
339
340 error = 0;
341
342 /* LK_RETRY is for vn_lock, not for lockmgr. */
343 KASSERT((flags & LK_RETRY) == 0);
344 KASSERT((l->l_pflag & LP_INTR) == 0 || panicstr != NULL);
345
346 mutex_enter(&lkp->lk_interlock);
347 if (flags & LK_INTERLOCK)
348 mutex_exit(interlkp);
349 extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK;
350
351 if (l == NULL) {
352 if (!doing_shutdown) {
353 panic("lockmgr: no context");
354 } else {
355 l = &lwp0;
356 if (panicstr && (!(flags & LK_NOWAIT))) {
357 flags |= LK_NOWAIT;
358 lock_shutdown_noblock = 1;
359 }
360 }
361 }
362 lid = l->l_lid;
363 pid = l->l_proc->p_pid;
364 cpu_num = cpu_number();
365
366 /*
367 * Once a lock has drained, the LK_DRAINING flag is set and an
368 * exclusive lock is returned. The only valid operation thereafter
369 * is a single release of that exclusive lock. This final release
370 * clears the LK_DRAINING flag and sets the LK_DRAINED flag. Any
371 * further requests of any sort will result in a panic. The bits
372 * selected for these two flags are chosen so that they will be set
373 * in memory that is freed (freed memory is filled with 0xdeadbeef).
374 * The final release is permitted to give a new lease on life to
375 * the lock by specifying LK_REENABLE.
376 */
377 if (lkp->lk_flags & (LK_DRAINING|LK_DRAINED)) {
378 #ifdef DIAGNOSTIC /* { */
379 if (lkp->lk_flags & LK_DRAINED)
380 lockpanic(lkp, "lockmgr: using decommissioned lock");
381 if ((flags & LK_TYPE_MASK) != LK_RELEASE ||
382 WEHOLDIT(lkp, pid, lid, cpu_num) == 0)
383 lockpanic(lkp, "lockmgr: non-release on draining lock: %d",
384 flags & LK_TYPE_MASK);
385 #endif /* DIAGNOSTIC */ /* } */
386 lkp->lk_flags &= ~LK_DRAINING;
387 if ((flags & LK_REENABLE) == 0)
388 lkp->lk_flags |= LK_DRAINED;
389 }
390
391 switch (flags & LK_TYPE_MASK) {
392
393 case LK_SHARED:
394 if (WEHOLDIT(lkp, pid, lid, cpu_num) == 0) {
395 /*
396 * If just polling, check to see if we will block.
397 */
398 if ((extflags & LK_NOWAIT) && (lkp->lk_flags &
399 (LK_HAVE_EXCL | LK_WANT_EXCL))) {
400 error = EBUSY;
401 break;
402 }
403 /*
404 * Wait for exclusive locks to clear.
405 */
406 error = acquire(&lkp, &s, extflags, 0,
407 LK_HAVE_EXCL | LK_WANT_EXCL,
408 RETURN_ADDRESS);
409 if (error)
410 break;
411 lkp->lk_sharecount++;
412 lkp->lk_flags |= LK_SHARE_NONZERO;
413 COUNT(lkp, l, cpu_num, 1);
414 break;
415 }
416 /*
417 * We hold an exclusive lock, so downgrade it to shared.
418 * An alternative would be to fail with EDEADLK.
419 */
420 lkp->lk_sharecount++;
421 lkp->lk_flags |= LK_SHARE_NONZERO;
422 COUNT(lkp, l, cpu_num, 1);
423 /* fall into downgrade */
424
425 case LK_DOWNGRADE:
426 if (WEHOLDIT(lkp, pid, lid, cpu_num) == 0 ||
427 lkp->lk_exclusivecount == 0)
428 lockpanic(lkp, "lockmgr: not holding exclusive lock");
429 lkp->lk_sharecount += lkp->lk_exclusivecount;
430 lkp->lk_flags |= LK_SHARE_NONZERO;
431 lkp->lk_exclusivecount = 0;
432 lkp->lk_recurselevel = 0;
433 lkp->lk_flags &= ~LK_HAVE_EXCL;
434 SETHOLDER(lkp, LK_NOPROC, 0, LK_NOCPU);
435 #if defined(LOCKDEBUG)
436 lkp->lk_unlock_addr = RETURN_ADDRESS;
437 #endif
438 WAKEUP_WAITER(lkp);
439 break;
440
441 case LK_EXCLUSIVE:
442 if (WEHOLDIT(lkp, pid, lid, cpu_num)) {
443 /*
444 * Recursive lock.
445 */
446 if ((extflags & LK_CANRECURSE) == 0 &&
447 lkp->lk_recurselevel == 0) {
448 if (extflags & LK_RECURSEFAIL) {
449 error = EDEADLK;
450 break;
451 } else
452 lockpanic(lkp, "lockmgr: locking against myself");
453 }
454 lkp->lk_exclusivecount++;
455 COUNT(lkp, l, cpu_num, 1);
456 break;
457 }
458 /*
459 * If we are just polling, check to see if we will sleep.
460 */
461 if ((extflags & LK_NOWAIT) && (lkp->lk_flags &
462 (LK_HAVE_EXCL | LK_WANT_EXCL | LK_SHARE_NONZERO))) {
463 error = EBUSY;
464 break;
465 }
466 /*
467 * Try to acquire the want_exclusive flag.
468 */
469 error = acquire(&lkp, &s, extflags, 0,
470 LK_HAVE_EXCL | LK_WANT_EXCL, RETURN_ADDRESS);
471 if (error)
472 break;
473 lkp->lk_flags |= LK_WANT_EXCL;
474 /*
475 * Wait for shared locks to finish.
476 */
477 error = acquire(&lkp, &s, extflags, 0,
478 LK_HAVE_EXCL | LK_SHARE_NONZERO,
479 RETURN_ADDRESS);
480 lkp->lk_flags &= ~LK_WANT_EXCL;
481 if (error) {
482 WAKEUP_WAITER(lkp);
483 break;
484 }
485 lkp->lk_flags |= LK_HAVE_EXCL;
486 SETHOLDER(lkp, pid, lid, cpu_num);
487 #if defined(LOCKDEBUG)
488 lkp->lk_lock_addr = RETURN_ADDRESS;
489 #endif
490 if (lkp->lk_exclusivecount != 0)
491 lockpanic(lkp, "lockmgr: non-zero exclusive count");
492 lkp->lk_exclusivecount = 1;
493 COUNT(lkp, l, cpu_num, 1);
494 break;
495
496 case LK_RELEASE:
497 if (lkp->lk_exclusivecount != 0) {
498 if (WEHOLDIT(lkp, pid, lid, cpu_num) == 0) {
499 lockpanic(lkp, "lockmgr: pid %d.%d, not "
500 "exclusive lock holder %d.%d "
501 "unlocking", pid, lid,
502 lkp->lk_lockholder,
503 lkp->lk_locklwp);
504 }
505 if (lkp->lk_exclusivecount == lkp->lk_recurselevel)
506 lkp->lk_recurselevel = 0;
507 lkp->lk_exclusivecount--;
508 COUNT(lkp, l, cpu_num, -1);
509 if (lkp->lk_exclusivecount == 0) {
510 lkp->lk_flags &= ~LK_HAVE_EXCL;
511 SETHOLDER(lkp, LK_NOPROC, 0, LK_NOCPU);
512 #if defined(LOCKDEBUG)
513 lkp->lk_unlock_addr = RETURN_ADDRESS;
514 #endif
515 }
516 } else if (lkp->lk_sharecount != 0) {
517 lkp->lk_sharecount--;
518 if (lkp->lk_sharecount == 0)
519 lkp->lk_flags &= ~LK_SHARE_NONZERO;
520 COUNT(lkp, l, cpu_num, -1);
521 }
522 #ifdef DIAGNOSTIC
523 else
524 lockpanic(lkp, "lockmgr: release of unlocked lock!");
525 #endif
526 WAKEUP_WAITER(lkp);
527 break;
528
529 case LK_DRAIN:
530 /*
531 * Check that we do not already hold the lock, as it can
532 * never drain if we do. Unfortunately, we have no way to
533 * check for holding a shared lock, but at least we can
534 * check for an exclusive one.
535 */
536 if (WEHOLDIT(lkp, pid, lid, cpu_num))
537 lockpanic(lkp, "lockmgr: draining against myself");
538 /*
539 * If we are just polling, check to see if we will sleep.
540 */
541 if ((extflags & LK_NOWAIT) && (lkp->lk_flags &
542 (LK_HAVE_EXCL | LK_WANT_EXCL |
543 LK_SHARE_NONZERO | LK_WAIT_NONZERO))) {
544 error = EBUSY;
545 break;
546 }
547 error = acquire(&lkp, &s, extflags, 1,
548 LK_HAVE_EXCL | LK_WANT_EXCL |
549 LK_SHARE_NONZERO | LK_WAIT_NONZERO,
550 RETURN_ADDRESS);
551 if (error)
552 break;
553 lkp->lk_flags |= LK_HAVE_EXCL;
554 if ((extflags & LK_RESURRECT) == 0)
555 lkp->lk_flags |= LK_DRAINING;
556 SETHOLDER(lkp, pid, lid, cpu_num);
557 #if defined(LOCKDEBUG)
558 lkp->lk_lock_addr = RETURN_ADDRESS;
559 #endif
560 lkp->lk_exclusivecount = 1;
561 COUNT(lkp, l, cpu_num, 1);
562 break;
563
564 default:
565 mutex_exit(&lkp->lk_interlock);
566 lockpanic(lkp, "lockmgr: unknown locktype request %d",
567 flags & LK_TYPE_MASK);
568 /* NOTREACHED */
569 }
570 if ((lkp->lk_flags & LK_WAITDRAIN) != 0 &&
571 ((lkp->lk_flags &
572 (LK_HAVE_EXCL | LK_WANT_EXCL |
573 LK_SHARE_NONZERO | LK_WAIT_NONZERO)) == 0)) {
574 lkp->lk_flags &= ~LK_WAITDRAIN;
575 wakeup(&lkp->lk_flags);
576 }
577 /*
578 * Note that this panic will be a recursive panic, since
579 * we only set lock_shutdown_noblock above if panicstr != NULL.
580 */
581 if (error && lock_shutdown_noblock)
582 lockpanic(lkp, "lockmgr: deadlock (see previous panic)");
583
584 mutex_exit(&lkp->lk_interlock);
585 return (error);
586 }
587
588 /*
589 * Print out information about state of a lock. Used by VOP_PRINT
590 * routines to display ststus about contained locks.
591 */
592 void
593 lockmgr_printinfo(struct lock *lkp)
594 {
595
596 if (lkp->lk_sharecount)
597 printf(" lock type %s: SHARED (count %d)", lkp->lk_wmesg,
598 lkp->lk_sharecount);
599 else if (lkp->lk_flags & LK_HAVE_EXCL) {
600 printf(" lock type %s: EXCL (count %d) by ",
601 lkp->lk_wmesg, lkp->lk_exclusivecount);
602 printf("pid %d.%d", lkp->lk_lockholder,
603 lkp->lk_locklwp);
604 } else
605 printf(" not locked");
606 if (lkp->lk_waitcount > 0)
607 printf(" with %d pending", lkp->lk_waitcount);
608 }
609
610 #if defined(LOCKDEBUG)
611 void
612 assert_sleepable(struct simplelock *interlock, const char *msg)
613 {
614
615 if (panicstr != NULL)
616 return;
617 LOCKDEBUG_BARRIER(&kernel_lock, 1);
618 if (CURCPU_IDLE_P() && !cold) {
619 panic("assert_sleepable: idle");
620 }
621 }
622 #endif
623
624 /*
625 * rump doesn't need the kernel lock so force it out. We cannot
626 * currently easily include it for compilation because of
627 * a) SPINLOCK_* b) membar_producer(). They are defined in different
628 * places / way for each arch, so just simply do not bother to
629 * fight a lot for no gain (i.e. pain but still no gain).
630 */
631 #ifndef _RUMPKERNEL
632 /*
633 * Functions for manipulating the kernel_lock. We put them here
634 * so that they show up in profiles.
635 */
636
637 #define _KERNEL_LOCK_ABORT(msg) \
638 LOCKDEBUG_ABORT(&kernel_lock, &_kernel_lock_ops, __func__, msg)
639
640 #ifdef LOCKDEBUG
641 #define _KERNEL_LOCK_ASSERT(cond) \
642 do { \
643 if (!(cond)) \
644 _KERNEL_LOCK_ABORT("assertion failed: " #cond); \
645 } while (/* CONSTCOND */ 0)
646 #else
647 #define _KERNEL_LOCK_ASSERT(cond) /* nothing */
648 #endif
649
650 void _kernel_lock_dump(volatile void *);
651
652 lockops_t _kernel_lock_ops = {
653 "Kernel lock",
654 0,
655 _kernel_lock_dump
656 };
657
658 /*
659 * Initialize the kernel lock.
660 */
661 void
662 kernel_lock_init(void)
663 {
664
665 __cpu_simple_lock_init(&kernel_lock);
666 kernel_lock_dodebug = LOCKDEBUG_ALLOC(&kernel_lock, &_kernel_lock_ops,
667 RETURN_ADDRESS);
668 }
669
670 /*
671 * Print debugging information about the kernel lock.
672 */
673 void
674 _kernel_lock_dump(volatile void *junk)
675 {
676 struct cpu_info *ci = curcpu();
677
678 (void)junk;
679
680 printf_nolog("curcpu holds : %18d wanted by: %#018lx\n",
681 ci->ci_biglock_count, (long)ci->ci_biglock_wanted);
682 }
683
684 /*
685 * Acquire 'nlocks' holds on the kernel lock. If 'l' is non-null, the
686 * acquisition is from process context.
687 */
688 void
689 _kernel_lock(int nlocks, struct lwp *l)
690 {
691 struct cpu_info *ci = curcpu();
692 LOCKSTAT_TIMER(spintime);
693 LOCKSTAT_FLAG(lsflag);
694 struct lwp *owant;
695 #ifdef LOCKDEBUG
696 u_int spins;
697 #endif
698 int s;
699
700 if (nlocks == 0)
701 return;
702 _KERNEL_LOCK_ASSERT(nlocks > 0);
703
704 l = curlwp;
705
706 if (ci->ci_biglock_count != 0) {
707 _KERNEL_LOCK_ASSERT(__SIMPLELOCK_LOCKED_P(&kernel_lock));
708 ci->ci_biglock_count += nlocks;
709 l->l_blcnt += nlocks;
710 return;
711 }
712
713 _KERNEL_LOCK_ASSERT(l->l_blcnt == 0);
714 LOCKDEBUG_WANTLOCK(kernel_lock_dodebug, &kernel_lock, RETURN_ADDRESS,
715 0);
716
717 s = splvm();
718 if (__cpu_simple_lock_try(&kernel_lock)) {
719 ci->ci_biglock_count = nlocks;
720 l->l_blcnt = nlocks;
721 LOCKDEBUG_LOCKED(kernel_lock_dodebug, &kernel_lock,
722 RETURN_ADDRESS, 0);
723 splx(s);
724 return;
725 }
726
727 LOCKSTAT_ENTER(lsflag);
728 LOCKSTAT_START_TIMER(lsflag, spintime);
729
730 /*
731 * Before setting ci_biglock_wanted we must post a store
732 * fence (see kern_mutex.c). This is accomplished by the
733 * __cpu_simple_lock_try() above.
734 */
735 owant = ci->ci_biglock_wanted;
736 ci->ci_biglock_wanted = curlwp; /* XXXAD */
737
738 #ifdef LOCKDEBUG
739 spins = 0;
740 #endif
741
742 do {
743 splx(s);
744 while (__SIMPLELOCK_LOCKED_P(&kernel_lock)) {
745 #ifdef LOCKDEBUG
746 if (SPINLOCK_SPINOUT(spins))
747 _KERNEL_LOCK_ABORT("spinout");
748 #endif
749 SPINLOCK_BACKOFF_HOOK;
750 SPINLOCK_SPIN_HOOK;
751 }
752 (void)splvm();
753 } while (!__cpu_simple_lock_try(&kernel_lock));
754
755 ci->ci_biglock_wanted = owant;
756 ci->ci_biglock_count = nlocks;
757 l->l_blcnt = nlocks;
758 LOCKSTAT_STOP_TIMER(lsflag, spintime);
759 LOCKDEBUG_LOCKED(kernel_lock_dodebug, &kernel_lock, RETURN_ADDRESS, 0);
760 splx(s);
761
762 /*
763 * Again, another store fence is required (see kern_mutex.c).
764 */
765 membar_producer();
766 if (owant == NULL) {
767 LOCKSTAT_EVENT(lsflag, &kernel_lock, LB_KERNEL_LOCK | LB_SPIN,
768 1, spintime);
769 }
770 LOCKSTAT_EXIT(lsflag);
771 }
772
773 /*
774 * Release 'nlocks' holds on the kernel lock. If 'nlocks' is zero, release
775 * all holds. If 'l' is non-null, the release is from process context.
776 */
777 void
778 _kernel_unlock(int nlocks, struct lwp *l, int *countp)
779 {
780 struct cpu_info *ci = curcpu();
781 u_int olocks;
782 int s;
783
784 l = curlwp;
785
786 _KERNEL_LOCK_ASSERT(nlocks < 2);
787
788 olocks = l->l_blcnt;
789
790 if (olocks == 0) {
791 _KERNEL_LOCK_ASSERT(nlocks <= 0);
792 if (countp != NULL)
793 *countp = 0;
794 return;
795 }
796
797 _KERNEL_LOCK_ASSERT(__SIMPLELOCK_LOCKED_P(&kernel_lock));
798
799 if (nlocks == 0)
800 nlocks = olocks;
801 else if (nlocks == -1) {
802 nlocks = 1;
803 _KERNEL_LOCK_ASSERT(olocks == 1);
804 }
805
806 _KERNEL_LOCK_ASSERT(ci->ci_biglock_count >= l->l_blcnt);
807
808 l->l_blcnt -= nlocks;
809 if (ci->ci_biglock_count == nlocks) {
810 s = splvm();
811 LOCKDEBUG_UNLOCKED(kernel_lock_dodebug, &kernel_lock,
812 RETURN_ADDRESS, 0);
813 ci->ci_biglock_count = 0;
814 __cpu_simple_unlock(&kernel_lock);
815 splx(s);
816 } else
817 ci->ci_biglock_count -= nlocks;
818
819 if (countp != NULL)
820 *countp = olocks;
821 }
822 #endif /* !_RUMPKERNEL */
823