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