Deleted Added
full compact
kern_lock.c (71320) kern_lock.c (71576)
1/*
2 * Copyright (c) 1995
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Copyright (C) 1997
6 * John S. Dyson. All rights reserved.
7 *
8 * This code contains ideas from software contributed to Berkeley by

--- 24 unchanged lines hidden (view full) ---

33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * @(#)kern_lock.c 8.18 (Berkeley) 5/21/95
1/*
2 * Copyright (c) 1995
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Copyright (C) 1997
6 * John S. Dyson. All rights reserved.
7 *
8 * This code contains ideas from software contributed to Berkeley by

--- 24 unchanged lines hidden (view full) ---

33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * @(#)kern_lock.c 8.18 (Berkeley) 5/21/95
41 * $FreeBSD: head/sys/kern/kern_lock.c 71320 2001-01-21 07:52:20Z jasone $
41 * $FreeBSD: head/sys/kern/kern_lock.c 71576 2001-01-24 12:35:55Z jasone $
42 */
43
44#include <sys/param.h>
45#include <sys/proc.h>
46#include <sys/kernel.h>
47#include <sys/lock.h>
48#include <sys/malloc.h>
49#include <sys/mutex.h>
50#include <sys/systm.h>
51
52/*
53 * Locking primitives implementation.
54 * Locks provide shared/exclusive sychronization.
55 */
56
42 */
43
44#include <sys/param.h>
45#include <sys/proc.h>
46#include <sys/kernel.h>
47#include <sys/lock.h>
48#include <sys/malloc.h>
49#include <sys/mutex.h>
50#include <sys/systm.h>
51
52/*
53 * Locking primitives implementation.
54 * Locks provide shared/exclusive sychronization.
55 */
56
57#ifdef SIMPLELOCK_DEBUG
58#define COUNT(p, x) if (p) (p)->p_locks += (x)
59#else
60#define COUNT(p, x)
61#endif
62
63#define LOCK_WAIT_TIME 100
64#define LOCK_SAMPLE_WAIT 7
65
66#if defined(DIAGNOSTIC)
67#define LOCK_INLINE
68#else
69#define LOCK_INLINE __inline
70#endif

--- 61 unchanged lines hidden (view full) ---

132 }
133 lkp->lk_sharecount = 0;
134 } else {
135 lkp->lk_sharecount -= decr;
136 }
137}
138
139/*
57#define LOCK_WAIT_TIME 100
58#define LOCK_SAMPLE_WAIT 7
59
60#if defined(DIAGNOSTIC)
61#define LOCK_INLINE
62#else
63#define LOCK_INLINE __inline
64#endif

--- 61 unchanged lines hidden (view full) ---

126 }
127 lkp->lk_sharecount = 0;
128 } else {
129 lkp->lk_sharecount -= decr;
130 }
131}
132
133/*
140 * This is the waitloop optimization, and note for this to work
141 * simple_lock and simple_unlock should be subroutines to avoid
142 * optimization troubles.
134 * This is the waitloop optimization.
143 */
144static int
145apause(struct lock *lkp, int flags)
146{
147#ifdef SMP
148 int i, lock_wait;
149#endif
150

--- 124 unchanged lines hidden (view full) ---

275 extflags,
276 LK_HAVE_EXCL | LK_WANT_EXCL |
277 LK_WANT_UPGRADE
278 );
279 }
280 if (error)
281 break;
282 sharelock(lkp, 1);
135 */
136static int
137apause(struct lock *lkp, int flags)
138{
139#ifdef SMP
140 int i, lock_wait;
141#endif
142

--- 124 unchanged lines hidden (view full) ---

267 extflags,
268 LK_HAVE_EXCL | LK_WANT_EXCL |
269 LK_WANT_UPGRADE
270 );
271 }
272 if (error)
273 break;
274 sharelock(lkp, 1);
283 COUNT(p, 1);
284 break;
285 }
286 /*
287 * We hold an exclusive lock, so downgrade it to shared.
288 * An alternative would be to fail with EDEADLK.
289 */
290 sharelock(lkp, 1);
275 break;
276 }
277 /*
278 * We hold an exclusive lock, so downgrade it to shared.
279 * An alternative would be to fail with EDEADLK.
280 */
281 sharelock(lkp, 1);
291 COUNT(p, 1);
292 /* fall into downgrade */
293
294 case LK_DOWNGRADE:
295 if (lkp->lk_lockholder != pid || lkp->lk_exclusivecount == 0)
296 panic("lockmgr: not holding exclusive lock");
297 sharelock(lkp, lkp->lk_exclusivecount);
298 lkp->lk_exclusivecount = 0;
299 lkp->lk_flags &= ~LK_HAVE_EXCL;

