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 9 * Avadis Tevanian, Jr., Michael Wayne Young, and the Mach Operating 10 * System project at Carnegie-Mellon University. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 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 * $Id: kern_lock.c,v 1.20 1998/11/26 18:50:23 eivind Exp $ 42 */ 43 44 #include "opt_lint.h" 45 46 #include <sys/param.h> 47 #include <sys/proc.h> 48 #include <sys/lock.h> 49 #include <sys/systm.h> 50 51 /* 52 * Locking primitives implementation. 53 * Locks provide shared/exclusive sychronization. 54 */ 55 56 #ifdef SIMPLELOCK_DEBUG 57 #define COUNT(p, x) if (p) (p)->p_locks += (x) 58 #else 59 #define COUNT(p, x) 60 #endif 61 62 #define LOCK_WAIT_TIME 100 63 #define LOCK_SAMPLE_WAIT 7 64 65 #if defined(DIAGNOSTIC) 66 #define LOCK_INLINE 67 #else 68 #define LOCK_INLINE __inline 69 #endif 70 71 #define LK_ALL (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE | \ 72 LK_SHARE_NONZERO | LK_WAIT_NONZERO) 73 74 static int acquire(struct lock *lkp, int extflags, int wanted); 75 static int apause(struct lock *lkp, int flags); 76 static int acquiredrain(struct lock *lkp, int extflags) ; 77 78 static LOCK_INLINE void 79 sharelock(struct lock *lkp, int incr) { 80 lkp->lk_flags |= LK_SHARE_NONZERO; 81 lkp->lk_sharecount += incr; 82 } 83 84 static LOCK_INLINE void 85 shareunlock(struct lock *lkp, int decr) { 86 KASSERT(lkp->lk_sharecount >= decr, ("shareunlock: count < decr")); 87 88 if (lkp->lk_sharecount == decr) { 89 lkp->lk_flags &= ~LK_SHARE_NONZERO; 90 if (lkp->lk_flags & (LK_WANT_UPGRADE | LK_WANT_EXCL)) { 91 wakeup(lkp); 92 } 93 lkp->lk_sharecount = 0; 94 } else { 95 lkp->lk_sharecount -= decr; 96 } 97 } 98 99 /* 100 * This is the waitloop optimization, and note for this to work 101 * simple_lock and simple_unlock should be subroutines to avoid 102 * optimization troubles. 103 */ 104 static int 105 apause(struct lock *lkp, int flags) { 106 int lock_wait; 107 lock_wait = LOCK_WAIT_TIME; 108 for (; lock_wait > 0; lock_wait--) { 109 int i; 110 if ((lkp->lk_flags & flags) == 0) 111 return 0; 112 simple_unlock(&lkp->lk_interlock); 113 for (i = LOCK_SAMPLE_WAIT; i > 0; i--) { 114 if ((lkp->lk_flags & flags) == 0) { 115 simple_lock(&lkp->lk_interlock); 116 if ((lkp->lk_flags & flags) == 0) 117 return 0; 118 break; 119 } 120 } 121 } 122 return 1; 123 } 124 125 static int 126 acquire(struct lock *lkp, int extflags, int wanted) { 127 int s, error; 128 129 if ((extflags & LK_NOWAIT) && (lkp->lk_flags & wanted)) { 130 return EBUSY; 131 } 132 133 if (((lkp->lk_flags | extflags) & LK_NOPAUSE) == 0) { 134 error = apause(lkp, wanted); 135 if (error == 0) 136 return 0; 137 } 138 139 s = splhigh(); 140 while ((lkp->lk_flags & wanted) != 0) { 141 lkp->lk_flags |= LK_WAIT_NONZERO; 142 lkp->lk_waitcount++; 143 simple_unlock(&lkp->lk_interlock); 144 error = tsleep(lkp, lkp->lk_prio, lkp->lk_wmesg, lkp->lk_timo); 145 simple_lock(&lkp->lk_interlock); 146 if (lkp->lk_waitcount == 1) { 147 lkp->lk_flags &= ~LK_WAIT_NONZERO; 148 lkp->lk_waitcount = 0; 149 } else { 150 lkp->lk_waitcount--; 151 } 152 if (error) { 153 splx(s); 154 return error; 155 } 156 if (extflags & LK_SLEEPFAIL) { 157 splx(s); 158 return ENOLCK; 159 } 160 } 161 splx(s); 162 return 0; 163 } 164 165 /* 166 * Set, change, or release a lock. 167 * 168 * Shared requests increment the shared count. Exclusive requests set the 169 * LK_WANT_EXCL flag (preventing further shared locks), and wait for already 170 * accepted shared locks and shared-to-exclusive upgrades to go away. 171 */ 172 int 173 lockmgr(lkp, flags, interlkp, p) 174 struct lock *lkp; 175 u_int flags; 176 struct simplelock *interlkp; 177 struct proc *p; 178 { 179 int error; 180 pid_t pid; 181 int extflags; 182 183 error = 0; 184 if (p == NULL) 185 pid = LK_KERNPROC; 186 else 187 pid = p->p_pid; 188 189 simple_lock(&lkp->lk_interlock); 190 if (flags & LK_INTERLOCK) 191 simple_unlock(interlkp); 192 193 extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK; 194 195 switch (flags & LK_TYPE_MASK) { 196 197 case LK_SHARED: 198 if (lkp->lk_lockholder != pid) { 199 error = acquire(lkp, extflags, 200 LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE); 201 if (error) 202 break; 203 sharelock(lkp, 1); 204 COUNT(p, 1); 205 break; 206 } 207 /* 208 * We hold an exclusive lock, so downgrade it to shared. 209 * An alternative would be to fail with EDEADLK. 210 */ 211 sharelock(lkp, 1); 212 COUNT(p, 1); 213 /* fall into downgrade */ 214 215 case LK_DOWNGRADE: 216 #if !defined(MAX_PERF) 217 if (lkp->lk_lockholder != pid || lkp->lk_exclusivecount == 0) 218 panic("lockmgr: not holding exclusive lock"); 219 #endif 220 sharelock(lkp, lkp->lk_exclusivecount); 221 lkp->lk_exclusivecount = 0; 222 lkp->lk_flags &= ~LK_HAVE_EXCL; 223 lkp->lk_lockholder = LK_NOPROC; 224 if (lkp->lk_waitcount) 225 wakeup((void *)lkp); 226 break; 227 228 case LK_EXCLUPGRADE: 229 /* 230 * If another process is ahead of us to get an upgrade, 231 * then we want to fail rather than have an intervening 232 * exclusive access. 233 */ 234 if (lkp->lk_flags & LK_WANT_UPGRADE) { 235 shareunlock(lkp, 1); 236 COUNT(p, -1); 237 error = EBUSY; 238 break; 239 } 240 /* fall into normal upgrade */ 241 242 case LK_UPGRADE: 243 /* 244 * Upgrade a shared lock to an exclusive one. If another 245 * shared lock has already requested an upgrade to an 246 * exclusive lock, our shared lock is released and an 247 * exclusive lock is requested (which will be granted 248 * after the upgrade). If we return an error, the file 249 * will always be unlocked. 250 */ 251 #if !defined(MAX_PERF) 252 if ((lkp->lk_lockholder == pid) || (lkp->lk_sharecount <= 0)) 253 panic("lockmgr: upgrade exclusive lock"); 254 #endif 255 shareunlock(lkp, 1); 256 COUNT(p, -1); 257 /* 258 * If we are just polling, check to see if we will block. 259 */ 260 if ((extflags & LK_NOWAIT) && 261 ((lkp->lk_flags & LK_WANT_UPGRADE) || 262 lkp->lk_sharecount > 1)) { 263 error = EBUSY; 264 break; 265 } 266 if ((lkp->lk_flags & LK_WANT_UPGRADE) == 0) { 267 /* 268 * We are first shared lock to request an upgrade, so 269 * request upgrade and wait for the shared count to 270 * drop to zero, then take exclusive lock. 271 */ 272 lkp->lk_flags |= LK_WANT_UPGRADE; 273 error = acquire(lkp, extflags, LK_SHARE_NONZERO); 274 lkp->lk_flags &= ~LK_WANT_UPGRADE; 275 276 if (error) 277 break; 278 lkp->lk_flags |= LK_HAVE_EXCL; 279 lkp->lk_lockholder = pid; 280 #if !defined(MAX_PERF) 281 if (lkp->lk_exclusivecount != 0) 282 panic("lockmgr: non-zero exclusive count"); 283 #endif 284 lkp->lk_exclusivecount = 1; 285 COUNT(p, 1); 286 break; 287 } 288 /* 289 * Someone else has requested upgrade. Release our shared 290 * lock, awaken upgrade requestor if we are the last shared 291 * lock, then request an exclusive lock. 292 */ 293 if ( (lkp->lk_flags & (LK_SHARE_NONZERO|LK_WAIT_NONZERO)) == 294 LK_WAIT_NONZERO) 295 wakeup((void *)lkp); 296 /* fall into exclusive request */ 297 298 case LK_EXCLUSIVE: 299 if (lkp->lk_lockholder == pid && pid != LK_KERNPROC) { 300 /* 301 * Recursive lock. 302 */ 303 #if !defined(MAX_PERF) 304 if ((extflags & LK_CANRECURSE) == 0) 305 panic("lockmgr: locking against myself"); 306 #endif 307 lkp->lk_exclusivecount++; 308 COUNT(p, 1); 309 break; 310 } 311 /* 312 * If we are just polling, check to see if we will sleep. 313 */ 314 if ((extflags & LK_NOWAIT) && 315 (lkp->lk_flags & (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE | LK_SHARE_NONZERO))) { 316 error = EBUSY; 317 break; 318 } 319 /* 320 * Try to acquire the want_exclusive flag. 321 */ 322 error = acquire(lkp, extflags, (LK_HAVE_EXCL | LK_WANT_EXCL)); 323 if (error) 324 break; 325 lkp->lk_flags |= LK_WANT_EXCL; 326 /* 327 * Wait for shared locks and upgrades to finish. 328 */ 329 error = acquire(lkp, extflags, LK_WANT_UPGRADE | LK_SHARE_NONZERO); 330 lkp->lk_flags &= ~LK_WANT_EXCL; 331 if (error) 332 break; 333 lkp->lk_flags |= LK_HAVE_EXCL; 334 lkp->lk_lockholder = pid; 335 #if !defined(MAX_PERF) 336 if (lkp->lk_exclusivecount != 0) 337 panic("lockmgr: non-zero exclusive count"); 338 #endif 339 lkp->lk_exclusivecount = 1; 340 COUNT(p, 1); 341 break; 342 343 case LK_RELEASE: 344 if (lkp->lk_exclusivecount != 0) { 345 #if !defined(MAX_PERF) 346 if (pid != lkp->lk_lockholder) 347 panic("lockmgr: pid %d, not %s %d unlocking", 348 pid, "exclusive lock holder", 349 lkp->lk_lockholder); 350 #endif 351 COUNT(p, -1); 352 if (lkp->lk_exclusivecount == 1) { 353 lkp->lk_flags &= ~LK_HAVE_EXCL; 354 lkp->lk_lockholder = LK_NOPROC; 355 lkp->lk_exclusivecount = 0; 356 } else { 357 lkp->lk_exclusivecount--; 358 } 359 } else if (lkp->lk_flags & LK_SHARE_NONZERO) { 360 shareunlock(lkp, 1); 361 COUNT(p, -1); 362 } 363 if (lkp->lk_flags & LK_WAIT_NONZERO) 364 wakeup((void *)lkp); 365 break; 366 367 case LK_DRAIN: 368 /* 369 * Check that we do not already hold the lock, as it can 370 * never drain if we do. Unfortunately, we have no way to 371 * check for holding a shared lock, but at least we can 372 * check for an exclusive one. 373 */ 374 #if !defined(MAX_PERF) 375 if (lkp->lk_lockholder == pid) 376 panic("lockmgr: draining against myself"); 377 #endif 378 379 error = acquiredrain(lkp, extflags); 380 if (error) 381 break; 382 lkp->lk_flags |= LK_DRAINING | LK_HAVE_EXCL; 383 lkp->lk_lockholder = pid; 384 lkp->lk_exclusivecount = 1; 385 COUNT(p, 1); 386 break; 387 388 default: 389 #if !defined(MAX_PERF) 390 simple_unlock(&lkp->lk_interlock); 391 panic("lockmgr: unknown locktype request %d", 392 flags & LK_TYPE_MASK); 393 #endif 394 /* NOTREACHED */ 395 } 396 if ((lkp->lk_flags & LK_WAITDRAIN) && 397 (lkp->lk_flags & (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE | 398 LK_SHARE_NONZERO | LK_WAIT_NONZERO)) == 0) { 399 lkp->lk_flags &= ~LK_WAITDRAIN; 400 wakeup((void *)&lkp->lk_flags); 401 } 402 simple_unlock(&lkp->lk_interlock); 403 return (error); 404 } 405 406 static int 407 acquiredrain(struct lock *lkp, int extflags) { 408 int error; 409 410 if ((extflags & LK_NOWAIT) && (lkp->lk_flags & LK_ALL)) { 411 return EBUSY; 412 } 413 414 error = apause(lkp, LK_ALL); 415 if (error == 0) 416 return 0; 417 418 while (lkp->lk_flags & LK_ALL) { 419 lkp->lk_flags |= LK_WAITDRAIN; 420 simple_unlock(&lkp->lk_interlock); 421 error = tsleep(&lkp->lk_flags, lkp->lk_prio, 422 lkp->lk_wmesg, lkp->lk_timo); 423 simple_lock(&lkp->lk_interlock); 424 if (error) 425 return error; 426 if (extflags & LK_SLEEPFAIL) { 427 return ENOLCK; 428 } 429 } 430 return 0; 431 } 432 433 /* 434 * Initialize a lock; required before use. 435 */ 436 void 437 lockinit(lkp, prio, wmesg, timo, flags) 438 struct lock *lkp; 439 int prio; 440 char *wmesg; 441 int timo; 442 int flags; 443 { 444 445 simple_lock_init(&lkp->lk_interlock); 446 lkp->lk_flags = (flags & LK_EXTFLG_MASK); 447 lkp->lk_sharecount = 0; 448 lkp->lk_waitcount = 0; 449 lkp->lk_exclusivecount = 0; 450 lkp->lk_prio = prio; 451 lkp->lk_wmesg = wmesg; 452 lkp->lk_timo = timo; 453 lkp->lk_lockholder = LK_NOPROC; 454 } 455 456 /* 457 * Determine the status of a lock. 458 */ 459 int 460 lockstatus(lkp) 461 struct lock *lkp; 462 { 463 int lock_type = 0; 464 465 simple_lock(&lkp->lk_interlock); 466 if (lkp->lk_exclusivecount != 0) 467 lock_type = LK_EXCLUSIVE; 468 else if (lkp->lk_sharecount != 0) 469 lock_type = LK_SHARED; 470 simple_unlock(&lkp->lk_interlock); 471 return (lock_type); 472 } 473 474 /* 475 * Print out information about state of a lock. Used by VOP_PRINT 476 * routines to display status about contained locks. 477 */ 478 void 479 lockmgr_printinfo(lkp) 480 struct lock *lkp; 481 { 482 483 if (lkp->lk_sharecount) 484 printf(" lock type %s: SHARED (count %d)", lkp->lk_wmesg, 485 lkp->lk_sharecount); 486 else if (lkp->lk_flags & LK_HAVE_EXCL) 487 printf(" lock type %s: EXCL (count %d) by pid %d", 488 lkp->lk_wmesg, lkp->lk_exclusivecount, lkp->lk_lockholder); 489 if (lkp->lk_waitcount > 0) 490 printf(" with %d pending", lkp->lk_waitcount); 491 } 492 493 #if defined(SIMPLELOCK_DEBUG) && (NCPUS == 1 || defined(COMPILING_LINT)) 494 #include <sys/kernel.h> 495 #include <sys/sysctl.h> 496 497 static int lockpausetime = 0; 498 SYSCTL_INT(_debug, OID_AUTO, lockpausetime, CTLFLAG_RW, &lockpausetime, 0, ""); 499 500 static int simplelockrecurse; 501 502 /* 503 * Simple lock functions so that the debugger can see from whence 504 * they are being called. 505 */ 506 void 507 simple_lock_init(alp) 508 struct simplelock *alp; 509 { 510 511 alp->lock_data = 0; 512 } 513 514 void 515 _simple_lock(alp, id, l) 516 struct simplelock *alp; 517 const char *id; 518 int l; 519 { 520 521 if (simplelockrecurse) 522 return; 523 if (alp->lock_data == 1) { 524 if (lockpausetime == -1) 525 panic("%s:%d: simple_lock: lock held", id, l); 526 printf("%s:%d: simple_lock: lock held\n", id, l); 527 if (lockpausetime == 1) { 528 Debugger("simple_lock"); 529 /*BACKTRACE(curproc); */ 530 } else if (lockpausetime > 1) { 531 printf("%s:%d: simple_lock: lock held...", id, l); 532 tsleep(&lockpausetime, PCATCH | PPAUSE, "slock", 533 lockpausetime * hz); 534 printf(" continuing\n"); 535 } 536 } 537 alp->lock_data = 1; 538 if (curproc) 539 curproc->p_simple_locks++; 540 } 541 542 int 543 _simple_lock_try(alp, id, l) 544 struct simplelock *alp; 545 const char *id; 546 int l; 547 { 548 549 if (alp->lock_data) 550 return (0); 551 if (simplelockrecurse) 552 return (1); 553 alp->lock_data = 1; 554 if (curproc) 555 curproc->p_simple_locks++; 556 return (1); 557 } 558 559 void 560 _simple_unlock(alp, id, l) 561 struct simplelock *alp; 562 const char *id; 563 int l; 564 { 565 566 if (simplelockrecurse) 567 return; 568 if (alp->lock_data == 0) { 569 if (lockpausetime == -1) 570 panic("%s:%d: simple_unlock: lock not held", id, l); 571 printf("%s:%d: simple_unlock: lock not held\n", id, l); 572 if (lockpausetime == 1) { 573 Debugger("simple_unlock"); 574 /* BACKTRACE(curproc); */ 575 } else if (lockpausetime > 1) { 576 printf("%s:%d: simple_unlock: lock not held...", id, l); 577 tsleep(&lockpausetime, PCATCH | PPAUSE, "sunlock", 578 lockpausetime * hz); 579 printf(" continuing\n"); 580 } 581 } 582 alp->lock_data = 0; 583 if (curproc) 584 curproc->p_simple_locks--; 585 } 586 #elif defined(SIMPLELOCK_DEBUG) 587 #error "SIMPLELOCK_DEBUG is not compatible with SMP!" 588 #endif /* SIMPLELOCK_DEBUG && NCPUS == 1 */ 589