Annotation of sys/kern/kern_lock.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: kern_lock.c,v 1.30 2007/05/31 22:07:53 thib Exp $ */
2:
3: /*
4: * Copyright (c) 1995
5: * The Regents of the University of California. All rights reserved.
6: *
7: * This code contains ideas from software contributed to Berkeley by
8: * Avadis Tevanian, Jr., Michael Wayne Young, and the Mach Operating
9: * System project at Carnegie-Mellon University.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: *
35: * @(#)kern_lock.c 8.18 (Berkeley) 5/21/95
36: */
37:
38: #include <sys/param.h>
39: #include <sys/proc.h>
40: #include <sys/lock.h>
41: #include <sys/systm.h>
42: #include <sys/sched.h>
43:
44: #include <machine/cpu.h>
45:
46: #ifndef spllock
47: #define spllock() splhigh()
48: #endif
49:
50: #ifdef MULTIPROCESSOR
51: #define CPU_NUMBER() cpu_number()
52: #else
53: #define CPU_NUMBER() 0
54: #endif
55:
56: void record_stacktrace(int *, int);
57: void playback_stacktrace(int *, int);
58:
59: /*
60: * Locking primitives implementation.
61: * Locks provide shared/exclusive synchronization.
62: */
63:
64: #ifdef DDB /* { */
65: #ifdef MULTIPROCESSOR
66: int simple_lock_debugger = 1; /* more serious on MP */
67: #else
68: int simple_lock_debugger = 0;
69: #endif
70: #define SLOCK_DEBUGGER() if (simple_lock_debugger) Debugger()
71: #define SLOCK_TRACE() \
72: db_stack_trace_print((db_expr_t)__builtin_frame_address(0), \
73: TRUE, 65535, "", lock_printf);
74: #else
75: #define SLOCK_DEBUGGER() /* nothing */
76: #define SLOCK_TRACE() /* nothing */
77: #endif /* } */
78:
79: /*
80: * Acquire a resource.
81: */
82: #define ACQUIRE(lkp, error, extflags, drain, wanted) \
83: do { \
84: for (error = 0; wanted; ) { \
85: if ((drain)) \
86: (lkp)->lk_flags |= LK_WAITDRAIN; \
87: else \
88: (lkp)->lk_waitcount++; \
89: /* XXX Cast away volatile. */ \
90: error = tsleep((drain) ? \
91: (void *)&(lkp)->lk_flags : (void *)(lkp), \
92: (lkp)->lk_prio, (lkp)->lk_wmesg, (lkp)->lk_timo); \
93: if ((drain) == 0) \
94: (lkp)->lk_waitcount--; \
95: if (error) \
96: break; \
97: if ((extflags) & LK_SLEEPFAIL) { \
98: error = ENOLCK; \
99: break; \
100: } \
101: } \
102: } while (0)
103:
104: #define SETHOLDER(lkp, pid, cpu_id) \
105: (lkp)->lk_lockholder = (pid)
106:
107: #define WEHOLDIT(lkp, pid, cpu_id) \
108: (lkp)->lk_lockholder == (pid)
109:
110: #define WAKEUP_WAITER(lkp) \
111: do { \
112: if ((lkp)->lk_waitcount) { \
113: /* XXX Cast away volatile. */ \
114: wakeup((void *)(lkp)); \
115: } \
116: } while (/*CONSTCOND*/0)
117:
118: #if defined(LOCKDEBUG) /* { */
119: #if defined(MULTIPROCESSOR) /* { */
120: struct simplelock spinlock_list_slock = SIMPLELOCK_INITIALIZER;
121:
122: #define SPINLOCK_LIST_LOCK() \
123: __cpu_simple_lock(&spinlock_list_slock.lock_data)
124:
125: #define SPINLOCK_LIST_UNLOCK() \
126: __cpu_simple_unlock(&spinlock_list_slock.lock_data)
127: #else
128: #define SPINLOCK_LIST_LOCK() /* nothing */
129:
130: #define SPINLOCK_LIST_UNLOCK() /* nothing */
131: #endif /* MULTIPROCESSOR */ /* } */
132:
133: TAILQ_HEAD(, lock) spinlock_list =
134: TAILQ_HEAD_INITIALIZER(spinlock_list);
135: #endif /* LOCKDEBUG */ /* } */
136:
137: #define HAVEIT(lkp) \
138: do { \
139: } while (/*CONSTCOND*/0)
140:
141: #define DONTHAVEIT(lkp) \
142: do { \
143: } while (/*CONSTCOND*/0)
144:
145: #if defined(LOCKDEBUG)
146: /*
147: * Lock debug printing routine; can be configured to print to console
148: * or log to syslog.
149: */
150: void
151: lock_printf(const char *fmt, ...)
152: {
153: char b[150];
154: va_list ap;
155:
156: va_start(ap, fmt);
157: if (lock_debug_syslog)
158: vlog(LOG_DEBUG, fmt, ap);
159: else {
160: vsnprintf(b, sizeof(b), fmt, ap);
161: printf_nolog("%s", b);
162: }
163: va_end(ap);
164: }
165: #endif /* LOCKDEBUG */
166:
167: /*
168: * Initialize a lock; required before use.
169: */
170: void
171: lockinit(struct lock *lkp, int prio, char *wmesg, int timo, int flags)
172: {
173:
174: bzero(lkp, sizeof(struct lock));
175: lkp->lk_flags = flags & LK_EXTFLG_MASK;
176: lkp->lk_lockholder = LK_NOPROC;
177: lkp->lk_prio = prio;
178: lkp->lk_timo = timo;
179: lkp->lk_wmesg = wmesg; /* just a name for spin locks */
180: #if defined(LOCKDEBUG)
181: lkp->lk_lock_file = NULL;
182: lkp->lk_unlock_file = NULL;
183: #endif
184: }
185:
186: /*
187: * Determine the status of a lock.
188: */
189: int
190: lockstatus(struct lock *lkp)
191: {
192: int lock_type = 0;
193:
194: if (lkp->lk_exclusivecount != 0)
195: lock_type = LK_EXCLUSIVE;
196: else if (lkp->lk_sharecount != 0)
197: lock_type = LK_SHARED;
198: return (lock_type);
199: }
200:
201: /*
202: * Set, change, or release a lock.
203: *
204: * Shared requests increment the shared count. Exclusive requests set the
205: * LK_WANT_EXCL flag (preventing further shared locks), and wait for already
206: * accepted shared locks and shared-to-exclusive upgrades to go away.
207: */
208: int
209: lockmgr(__volatile struct lock *lkp, u_int flags, struct simplelock *interlkp)
210: {
211: int error;
212: pid_t pid;
213: int extflags;
214: cpuid_t cpu_id;
215: struct proc *p = curproc;
216:
217: error = 0;
218: extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK;
219:
220: #ifdef DIAGNOSTIC
221: if (p == NULL)
222: panic("lockmgr: process context required");
223: #endif
224: /* Process context required. */
225: pid = p->p_pid;
226: cpu_id = CPU_NUMBER();
227:
228: /*
229: * Once a lock has drained, the LK_DRAINING flag is set and an
230: * exclusive lock is returned. The only valid operation thereafter
231: * is a single release of that exclusive lock. This final release
232: * clears the LK_DRAINING flag and sets the LK_DRAINED flag. Any
233: * further requests of any sort will result in a panic. The bits
234: * selected for these two flags are chosen so that they will be set
235: * in memory that is freed (freed memory is filled with 0xdeadbeef).
236: */
237: if (lkp->lk_flags & (LK_DRAINING|LK_DRAINED)) {
238: #ifdef DIAGNOSTIC
239: if (lkp->lk_flags & LK_DRAINED)
240: panic("lockmgr: using decommissioned lock");
241: if ((flags & LK_TYPE_MASK) != LK_RELEASE ||
242: WEHOLDIT(lkp, pid, cpu_id) == 0)
243: panic("lockmgr: non-release on draining lock: %d",
244: flags & LK_TYPE_MASK);
245: #endif /* DIAGNOSTIC */
246: lkp->lk_flags &= ~LK_DRAINING;
247: lkp->lk_flags |= LK_DRAINED;
248: }
249:
250: /*
251: * Check if the caller is asking us to be schizophrenic.
252: */
253: if ((lkp->lk_flags & (LK_CANRECURSE|LK_RECURSEFAIL)) ==
254: (LK_CANRECURSE|LK_RECURSEFAIL))
255: panic("lockmgr: make up your mind");
256:
257: switch (flags & LK_TYPE_MASK) {
258:
259: case LK_SHARED:
260: if (WEHOLDIT(lkp, pid, cpu_id) == 0) {
261: /*
262: * If just polling, check to see if we will block.
263: */
264: if ((extflags & LK_NOWAIT) && (lkp->lk_flags &
265: (LK_HAVE_EXCL | LK_WANT_EXCL))) {
266: error = EBUSY;
267: break;
268: }
269: /*
270: * Wait for exclusive locks and upgrades to clear.
271: */
272: ACQUIRE(lkp, error, extflags, 0, lkp->lk_flags &
273: (LK_HAVE_EXCL | LK_WANT_EXCL));
274: if (error)
275: break;
276: lkp->lk_sharecount++;
277: break;
278: }
279: /*
280: * We hold an exclusive lock, so downgrade it to shared.
281: * An alternative would be to fail with EDEADLK.
282: */
283: lkp->lk_sharecount++;
284:
285: if (WEHOLDIT(lkp, pid, cpu_id) == 0 ||
286: lkp->lk_exclusivecount == 0)
287: panic("lockmgr: not holding exclusive lock");
288: lkp->lk_sharecount += lkp->lk_exclusivecount;
289: lkp->lk_exclusivecount = 0;
290: lkp->lk_flags &= ~LK_HAVE_EXCL;
291: SETHOLDER(lkp, LK_NOPROC, LK_NOCPU);
292: #if defined(LOCKDEBUG)
293: lkp->lk_unlock_file = file;
294: lkp->lk_unlock_line = line;
295: #endif
296: DONTHAVEIT(lkp);
297: WAKEUP_WAITER(lkp);
298: break;
299:
300: case LK_EXCLUSIVE:
301: if (WEHOLDIT(lkp, pid, cpu_id)) {
302: /*
303: * Recursive lock.
304: */
305: if ((extflags & LK_CANRECURSE) == 0) {
306: if (extflags & LK_RECURSEFAIL) {
307: error = EDEADLK;
308: break;
309: } else
310: panic("lockmgr: locking against myself");
311: }
312: lkp->lk_exclusivecount++;
313: break;
314: }
315: /*
316: * If we are just polling, check to see if we will sleep.
317: */
318: if ((extflags & LK_NOWAIT) && ((lkp->lk_flags &
319: (LK_HAVE_EXCL | LK_WANT_EXCL)) ||
320: lkp->lk_sharecount != 0)) {
321: error = EBUSY;
322: break;
323: }
324: /*
325: * Try to acquire the want_exclusive flag.
326: */
327: ACQUIRE(lkp, error, extflags, 0, lkp->lk_flags &
328: (LK_HAVE_EXCL | LK_WANT_EXCL));
329: if (error)
330: break;
331: lkp->lk_flags |= LK_WANT_EXCL;
332: /*
333: * Wait for shared locks and upgrades to finish.
334: */
335: ACQUIRE(lkp, error, extflags, 0, lkp->lk_sharecount != 0);
336: lkp->lk_flags &= ~LK_WANT_EXCL;
337: if (error)
338: break;
339: lkp->lk_flags |= LK_HAVE_EXCL;
340: SETHOLDER(lkp, pid, cpu_id);
341: #if defined(LOCKDEBUG)
342: lkp->lk_lock_file = file;
343: lkp->lk_lock_line = line;
344: #endif
345: HAVEIT(lkp);
346: if (lkp->lk_exclusivecount != 0)
347: panic("lockmgr: non-zero exclusive count");
348: lkp->lk_exclusivecount = 1;
349: break;
350:
351: case LK_RELEASE:
352: if (lkp->lk_exclusivecount != 0) {
353: if (WEHOLDIT(lkp, pid, cpu_id) == 0) {
354: panic("lockmgr: pid %d, not exclusive lock "
355: "holder %d unlocking",
356: pid, lkp->lk_lockholder);
357: }
358: lkp->lk_exclusivecount--;
359: if (lkp->lk_exclusivecount == 0) {
360: lkp->lk_flags &= ~LK_HAVE_EXCL;
361: SETHOLDER(lkp, LK_NOPROC, LK_NOCPU);
362: #if defined(LOCKDEBUG)
363: lkp->lk_unlock_file = file;
364: lkp->lk_unlock_line = line;
365: #endif
366: DONTHAVEIT(lkp);
367: }
368: } else if (lkp->lk_sharecount != 0) {
369: lkp->lk_sharecount--;
370: }
371: #ifdef DIAGNOSTIC
372: else
373: panic("lockmgr: release of unlocked lock!");
374: #endif
375: WAKEUP_WAITER(lkp);
376: break;
377:
378: case LK_DRAIN:
379: /*
380: * Check that we do not already hold the lock, as it can
381: * never drain if we do. Unfortunately, we have no way to
382: * check for holding a shared lock, but at least we can
383: * check for an exclusive one.
384: */
385: if (WEHOLDIT(lkp, pid, cpu_id))
386: panic("lockmgr: draining against myself");
387: /*
388: * If we are just polling, check to see if we will sleep.
389: */
390: if ((extflags & LK_NOWAIT) && ((lkp->lk_flags &
391: (LK_HAVE_EXCL | LK_WANT_EXCL)) ||
392: lkp->lk_sharecount != 0 || lkp->lk_waitcount != 0)) {
393: error = EBUSY;
394: break;
395: }
396: ACQUIRE(lkp, error, extflags, 1,
397: ((lkp->lk_flags &
398: (LK_HAVE_EXCL | LK_WANT_EXCL)) ||
399: lkp->lk_sharecount != 0 ||
400: lkp->lk_waitcount != 0));
401: if (error)
402: break;
403: lkp->lk_flags |= LK_DRAINING | LK_HAVE_EXCL;
404: SETHOLDER(lkp, pid, cpu_id);
405: #if defined(LOCKDEBUG)
406: lkp->lk_lock_file = file;
407: lkp->lk_lock_line = line;
408: #endif
409: HAVEIT(lkp);
410: lkp->lk_exclusivecount = 1;
411: break;
412:
413: default:
414: panic("lockmgr: unknown locktype request %d",
415: flags & LK_TYPE_MASK);
416: /* NOTREACHED */
417: }
418: if ((lkp->lk_flags & LK_WAITDRAIN) != 0 &&
419: ((lkp->lk_flags &
420: (LK_HAVE_EXCL | LK_WANT_EXCL)) == 0 &&
421: lkp->lk_sharecount == 0 && lkp->lk_waitcount == 0)) {
422: lkp->lk_flags &= ~LK_WAITDRAIN;
423: wakeup((void *)&lkp->lk_flags);
424: }
425: return (error);
426: }
427:
428: #ifdef DIAGNOSTIC
429: /*
430: * Print out information about state of a lock. Used by VOP_PRINT
431: * routines to display ststus about contained locks.
432: */
433: void
434: lockmgr_printinfo(__volatile struct lock *lkp)
435: {
436:
437: if (lkp->lk_sharecount)
438: printf(" lock type %s: SHARED (count %d)", lkp->lk_wmesg,
439: lkp->lk_sharecount);
440: else if (lkp->lk_flags & LK_HAVE_EXCL) {
441: printf(" lock type %s: EXCL (count %d) by ",
442: lkp->lk_wmesg, lkp->lk_exclusivecount);
443: printf("pid %d", lkp->lk_lockholder);
444: } else
445: printf(" not locked");
446: if (lkp->lk_waitcount > 0)
447: printf(" with %d pending", lkp->lk_waitcount);
448: }
449: #endif /* DIAGNOSTIC */
450:
451: #if defined(LOCKDEBUG)
452: TAILQ_HEAD(, simplelock) simplelock_list =
453: TAILQ_HEAD_INITIALIZER(simplelock_list);
454:
455: #if defined(MULTIPROCESSOR) /* { */
456: struct simplelock simplelock_list_slock = SIMPLELOCK_INITIALIZER;
457:
458: #define SLOCK_LIST_LOCK() \
459: __cpu_simple_lock(&simplelock_list_slock.lock_data)
460:
461: #define SLOCK_LIST_UNLOCK() \
462: __cpu_simple_unlock(&simplelock_list_slock.lock_data)
463:
464: #define SLOCK_COUNT(x) \
465: curcpu()->ci_simple_locks += (x)
466: #else
467: u_long simple_locks;
468:
469: #define SLOCK_LIST_LOCK() /* nothing */
470:
471: #define SLOCK_LIST_UNLOCK() /* nothing */
472:
473: #define SLOCK_COUNT(x) simple_locks += (x)
474: #endif /* MULTIPROCESSOR */ /* } */
475:
476: #ifdef MULTIPROCESSOR
477: #define SLOCK_MP() lock_printf("on cpu %ld\n", \
478: (u_long) cpu_number())
479: #else
480: #define SLOCK_MP() /* nothing */
481: #endif
482:
483: #define SLOCK_WHERE(str, alp, id, l) \
484: do { \
485: lock_printf("\n"); \
486: lock_printf(str); \
487: lock_printf("lock: %p, currently at: %s:%d\n", (alp), (id), (l)); \
488: SLOCK_MP(); \
489: if ((alp)->lock_file != NULL) \
490: lock_printf("last locked: %s:%d\n", (alp)->lock_file, \
491: (alp)->lock_line); \
492: if ((alp)->unlock_file != NULL) \
493: lock_printf("last unlocked: %s:%d\n", (alp)->unlock_file, \
494: (alp)->unlock_line); \
495: SLOCK_TRACE() \
496: SLOCK_DEBUGGER(); \
497: } while (/*CONSTCOND*/0)
498:
499: /*
500: * Simple lock functions so that the debugger can see from whence
501: * they are being called.
502: */
503: void
504: simple_lock_init(struct simplelock *lkp)
505: {
506:
507: #if defined(MULTIPROCESSOR) /* { */
508: __cpu_simple_lock_init(&alp->lock_data);
509: #else
510: alp->lock_data = __SIMPLELOCK_UNLOCKED;
511: #endif /* } */
512: alp->lock_file = NULL;
513: alp->lock_line = 0;
514: alp->unlock_file = NULL;
515: alp->unlock_line = 0;
516: alp->lock_holder = LK_NOCPU;
517: }
518:
519: void
520: _simple_lock(__volatile struct simplelock *lkp, const char *id, int l)
521: {
522: cpuid_t cpu_id = CPU_NUMBER();
523: int s;
524:
525: s = spllock();
526:
527: /*
528: * MULTIPROCESSOR case: This is `safe' since if it's not us, we
529: * don't take any action, and just fall into the normal spin case.
530: */
531: if (alp->lock_data == __SIMPLELOCK_LOCKED) {
532: #if defined(MULTIPROCESSOR) /* { */
533: if (alp->lock_holder == cpu_id) {
534: SLOCK_WHERE("simple_lock: locking against myself\n",
535: alp, id, l);
536: goto out;
537: }
538: #else
539: SLOCK_WHERE("simple_lock: lock held\n", alp, id, l);
540: goto out;
541: #endif /* MULTIPROCESSOR */ /* } */
542: }
543:
544: #if defined(MULTIPROCESSOR) /* { */
545: /* Acquire the lock before modifying any fields. */
546: splx(s);
547: __cpu_simple_lock(&alp->lock_data);
548: s = spllock();
549: #else
550: alp->lock_data = __SIMPLELOCK_LOCKED;
551: #endif /* } */
552:
553: if (alp->lock_holder != LK_NOCPU) {
554: SLOCK_WHERE("simple_lock: uninitialized lock\n",
555: alp, id, l);
556: }
557: alp->lock_file = id;
558: alp->lock_line = l;
559: alp->lock_holder = cpu_id;
560:
561: SLOCK_LIST_LOCK();
562: /* XXX Cast away volatile */
563: TAILQ_INSERT_TAIL(&simplelock_list, (struct simplelock *)alp, list);
564: SLOCK_LIST_UNLOCK();
565:
566: SLOCK_COUNT(1);
567:
568: out:
569: splx(s);
570: }
571:
572: int
573: _simple_lock_held(__volatile struct simplelock *alp)
574: {
575: cpuid_t cpu_id = CPU_NUMBER();
576: int s, locked = 0;
577:
578: s = spllock();
579:
580: #if defined(MULTIPROCESSOR)
581: if (__cpu_simple_lock_try(&alp->lock_data) == 0)
582: locked = (alp->lock_holder == cpu_id);
583: else
584: __cpu_simple_unlock(&alp->lock_data);
585: #else
586: if (alp->lock_data == __SIMPLELOCK_LOCKED) {
587: locked = 1;
588: KASSERT(alp->lock_holder == cpu_id);
589: }
590: #endif
591:
592: splx(s);
593:
594: return (locked);
595: }
596:
597: int
598: _simple_lock_try(__volatile struct simplelock *lkp, const char *id, int l)
599: {
600: cpuid_t cpu_id = CPU_NUMBER();
601: int s, rv = 0;
602:
603: s = spllock();
604:
605: /*
606: * MULTIPROCESSOR case: This is `safe' since if it's not us, we
607: * don't take any action.
608: */
609: #if defined(MULTIPROCESSOR) /* { */
610: if ((rv = __cpu_simple_lock_try(&alp->lock_data)) == 0) {
611: if (alp->lock_holder == cpu_id)
612: SLOCK_WHERE("simple_lock_try: locking against myself\n",
613: alp, id, l);
614: goto out;
615: }
616: #else
617: if (alp->lock_data == __SIMPLELOCK_LOCKED) {
618: SLOCK_WHERE("simple_lock_try: lock held\n", alp, id, l);
619: goto out;
620: }
621: alp->lock_data = __SIMPLELOCK_LOCKED;
622: #endif /* MULTIPROCESSOR */ /* } */
623:
624: /*
625: * At this point, we have acquired the lock.
626: */
627:
628: rv = 1;
629:
630: alp->lock_file = id;
631: alp->lock_line = l;
632: alp->lock_holder = cpu_id;
633:
634: SLOCK_LIST_LOCK();
635: /* XXX Cast away volatile. */
636: TAILQ_INSERT_TAIL(&simplelock_list, (struct simplelock *)alp, list);
637: SLOCK_LIST_UNLOCK();
638:
639: SLOCK_COUNT(1);
640:
641: out:
642: splx(s);
643: return (rv);
644: }
645:
646: void
647: _simple_unlock(__volatile struct simplelock *lkp, const char *id, int l)
648: {
649: int s;
650:
651: s = spllock();
652:
653: /*
654: * MULTIPROCESSOR case: This is `safe' because we think we hold
655: * the lock, and if we don't, we don't take any action.
656: */
657: if (alp->lock_data == __SIMPLELOCK_UNLOCKED) {
658: SLOCK_WHERE("simple_unlock: lock not held\n",
659: alp, id, l);
660: goto out;
661: }
662:
663: SLOCK_LIST_LOCK();
664: TAILQ_REMOVE(&simplelock_list, alp, list);
665: SLOCK_LIST_UNLOCK();
666:
667: SLOCK_COUNT(-1);
668:
669: alp->list.tqe_next = NULL; /* sanity */
670: alp->list.tqe_prev = NULL; /* sanity */
671:
672: alp->unlock_file = id;
673: alp->unlock_line = l;
674:
675: #if defined(MULTIPROCESSOR) /* { */
676: alp->lock_holder = LK_NOCPU;
677: /* Now that we've modified all fields, release the lock. */
678: __cpu_simple_unlock(&alp->lock_data);
679: #else
680: alp->lock_data = __SIMPLELOCK_UNLOCKED;
681: KASSERT(alp->lock_holder == CPU_NUMBER());
682: alp->lock_holder = LK_NOCPU;
683: #endif /* } */
684:
685: out:
686: splx(s);
687: }
688:
689: void
690: simple_lock_dump(void)
691: {
692: struct simplelock *alp;
693: int s;
694:
695: s = spllock();
696: SLOCK_LIST_LOCK();
697: lock_printf("all simple locks:\n");
698: TAILQ_FOREACH(alp, &simplelock_list, list) {
699: lock_printf("%p CPU %lu %s:%d\n", alp, alp->lock_holder,
700: alp->lock_file, alp->lock_line);
701: }
702: SLOCK_LIST_UNLOCK();
703: splx(s);
704: }
705:
706: void
707: simple_lock_freecheck(void *start, void *end)
708: {
709: struct simplelock *alp;
710: int s;
711:
712: s = spllock();
713: SLOCK_LIST_LOCK();
714: TAILQ_FOREACH(alp, &simplelock_list, list) {
715: if ((void *)alp >= start && (void *)alp < end) {
716: lock_printf("freeing simple_lock %p CPU %lu %s:%d\n",
717: alp, alp->lock_holder, alp->lock_file,
718: alp->lock_line);
719: SLOCK_DEBUGGER();
720: }
721: }
722: SLOCK_LIST_UNLOCK();
723: splx(s);
724: }
725:
726: /*
727: * We must be holding exactly one lock: the sched_lock.
728: */
729:
730: #ifdef notyet
731: void
732: simple_lock_switchcheck(void)
733: {
734:
735: simple_lock_only_held(&sched_lock, "switching");
736: }
737: #endif
738:
739: void
740: simple_lock_only_held(volatile struct simplelock *lp, const char *where)
741: {
742: struct simplelock *alp;
743: cpuid_t cpu_id = CPU_NUMBER();
744: int s;
745:
746: if (lp) {
747: LOCK_ASSERT(simple_lock_held(lp));
748: }
749: s = spllock();
750: SLOCK_LIST_LOCK();
751: TAILQ_FOREACH(alp, &simplelock_list, list) {
752: if (alp == lp)
753: continue;
754: if (alp->lock_holder == cpu_id)
755: break;
756: }
757: SLOCK_LIST_UNLOCK();
758: splx(s);
759:
760: if (alp != NULL) {
761: lock_printf("\n%s with held simple_lock %p "
762: "CPU %lu %s:%d\n",
763: where, alp, alp->lock_holder, alp->lock_file,
764: alp->lock_line);
765: SLOCK_TRACE();
766: SLOCK_DEBUGGER();
767: }
768: }
769: #endif /* LOCKDEBUG */
770:
771: #if defined(MULTIPROCESSOR)
772: /*
773: * Functions for manipulating the kernel_lock. We put them here
774: * so that they show up in profiles.
775: */
776:
777: struct __mp_lock kernel_lock;
778:
779: void
780: _kernel_lock_init(void)
781: {
782: __mp_lock_init(&kernel_lock);
783: }
784:
785: /*
786: * Acquire/release the kernel lock. Intended for use in the scheduler
787: * and the lower half of the kernel.
788: */
789:
790: void
791: _kernel_lock(void)
792: {
793: SCHED_ASSERT_UNLOCKED();
794: __mp_lock(&kernel_lock);
795: }
796:
797: void
798: _kernel_unlock(void)
799: {
800: __mp_unlock(&kernel_lock);
801: }
802:
803: /*
804: * Acquire/release the kernel_lock on behalf of a process. Intended for
805: * use in the top half of the kernel.
806: */
807: void
808: _kernel_proc_lock(struct proc *p)
809: {
810: SCHED_ASSERT_UNLOCKED();
811: __mp_lock(&kernel_lock);
812: atomic_setbits_int(&p->p_flag, P_BIGLOCK);
813: }
814:
815: void
816: _kernel_proc_unlock(struct proc *p)
817: {
818: atomic_clearbits_int(&p->p_flag, P_BIGLOCK);
819: __mp_unlock(&kernel_lock);
820: }
821:
822: #ifdef MP_LOCKDEBUG
823: /* CPU-dependent timing, needs this to be settable from ddb. */
824: int __mp_lock_spinout = 200000000;
825: #endif
826:
827: #endif /* MULTIPROCESSOR */
CVSweb