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