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