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 */ | |