kern_lock.c revision 1.124 1 /* $NetBSD: kern_lock.c,v 1.124 2007/10/31 15:36:07 pooka 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.124 2007/10/31 15:36:07 pooka 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/lockdebug.h>
88 #include <sys/cpu.h>
89 #include <sys/syslog.h>
90
91 #include <machine/stdarg.h>
92
93 #include <dev/lockstat.h>
94
95 /*
96 * note that stdarg.h and the ansi style va_start macro is used for both
97 * ansi and traditional c compiles.
98 * XXX: this requires that stdarg.h define: va_alist and va_dcl
99 */
100 void lock_printf(const char *fmt, ...)
101 __attribute__((__format__(__printf__,1,2)));
102
103 static int acquire(struct lock **, int *, int, int, int, uintptr_t);
104
105 int lock_debug_syslog = 0; /* defaults to printf, but can be patched */
106 int kernel_lock_id;
107 __cpu_simple_lock_t kernel_lock;
108
109 #if defined(LOCKDEBUG) || defined(DIAGNOSTIC) /* { */
110 #define COUNT(lkp, l, cpu_id, x) (l)->l_locks += (x)
111 #else
112 #define COUNT(lkp, p, cpu_id, x)
113 #endif /* LOCKDEBUG || DIAGNOSTIC */ /* } */
114
115 #define RETURN_ADDRESS ((uintptr_t)__builtin_return_address(0))
116
117 /*
118 * Acquire a resource.
119 */
120 static int
121 acquire(struct lock **lkpp, int *s, int extflags,
122 int drain, int wanted, uintptr_t ra)
123 {
124 int error;
125 struct lock *lkp = *lkpp;
126 LOCKSTAT_TIMER(slptime);
127 LOCKSTAT_FLAG(lsflag);
128
129 KASSERT(drain || (wanted & LK_WAIT_NONZERO) == 0);
130
131 LOCKSTAT_ENTER(lsflag);
132
133 for (error = 0; (lkp->lk_flags & wanted) != 0; ) {
134 if (drain)
135 lkp->lk_flags |= LK_WAITDRAIN;
136 else {
137 lkp->lk_waitcount++;
138 lkp->lk_flags |= LK_WAIT_NONZERO;
139 }
140 LOCKSTAT_START_TIMER(lsflag, slptime);
141 error = ltsleep(drain ? (void *)&lkp->lk_flags : (void *)lkp,
142 lkp->lk_prio, lkp->lk_wmesg, lkp->lk_timo,
143 &lkp->lk_interlock);
144 LOCKSTAT_STOP_TIMER(lsflag, slptime);
145 LOCKSTAT_EVENT_RA(lsflag, (void *)(uintptr_t)lkp,
146 LB_LOCKMGR | LB_SLEEP1, 1, slptime, ra);
147 if (!drain) {
148 lkp->lk_waitcount--;
149 if (lkp->lk_waitcount == 0)
150 lkp->lk_flags &= ~LK_WAIT_NONZERO;
151 }
152 if (error)
153 break;
154 if (extflags & LK_SLEEPFAIL) {
155 error = ENOLCK;
156 break;
157 }
158 }
159
160 LOCKSTAT_EXIT(lsflag);
161
162 return error;
163 }
164
165 #define SETHOLDER(lkp, pid, lid, cpu_id) \
166 do { \
167 (lkp)->lk_lockholder = pid; \
168 (lkp)->lk_locklwp = lid; \
169 } while (/*CONSTCOND*/0)
170
171 #define WEHOLDIT(lkp, pid, lid, cpu_id) \
172 ((lkp)->lk_lockholder == (pid) && (lkp)->lk_locklwp == (lid))
173
174 #define WAKEUP_WAITER(lkp) \
175 do { \
176 if (((lkp)->lk_flags & LK_WAIT_NONZERO) != 0) { \
177 wakeup((lkp)); \
178 } \
179 } while (/*CONSTCOND*/0)
180
181 #if defined(LOCKDEBUG)
182 /*
183 * Lock debug printing routine; can be configured to print to console
184 * or log to syslog.
185 */
186 void
187 lock_printf(const char *fmt, ...)
188 {
189 char b[150];
190 va_list ap;
191
192 va_start(ap, fmt);
193 if (lock_debug_syslog)
194 vlog(LOG_DEBUG, fmt, ap);
195 else {
196 vsnprintf(b, sizeof(b), fmt, ap);
197 printf_nolog("%s", b);
198 }
199 va_end(ap);
200 }
201 #endif /* LOCKDEBUG */
202
203 static void
204 lockpanic(struct lock *lkp, const char *fmt, ...)
205 {
206 char s[150], b[150];
207 static const char *locktype[] = {
208 "*0*", "shared", "exclusive", "upgrade", "exclupgrade",
209 "downgrade", "release", "drain", "exclother", "*9*",
210 "*10*", "*11*", "*12*", "*13*", "*14*", "*15*"
211 };
212 va_list ap;
213 va_start(ap, fmt);
214 vsnprintf(s, sizeof(s), fmt, ap);
215 va_end(ap);
216 bitmask_snprintf(lkp->lk_flags, __LK_FLAG_BITS, b, sizeof(b));
217 panic("%s ("
218 "type %s flags %s, sharecount %d, exclusivecount %d, "
219 "recurselevel %d, waitcount %d, wmesg %s"
220 ", lock_addr %p, unlock_addr %p"
221 ")\n",
222 s, locktype[lkp->lk_flags & LK_TYPE_MASK],
223 b, lkp->lk_sharecount, lkp->lk_exclusivecount,
224 lkp->lk_recurselevel, lkp->lk_waitcount, lkp->lk_wmesg,
225 (void *)lkp->lk_lock_addr, (void *)lkp->lk_unlock_addr
226 );
227 }
228
229 /*
230 * Initialize a lock; required before use.
231 */
232 void
233 lockinit(struct lock *lkp, pri_t prio, const char *wmesg, int timo, int flags)
234 {
235
236 memset(lkp, 0, sizeof(struct lock));
237 lkp->lk_flags = flags & LK_EXTFLG_MASK;
238 simple_lock_init(&lkp->lk_interlock);
239 lkp->lk_lockholder = LK_NOPROC;
240 lkp->lk_prio = prio;
241 lkp->lk_timo = timo;
242 lkp->lk_wmesg = wmesg;
243 lkp->lk_lock_addr = 0;
244 lkp->lk_unlock_addr = 0;
245 }
246
247 void
248 lockdestroy(struct lock *lkp)
249 {
250
251 /* nothing yet */
252 }
253
254 /*
255 * Determine the status of a lock.
256 */
257 int
258 lockstatus(struct lock *lkp)
259 {
260 int lock_type = 0;
261 struct lwp *l = curlwp; /* XXX */
262 pid_t pid;
263 lwpid_t lid;
264 cpuid_t cpu_num;
265
266 if (l == NULL) {
267 cpu_num = cpu_number();
268 pid = LK_KERNPROC;
269 lid = 0;
270 } else {
271 cpu_num = LK_NOCPU;
272 pid = l->l_proc->p_pid;
273 lid = l->l_lid;
274 }
275
276 simple_lock(&lkp->lk_interlock);
277 if (lkp->lk_exclusivecount != 0) {
278 if (WEHOLDIT(lkp, pid, lid, cpu_num))
279 lock_type = LK_EXCLUSIVE;
280 else
281 lock_type = LK_EXCLOTHER;
282 } else if (lkp->lk_sharecount != 0)
283 lock_type = LK_SHARED;
284 else if (lkp->lk_flags & (LK_WANT_EXCL | LK_WANT_UPGRADE))
285 lock_type = LK_EXCLOTHER;
286 simple_unlock(&lkp->lk_interlock);
287 return (lock_type);
288 }
289
290 /*
291 * XXX XXX kludge around another kludge..
292 *
293 * vfs_shutdown() may be called from interrupt context, either as a result
294 * of a panic, or from the debugger. It proceeds to call
295 * sys_sync(&proc0, ...), pretending its running on behalf of proc0
296 *
297 * We would like to make an attempt to sync the filesystems in this case, so
298 * if this happens, we treat attempts to acquire locks specially.
299 * All locks are acquired on behalf of proc0.
300 *
301 * If we've already paniced, we don't block waiting for locks, but
302 * just barge right ahead since we're already going down in flames.
303 */
304
305 /*
306 * Set, change, or release a lock.
307 *
308 * Shared requests increment the shared count. Exclusive requests set the
309 * LK_WANT_EXCL flag (preventing further shared locks), and wait for already
310 * accepted shared locks and shared-to-exclusive upgrades to go away.
311 */
312 int
313 lockmgr(struct lock *lkp, u_int flags, struct simplelock *interlkp)
314 {
315 int error;
316 pid_t pid;
317 lwpid_t lid;
318 int extflags;
319 cpuid_t cpu_num;
320 struct lwp *l = curlwp;
321 int lock_shutdown_noblock = 0;
322 int s = 0;
323
324 error = 0;
325
326 /* LK_RETRY is for vn_lock, not for lockmgr. */
327 KASSERT((flags & LK_RETRY) == 0);
328 KASSERT((l->l_flag & LW_INTR) == 0 || panicstr != NULL);
329
330 simple_lock(&lkp->lk_interlock);
331 if (flags & LK_INTERLOCK)
332 simple_unlock(interlkp);
333 extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK;
334
335 if (l == NULL) {
336 if (!doing_shutdown) {
337 panic("lockmgr: no context");
338 } else {
339 l = &lwp0;
340 if (panicstr && (!(flags & LK_NOWAIT))) {
341 flags |= LK_NOWAIT;
342 lock_shutdown_noblock = 1;
343 }
344 }
345 }
346 lid = l->l_lid;
347 pid = l->l_proc->p_pid;
348 cpu_num = cpu_number();
349
350 /*
351 * Once a lock has drained, the LK_DRAINING flag is set and an
352 * exclusive lock is returned. The only valid operation thereafter
353 * is a single release of that exclusive lock. This final release
354 * clears the LK_DRAINING flag and sets the LK_DRAINED flag. Any
355 * further requests of any sort will result in a panic. The bits
356 * selected for these two flags are chosen so that they will be set
357 * in memory that is freed (freed memory is filled with 0xdeadbeef).
358 * The final release is permitted to give a new lease on life to
359 * the lock by specifying LK_REENABLE.
360 */
361 if (lkp->lk_flags & (LK_DRAINING|LK_DRAINED)) {
362 #ifdef DIAGNOSTIC /* { */
363 if (lkp->lk_flags & LK_DRAINED)
364 lockpanic(lkp, "lockmgr: using decommissioned lock");
365 if ((flags & LK_TYPE_MASK) != LK_RELEASE ||
366 WEHOLDIT(lkp, pid, lid, cpu_num) == 0)
367 lockpanic(lkp, "lockmgr: non-release on draining lock: %d",
368 flags & LK_TYPE_MASK);
369 #endif /* DIAGNOSTIC */ /* } */
370 lkp->lk_flags &= ~LK_DRAINING;
371 if ((flags & LK_REENABLE) == 0)
372 lkp->lk_flags |= LK_DRAINED;
373 }
374
375 switch (flags & LK_TYPE_MASK) {
376
377 case LK_SHARED:
378 if (WEHOLDIT(lkp, pid, lid, cpu_num) == 0) {
379 /*
380 * If just polling, check to see if we will block.
381 */
382 if ((extflags & LK_NOWAIT) && (lkp->lk_flags &
383 (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE))) {
384 error = EBUSY;
385 break;
386 }
387 /*
388 * Wait for exclusive locks and upgrades to clear.
389 */
390 error = acquire(&lkp, &s, extflags, 0,
391 LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE,
392 RETURN_ADDRESS);
393 if (error)
394 break;
395 lkp->lk_sharecount++;
396 lkp->lk_flags |= LK_SHARE_NONZERO;
397 COUNT(lkp, l, cpu_num, 1);
398 break;
399 }
400 /*
401 * We hold an exclusive lock, so downgrade it to shared.
402 * An alternative would be to fail with EDEADLK.
403 */
404 lkp->lk_sharecount++;
405 lkp->lk_flags |= LK_SHARE_NONZERO;
406 COUNT(lkp, l, cpu_num, 1);
407 /* fall into downgrade */
408
409 case LK_DOWNGRADE:
410 if (WEHOLDIT(lkp, pid, lid, cpu_num) == 0 ||
411 lkp->lk_exclusivecount == 0)
412 lockpanic(lkp, "lockmgr: not holding exclusive lock");
413 lkp->lk_sharecount += lkp->lk_exclusivecount;
414 lkp->lk_flags |= LK_SHARE_NONZERO;
415 lkp->lk_exclusivecount = 0;
416 lkp->lk_recurselevel = 0;
417 lkp->lk_flags &= ~LK_HAVE_EXCL;
418 SETHOLDER(lkp, LK_NOPROC, 0, LK_NOCPU);
419 #if defined(LOCKDEBUG)
420 lkp->lk_unlock_addr = RETURN_ADDRESS;
421 #endif
422 WAKEUP_WAITER(lkp);
423 break;
424
425 case LK_EXCLUPGRADE:
426 /*
427 * If another process is ahead of us to get an upgrade,
428 * then we want to fail rather than have an intervening
429 * exclusive access.
430 */
431 if (lkp->lk_flags & LK_WANT_UPGRADE) {
432 lkp->lk_sharecount--;
433 if (lkp->lk_sharecount == 0)
434 lkp->lk_flags &= ~LK_SHARE_NONZERO;
435 COUNT(lkp, l, cpu_num, -1);
436 error = EBUSY;
437 break;
438 }
439 /* fall into normal upgrade */
440
441 case LK_UPGRADE:
442 /*
443 * Upgrade a shared lock to an exclusive one. If another
444 * shared lock has already requested an upgrade to an
445 * exclusive lock, our shared lock is released and an
446 * exclusive lock is requested (which will be granted
447 * after the upgrade). If we return an error, the file
448 * will always be unlocked.
449 */
450 if (WEHOLDIT(lkp, pid, lid, cpu_num) || lkp->lk_sharecount <= 0)
451 lockpanic(lkp, "lockmgr: upgrade exclusive lock");
452 lkp->lk_sharecount--;
453 if (lkp->lk_sharecount == 0)
454 lkp->lk_flags &= ~LK_SHARE_NONZERO;
455 COUNT(lkp, l, cpu_num, -1);
456 /*
457 * If we are just polling, check to see if we will block.
458 */
459 if ((extflags & LK_NOWAIT) &&
460 ((lkp->lk_flags & LK_WANT_UPGRADE) ||
461 lkp->lk_sharecount > 1)) {
462 error = EBUSY;
463 break;
464 }
465 if ((lkp->lk_flags & LK_WANT_UPGRADE) == 0) {
466 /*
467 * We are first shared lock to request an upgrade, so
468 * request upgrade and wait for the shared count to
469 * drop to zero, then take exclusive lock.
470 */
471 lkp->lk_flags |= LK_WANT_UPGRADE;
472 error = acquire(&lkp, &s, extflags, 0, LK_SHARE_NONZERO,
473 RETURN_ADDRESS);
474 lkp->lk_flags &= ~LK_WANT_UPGRADE;
475 if (error) {
476 WAKEUP_WAITER(lkp);
477 break;
478 }
479 lkp->lk_flags |= LK_HAVE_EXCL;
480 SETHOLDER(lkp, pid, lid, cpu_num);
481 #if defined(LOCKDEBUG)
482 lkp->lk_lock_addr = RETURN_ADDRESS;
483 #endif
484 if (lkp->lk_exclusivecount != 0)
485 lockpanic(lkp, "lockmgr: non-zero exclusive count");
486 lkp->lk_exclusivecount = 1;
487 if (extflags & LK_SETRECURSE)
488 lkp->lk_recurselevel = 1;
489 COUNT(lkp, l, cpu_num, 1);
490 break;
491 }
492 /*
493 * Someone else has requested upgrade. Release our shared
494 * lock, awaken upgrade requestor if we are the last shared
495 * lock, then request an exclusive lock.
496 */
497 if (lkp->lk_sharecount == 0)
498 WAKEUP_WAITER(lkp);
499 /* fall into exclusive request */
500
501 case LK_EXCLUSIVE:
502 if (WEHOLDIT(lkp, pid, lid, cpu_num)) {
503 /*
504 * Recursive lock.
505 */
506 if ((extflags & LK_CANRECURSE) == 0 &&
507 lkp->lk_recurselevel == 0) {
508 if (extflags & LK_RECURSEFAIL) {
509 error = EDEADLK;
510 break;
511 } else
512 lockpanic(lkp, "lockmgr: locking against myself");
513 }
514 lkp->lk_exclusivecount++;
515 if (extflags & LK_SETRECURSE &&
516 lkp->lk_recurselevel == 0)
517 lkp->lk_recurselevel = lkp->lk_exclusivecount;
518 COUNT(lkp, l, cpu_num, 1);
519 break;
520 }
521 /*
522 * If we are just polling, check to see if we will sleep.
523 */
524 if ((extflags & LK_NOWAIT) && (lkp->lk_flags &
525 (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE |
526 LK_SHARE_NONZERO))) {
527 error = EBUSY;
528 break;
529 }
530 /*
531 * Try to acquire the want_exclusive flag.
532 */
533 error = acquire(&lkp, &s, extflags, 0,
534 LK_HAVE_EXCL | LK_WANT_EXCL, RETURN_ADDRESS);
535 if (error)
536 break;
537 lkp->lk_flags |= LK_WANT_EXCL;
538 /*
539 * Wait for shared locks and upgrades to finish.
540 */
541 error = acquire(&lkp, &s, extflags, 0,
542 LK_HAVE_EXCL | LK_WANT_UPGRADE | LK_SHARE_NONZERO,
543 RETURN_ADDRESS);
544 lkp->lk_flags &= ~LK_WANT_EXCL;
545 if (error) {
546 WAKEUP_WAITER(lkp);
547 break;
548 }
549 lkp->lk_flags |= LK_HAVE_EXCL;
550 SETHOLDER(lkp, pid, lid, cpu_num);
551 #if defined(LOCKDEBUG)
552 lkp->lk_lock_addr = RETURN_ADDRESS;
553 #endif
554 if (lkp->lk_exclusivecount != 0)
555 lockpanic(lkp, "lockmgr: non-zero exclusive count");
556 lkp->lk_exclusivecount = 1;
557 if (extflags & LK_SETRECURSE)
558 lkp->lk_recurselevel = 1;
559 COUNT(lkp, l, cpu_num, 1);
560 break;
561
562 case LK_RELEASE:
563 if (lkp->lk_exclusivecount != 0) {
564 if (WEHOLDIT(lkp, pid, lid, cpu_num) == 0) {
565 lockpanic(lkp, "lockmgr: pid %d.%d, not "
566 "exclusive lock holder %d.%d "
567 "unlocking", pid, lid,
568 lkp->lk_lockholder,
569 lkp->lk_locklwp);
570 }
571 if (lkp->lk_exclusivecount == lkp->lk_recurselevel)
572 lkp->lk_recurselevel = 0;
573 lkp->lk_exclusivecount--;
574 COUNT(lkp, l, cpu_num, -1);
575 if (lkp->lk_exclusivecount == 0) {
576 lkp->lk_flags &= ~LK_HAVE_EXCL;
577 SETHOLDER(lkp, LK_NOPROC, 0, LK_NOCPU);
578 #if defined(LOCKDEBUG)
579 lkp->lk_unlock_addr = RETURN_ADDRESS;
580 #endif
581 }
582 } else if (lkp->lk_sharecount != 0) {
583 lkp->lk_sharecount--;
584 if (lkp->lk_sharecount == 0)
585 lkp->lk_flags &= ~LK_SHARE_NONZERO;
586 COUNT(lkp, l, cpu_num, -1);
587 }
588 #ifdef DIAGNOSTIC
589 else
590 lockpanic(lkp, "lockmgr: release of unlocked lock!");
591 #endif
592 WAKEUP_WAITER(lkp);
593 break;
594
595 case LK_DRAIN:
596 /*
597 * Check that we do not already hold the lock, as it can
598 * never drain if we do. Unfortunately, we have no way to
599 * check for holding a shared lock, but at least we can
600 * check for an exclusive one.
601 */
602 if (WEHOLDIT(lkp, pid, lid, cpu_num))
603 lockpanic(lkp, "lockmgr: draining against myself");
604 /*
605 * If we are just polling, check to see if we will sleep.
606 */
607 if ((extflags & LK_NOWAIT) && (lkp->lk_flags &
608 (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE |
609 LK_SHARE_NONZERO | LK_WAIT_NONZERO))) {
610 error = EBUSY;
611 break;
612 }
613 error = acquire(&lkp, &s, extflags, 1,
614 LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE |
615 LK_SHARE_NONZERO | LK_WAIT_NONZERO,
616 RETURN_ADDRESS);
617 if (error)
618 break;
619 lkp->lk_flags |= LK_HAVE_EXCL;
620 if ((extflags & LK_RESURRECT) == 0)
621 lkp->lk_flags |= LK_DRAINING;
622 SETHOLDER(lkp, pid, lid, cpu_num);
623 #if defined(LOCKDEBUG)
624 lkp->lk_lock_addr = RETURN_ADDRESS;
625 #endif
626 lkp->lk_exclusivecount = 1;
627 /* XXX unlikely that we'd want this */
628 if (extflags & LK_SETRECURSE)
629 lkp->lk_recurselevel = 1;
630 COUNT(lkp, l, cpu_num, 1);
631 break;
632
633 default:
634 simple_unlock(&lkp->lk_interlock);
635 lockpanic(lkp, "lockmgr: unknown locktype request %d",
636 flags & LK_TYPE_MASK);
637 /* NOTREACHED */
638 }
639 if ((lkp->lk_flags & LK_WAITDRAIN) != 0 &&
640 ((lkp->lk_flags &
641 (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE |
642 LK_SHARE_NONZERO | LK_WAIT_NONZERO)) == 0)) {
643 lkp->lk_flags &= ~LK_WAITDRAIN;
644 wakeup(&lkp->lk_flags);
645 }
646 /*
647 * Note that this panic will be a recursive panic, since
648 * we only set lock_shutdown_noblock above if panicstr != NULL.
649 */
650 if (error && lock_shutdown_noblock)
651 lockpanic(lkp, "lockmgr: deadlock (see previous panic)");
652
653 simple_unlock(&lkp->lk_interlock);
654 return (error);
655 }
656
657 /*
658 * Print out information about state of a lock. Used by VOP_PRINT
659 * routines to display ststus about contained locks.
660 */
661 void
662 lockmgr_printinfo(struct lock *lkp)
663 {
664
665 if (lkp->lk_sharecount)
666 printf(" lock type %s: SHARED (count %d)", lkp->lk_wmesg,
667 lkp->lk_sharecount);
668 else if (lkp->lk_flags & LK_HAVE_EXCL) {
669 printf(" lock type %s: EXCL (count %d) by ",
670 lkp->lk_wmesg, lkp->lk_exclusivecount);
671 printf("pid %d.%d", lkp->lk_lockholder,
672 lkp->lk_locklwp);
673 } else
674 printf(" not locked");
675 if (lkp->lk_waitcount > 0)
676 printf(" with %d pending", lkp->lk_waitcount);
677 }
678
679 #if defined(LOCKDEBUG)
680 void
681 assert_sleepable(struct simplelock *interlock, const char *msg)
682 {
683
684 if (panicstr != NULL)
685 return;
686 LOCKDEBUG_BARRIER(&kernel_lock, 1);
687 if (CURCPU_IDLE_P()) {
688 panic("assert_sleepable: idle");
689 }
690 }
691 #endif
692
693 /*
694 * rump doesn't need the kernel lock so force it out. We cannot
695 * currently easily include it for compilation because of
696 * a) SPINLOCK_* b) mb_write(). They are defined in different
697 * places / way for each arch, so just simply do not bother to
698 * fight a lot for no gain (i.e. pain but still no gain).
699 */
700 #ifndef _RUMPKERNEL
701 /*
702 * Functions for manipulating the kernel_lock. We put them here
703 * so that they show up in profiles.
704 */
705
706 #define _KERNEL_LOCK_ABORT(msg) \
707 LOCKDEBUG_ABORT(kernel_lock_id, &kernel_lock, &_kernel_lock_ops, \
708 __func__, msg)
709
710 #ifdef LOCKDEBUG
711 #define _KERNEL_LOCK_ASSERT(cond) \
712 do { \
713 if (!(cond)) \
714 _KERNEL_LOCK_ABORT("assertion failed: " #cond); \
715 } while (/* CONSTCOND */ 0)
716 #else
717 #define _KERNEL_LOCK_ASSERT(cond) /* nothing */
718 #endif
719
720 void _kernel_lock_dump(volatile void *);
721
722 lockops_t _kernel_lock_ops = {
723 "Kernel lock",
724 0,
725 _kernel_lock_dump
726 };
727
728 /*
729 * Initialize the kernel lock.
730 */
731 void
732 kernel_lock_init(void)
733 {
734
735 __cpu_simple_lock_init(&kernel_lock);
736 kernel_lock_id = LOCKDEBUG_ALLOC(&kernel_lock, &_kernel_lock_ops,
737 RETURN_ADDRESS);
738 }
739
740 /*
741 * Print debugging information about the kernel lock.
742 */
743 void
744 _kernel_lock_dump(volatile void *junk)
745 {
746 struct cpu_info *ci = curcpu();
747
748 (void)junk;
749
750 printf_nolog("curcpu holds : %18d wanted by: %#018lx\n",
751 ci->ci_biglock_count, (long)ci->ci_biglock_wanted);
752 }
753
754 /*
755 * Acquire 'nlocks' holds on the kernel lock. If 'l' is non-null, the
756 * acquisition is from process context.
757 */
758 void
759 _kernel_lock(int nlocks, struct lwp *l)
760 {
761 struct cpu_info *ci = curcpu();
762 LOCKSTAT_TIMER(spintime);
763 LOCKSTAT_FLAG(lsflag);
764 struct lwp *owant;
765 #ifdef LOCKDEBUG
766 u_int spins;
767 #endif
768 int s;
769
770 if (nlocks == 0)
771 return;
772 _KERNEL_LOCK_ASSERT(nlocks > 0);
773
774 l = curlwp;
775
776 if (ci->ci_biglock_count != 0) {
777 _KERNEL_LOCK_ASSERT(__SIMPLELOCK_LOCKED_P(&kernel_lock));
778 ci->ci_biglock_count += nlocks;
779 l->l_blcnt += nlocks;
780 return;
781 }
782
783 _KERNEL_LOCK_ASSERT(l->l_blcnt == 0);
784 LOCKDEBUG_WANTLOCK(kernel_lock_id, RETURN_ADDRESS, 0);
785
786 s = splvm();
787 if (__cpu_simple_lock_try(&kernel_lock)) {
788 ci->ci_biglock_count = nlocks;
789 l->l_blcnt = nlocks;
790 LOCKDEBUG_LOCKED(kernel_lock_id, RETURN_ADDRESS, 0);
791 splx(s);
792 return;
793 }
794
795 LOCKSTAT_ENTER(lsflag);
796 LOCKSTAT_START_TIMER(lsflag, spintime);
797
798 /*
799 * Before setting ci_biglock_wanted we must post a store
800 * fence (see kern_mutex.c). This is accomplished by the
801 * __cpu_simple_lock_try() above.
802 */
803 owant = ci->ci_biglock_wanted;
804 ci->ci_biglock_wanted = curlwp; /* XXXAD */
805
806 #ifdef LOCKDEBUG
807 spins = 0;
808 #endif
809
810 do {
811 splx(s);
812 while (__SIMPLELOCK_LOCKED_P(&kernel_lock)) {
813 #ifdef LOCKDEBUG
814 if (SPINLOCK_SPINOUT(spins))
815 _KERNEL_LOCK_ABORT("spinout");
816 #endif
817 SPINLOCK_BACKOFF_HOOK;
818 SPINLOCK_SPIN_HOOK;
819 }
820 (void)splvm();
821 } while (!__cpu_simple_lock_try(&kernel_lock));
822
823 ci->ci_biglock_wanted = owant;
824 ci->ci_biglock_count = nlocks;
825 l->l_blcnt = nlocks;
826 LOCKSTAT_STOP_TIMER(lsflag, spintime);
827 LOCKDEBUG_LOCKED(kernel_lock_id, RETURN_ADDRESS, 0);
828 splx(s);
829
830 /*
831 * Again, another store fence is required (see kern_mutex.c).
832 */
833 mb_write();
834 if (owant == NULL) {
835 LOCKSTAT_EVENT(lsflag, &kernel_lock, LB_KERNEL_LOCK | LB_SPIN,
836 1, spintime);
837 }
838 LOCKSTAT_EXIT(lsflag);
839 }
840
841 /*
842 * Release 'nlocks' holds on the kernel lock. If 'nlocks' is zero, release
843 * all holds. If 'l' is non-null, the release is from process context.
844 */
845 void
846 _kernel_unlock(int nlocks, struct lwp *l, int *countp)
847 {
848 struct cpu_info *ci = curcpu();
849 u_int olocks;
850 int s;
851
852 l = curlwp;
853
854 _KERNEL_LOCK_ASSERT(nlocks < 2);
855
856 olocks = l->l_blcnt;
857
858 if (olocks == 0) {
859 _KERNEL_LOCK_ASSERT(nlocks <= 0);
860 if (countp != NULL)
861 *countp = 0;
862 return;
863 }
864
865 _KERNEL_LOCK_ASSERT(__SIMPLELOCK_LOCKED_P(&kernel_lock));
866
867 if (nlocks == 0)
868 nlocks = olocks;
869 else if (nlocks == -1) {
870 nlocks = 1;
871 _KERNEL_LOCK_ASSERT(olocks == 1);
872 }
873
874 _KERNEL_LOCK_ASSERT(ci->ci_biglock_count >= l->l_blcnt);
875
876 l->l_blcnt -= nlocks;
877 if (ci->ci_biglock_count == nlocks) {
878 s = splvm();
879 LOCKDEBUG_UNLOCKED(kernel_lock_id, RETURN_ADDRESS, 0);
880 ci->ci_biglock_count = 0;
881 __cpu_simple_unlock(&kernel_lock);
882 splx(s);
883 } else
884 ci->ci_biglock_count -= nlocks;
885
886 if (countp != NULL)
887 *countp = olocks;
888 }
889
890 #if defined(DEBUG)
891 /*
892 * Assert that the kernel lock is held.
893 */
894 void
895 _kernel_lock_assert_locked(void)
896 {
897
898 if (!__SIMPLELOCK_LOCKED_P(&kernel_lock) ||
899 curcpu()->ci_biglock_count == 0)
900 _KERNEL_LOCK_ABORT("not locked");
901 }
902
903 void
904 _kernel_lock_assert_unlocked()
905 {
906
907 if (curcpu()->ci_biglock_count != 0)
908 _KERNEL_LOCK_ABORT("locked");
909 }
910 #endif
911 #endif /* !_RUMPKERNEL */
912