--- 5 unchanged lines hidden (view full) ---

305 case LK_EXCLUPGRADE:
306 /*
307 * If another process is ahead of us to get an upgrade,
308 * then we want to fail rather than have an intervening
309 * exclusive access.
310 */
311 if (lkp->lk_flags & LK_WANT_UPGRADE) {
312 shareunlock(lkp, 1);
282 /* fall into downgrade */
283
284 case LK_DOWNGRADE:
285 if (lkp->lk_lockholder != pid || lkp->lk_exclusivecount == 0)
286 panic("lockmgr: not holding exclusive lock");
287 sharelock(lkp, lkp->lk_exclusivecount);
288 lkp->lk_exclusivecount = 0;
289 lkp->lk_flags &= ~LK_HAVE_EXCL;

--- 5 unchanged lines hidden (view full) ---

295 case LK_EXCLUPGRADE:
296 /*
297 * If another process is ahead of us to get an upgrade,
298 * then we want to fail rather than have an intervening
299 * exclusive access.
300 */
301 if (lkp->lk_flags & LK_WANT_UPGRADE) {
302 shareunlock(lkp, 1);
313 COUNT(p, -1);
314 error = EBUSY;
315 break;
316 }
317 /* fall into normal upgrade */
318
319 case LK_UPGRADE:
320 /*
321 * Upgrade a shared lock to an exclusive one. If another
322 * shared lock has already requested an upgrade to an
323 * exclusive lock, our shared lock is released and an
324 * exclusive lock is requested (which will be granted
325 * after the upgrade). If we return an error, the file
326 * will always be unlocked.
327 */
328 if ((lkp->lk_lockholder == pid) || (lkp->lk_sharecount <= 0))
329 panic("lockmgr: upgrade exclusive lock");
330 shareunlock(lkp, 1);
303 error = EBUSY;
304 break;
305 }
306 /* fall into normal upgrade */
307
308 case LK_UPGRADE:
309 /*
310 * Upgrade a shared lock to an exclusive one. If another
311 * shared lock has already requested an upgrade to an
312 * exclusive lock, our shared lock is released and an
313 * exclusive lock is requested (which will be granted
314 * after the upgrade). If we return an error, the file
315 * will always be unlocked.
316 */
317 if ((lkp->lk_lockholder == pid) || (lkp->lk_sharecount <= 0))
318 panic("lockmgr: upgrade exclusive lock");
319 shareunlock(lkp, 1);
331 COUNT(p, -1);
332 /*
333 * If we are just polling, check to see if we will block.
334 */
335 if ((extflags & LK_NOWAIT) &&
336 ((lkp->lk_flags & LK_WANT_UPGRADE) ||
337 lkp->lk_sharecount > 1)) {
338 error = EBUSY;
339 break;

--- 15 unchanged lines hidden (view full) ---

355 if (lkp->lk_exclusivecount != 0)
356 panic("lockmgr: non-zero exclusive count");
357 lkp->lk_exclusivecount = 1;
358#if defined(DEBUG_LOCKS)
359 lkp->lk_filename = file;
360 lkp->lk_lineno = line;
361 lkp->lk_lockername = name;
362#endif
320 /*
321 * If we are just polling, check to see if we will block.
322 */
323 if ((extflags & LK_NOWAIT) &&
324 ((lkp->lk_flags & LK_WANT_UPGRADE) ||
325 lkp->lk_sharecount > 1)) {
326 error = EBUSY;
327 break;

--- 15 unchanged lines hidden (view full) ---

343 if (lkp->lk_exclusivecount != 0)
344 panic("lockmgr: non-zero exclusive count");
345 lkp->lk_exclusivecount = 1;
346#if defined(DEBUG_LOCKS)
347 lkp->lk_filename = file;
348 lkp->lk_lineno = line;
349 lkp->lk_lockername = name;
350#endif
363 COUNT(p, 1);
364 break;
365 }
366 /*
367 * Someone else has requested upgrade. Release our shared
368 * lock, awaken upgrade requestor if we are the last shared
369 * lock, then request an exclusive lock.
370 */
371 if ( (lkp->lk_flags & (LK_SHARE_NONZERO|LK_WAIT_NONZERO)) ==

--- 5 unchanged lines hidden (view full) ---

377 if (lkp->lk_lockholder == pid && pid != LK_KERNPROC) {
378 /*
379 * Recursive lock.
380 */
381 if ((extflags & (LK_NOWAIT | LK_CANRECURSE)) == 0)
382 panic("lockmgr: locking against myself");
383 if ((extflags & LK_CANRECURSE) != 0) {
384 lkp->lk_exclusivecount++;
351 break;
352 }
353 /*
354 * Someone else has requested upgrade. Release our shared
355 * lock, awaken upgrade requestor if we are the last shared
356 * lock, then request an exclusive lock.
357 */
358 if ( (lkp->lk_flags & (LK_SHARE_NONZERO|LK_WAIT_NONZERO)) ==

--- 5 unchanged lines hidden (view full) ---

364 if (lkp->lk_lockholder == pid && pid != LK_KERNPROC) {
365 /*
366 * Recursive lock.
367 */
368 if ((extflags & (LK_NOWAIT | LK_CANRECURSE)) == 0)
369 panic("lockmgr: locking against myself");
370 if ((extflags & LK_CANRECURSE) != 0) {
371 lkp->lk_exclusivecount++;
385 COUNT(p, 1);
386 break;
387 }
388 }
389 /*
390 * If we are just polling, check to see if we will sleep.
391 */
392 if ((extflags & LK_NOWAIT) &&
393 (lkp->lk_flags & (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE | LK_SHARE_NONZERO))) {

--- 19 unchanged lines hidden (view full) ---

413 if (lkp->lk_exclusivecount != 0)
414 panic("lockmgr: non-zero exclusive count");
415 lkp->lk_exclusivecount = 1;
416#if defined(DEBUG_LOCKS)
417 lkp->lk_filename = file;
418 lkp->lk_lineno = line;
419 lkp->lk_lockername = name;
420#endif
372 break;
373 }
374 }
375 /*
376 * If we are just polling, check to see if we will sleep.
377 */
378 if ((extflags & LK_NOWAIT) &&
379 (lkp->lk_flags & (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE | LK_SHARE_NONZERO))) {

--- 19 unchanged lines hidden (view full) ---

399 if (lkp->lk_exclusivecount != 0)
400 panic("lockmgr: non-zero exclusive count");
401 lkp->lk_exclusivecount = 1;
402#if defined(DEBUG_LOCKS)
403 lkp->lk_filename = file;
404 lkp->lk_lineno = line;
405 lkp->lk_lockername = name;
406#endif
421 COUNT(p, 1);
422 break;
423
424 case LK_RELEASE:
425 if (lkp->lk_exclusivecount != 0) {
426 if (lkp->lk_lockholder != pid &&
427 lkp->lk_lockholder != LK_KERNPROC) {
428 panic("lockmgr: pid %d, not %s %d unlocking",
429 pid, "exclusive lock holder",
430 lkp->lk_lockholder);
431 }
407 break;
408
409 case LK_RELEASE:
410 if (lkp->lk_exclusivecount != 0) {
411 if (lkp->lk_lockholder != pid &&
412 lkp->lk_lockholder != LK_KERNPROC) {
413 panic("lockmgr: pid %d, not %s %d unlocking",
414 pid, "exclusive lock holder",
415 lkp->lk_lockholder);
416 }
432 if (lkp->lk_lockholder != LK_KERNPROC) {
433 COUNT(p, -1);
434 }
435 if (lkp->lk_exclusivecount == 1) {
436 lkp->lk_flags &= ~LK_HAVE_EXCL;
437 lkp->lk_lockholder = LK_NOPROC;
438 lkp->lk_exclusivecount = 0;
439 } else {
440 lkp->lk_exclusivecount--;
441 }
417 if (lkp->lk_exclusivecount == 1) {
418 lkp->lk_flags &= ~LK_HAVE_EXCL;
419 lkp->lk_lockholder = LK_NOPROC;
420 lkp->lk_exclusivecount = 0;
421 } else {
422 lkp->lk_exclusivecount--;
423 }
442 } else if (lkp->lk_flags & LK_SHARE_NONZERO) {
424 } else if (lkp->lk_flags & LK_SHARE_NONZERO)
443 shareunlock(lkp, 1);
425 shareunlock(lkp, 1);
444 COUNT(p, -1);
445 }
446 if (lkp->lk_flags & LK_WAIT_NONZERO)
447 wakeup((void *)lkp);
448 break;
449
450 case LK_DRAIN:
451 /*
452 * Check that we do not already hold the lock, as it can
453 * never drain if we do. Unfortunately, we have no way to

--- 9 unchanged lines hidden (view full) ---

463 lkp->lk_flags |= LK_DRAINING | LK_HAVE_EXCL;
464 lkp->lk_lockholder = pid;
465 lkp->lk_exclusivecount = 1;
466#if defined(DEBUG_LOCKS)
467 lkp->lk_filename = file;
468 lkp->lk_lineno = line;
469 lkp->lk_lockername = name;
470#endif
426 if (lkp->lk_flags & LK_WAIT_NONZERO)
427 wakeup((void *)lkp);
428 break;
429
430 case LK_DRAIN:
431 /*
432 * Check that we do not already hold the lock, as it can
433 * never drain if we do. Unfortunately, we have no way to

--- 9 unchanged lines hidden (view full) ---

443 lkp->lk_flags |= LK_DRAINING | LK_HAVE_EXCL;
444 lkp->lk_lockholder = pid;
445 lkp->lk_exclusivecount = 1;
446#if defined(DEBUG_LOCKS)
447 lkp->lk_filename = file;
448 lkp->lk_lineno = line;
449 lkp->lk_lockername = name;
450#endif
471 COUNT(p, 1);
472 break;
473
474 default:
475 mtx_exit(lkp->lk_interlock, MTX_DEF);
476 panic("lockmgr: unknown locktype request %d",
477 flags & LK_TYPE_MASK);
478 /* NOTREACHED */
479 }

--- 142 unchanged lines hidden (view full) ---

622 printf(" lock type %s: SHARED (count %d)", lkp->lk_wmesg,
623 lkp->lk_sharecount);
624 else if (lkp->lk_flags & LK_HAVE_EXCL)
625 printf(" lock type %s: EXCL (count %d) by pid %d",
626 lkp->lk_wmesg, lkp->lk_exclusivecount, lkp->lk_lockholder);
627 if (lkp->lk_waitcount > 0)
628 printf(" with %d pending", lkp->lk_waitcount);
629}
451 break;
452
453 default:
454 mtx_exit(lkp->lk_interlock, MTX_DEF);
455 panic("lockmgr: unknown locktype request %d",
456 flags & LK_TYPE_MASK);
457 /* NOTREACHED */
458 }

--- 142 unchanged lines hidden (view full) ---

601 printf(" lock type %s: SHARED (count %d)", lkp->lk_wmesg,
602 lkp->lk_sharecount);
603 else if (lkp->lk_flags & LK_HAVE_EXCL)
604 printf(" lock type %s: EXCL (count %d) by pid %d",
605 lkp->lk_wmesg, lkp->lk_exclusivecount, lkp->lk_lockholder);
606 if (lkp->lk_waitcount > 0)
607 printf(" with %d pending", lkp->lk_waitcount);
608}
630
631#if defined(SIMPLELOCK_DEBUG) && (MAXCPU == 1 || defined(COMPILING_LINT))
632#include <sys/kernel.h>
633#include <sys/sysctl.h>
634
635static int lockpausetime = 0;
636SYSCTL_INT(_debug, OID_AUTO, lockpausetime, CTLFLAG_RW, &lockpausetime, 0, "");
637
638static int simplelockrecurse;
639
640/*
641 * Simple lock functions so that the debugger can see from whence
642 * they are being called.
643 */
644void
645simple_lock_init(alp)
646 struct simplelock *alp;
647{
648
649 alp->lock_data = 0;
650}
651
652void
653_simple_lock(alp, id, l)
654 struct simplelock *alp;
655 const char *id;
656 int l;
657{
658
659 if (simplelockrecurse)
660 return;
661 if (alp->lock_data == 1) {
662 if (lockpausetime == -1)
663 panic("%s:%d: simple_lock: lock held", id, l);
664 printf("%s:%d: simple_lock: lock held\n", id, l);
665 if (lockpausetime == 1) {
666 Debugger("simple_lock");
667 /*BACKTRACE(curproc); */
668 } else if (lockpausetime > 1) {
669 printf("%s:%d: simple_lock: lock held...", id, l);
670 tsleep(&lockpausetime, PCATCH | PPAUSE, "slock",
671 lockpausetime * hz);
672 printf(" continuing\n");
673 }
674 }
675 alp->lock_data = 1;
676 if (curproc)
677 curproc->p_simple_locks++;
678}
679
680int
681_simple_lock_try(alp, id, l)
682 struct simplelock *alp;
683 const char *id;
684 int l;
685{
686
687 if (alp->lock_data)
688 return (0);
689 if (simplelockrecurse)
690 return (1);
691 alp->lock_data = 1;
692 if (curproc)
693 curproc->p_simple_locks++;
694 return (1);
695}
696
697void
698_simple_unlock(alp, id, l)
699 struct simplelock *alp;
700 const char *id;
701 int l;
702{
703
704 if (simplelockrecurse)
705 return;
706 if (alp->lock_data == 0) {
707 if (lockpausetime == -1)
708 panic("%s:%d: simple_unlock: lock not held", id, l);
709 printf("%s:%d: simple_unlock: lock not held\n", id, l);
710 if (lockpausetime == 1) {
711 Debugger("simple_unlock");
712 /* BACKTRACE(curproc); */
713 } else if (lockpausetime > 1) {
714 printf("%s:%d: simple_unlock: lock not held...", id, l);
715 tsleep(&lockpausetime, PCATCH | PPAUSE, "sunlock",
716 lockpausetime * hz);
717 printf(" continuing\n");
718 }
719 }
720 alp->lock_data = 0;
721 if (curproc)
722 curproc->p_simple_locks--;
723}
724#elif defined(SIMPLELOCK_DEBUG)
725#error "SIMPLELOCK_DEBUG is not compatible with SMP!"
726#endif /* SIMPLELOCK_DEBUG && MAXCPU == 1 */