1 /*- 2 * Copyright (c) 2007 Attilio Rao <attilio@freebsd.org> 3 * Copyright (c) 2001 Jason Evans <jasone@freebsd.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice(s), this list of conditions and the following disclaimer as 11 * the first lines of this file unmodified other than the possible 12 * addition of one or more copyright notices. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice(s), this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 27 * DAMAGE. 28 */ 29 30 /* 31 * Shared/exclusive locks. This implementation attempts to ensure 32 * deterministic lock granting behavior, so that slocks and xlocks are 33 * interleaved. 34 * 35 * Priority propagation will not generally raise the priority of lock holders, 36 * so should not be relied upon in combination with sx locks. 37 */ 38 39 #include "opt_ddb.h" 40 #include "opt_kdtrace.h" 41 #include "opt_no_adaptive_sx.h" 42 43 #include <sys/cdefs.h> 44 __FBSDID("$FreeBSD$"); 45 46 #include <sys/param.h> 47 #include <sys/ktr.h> 48 #include <sys/linker_set.h> 49 #include <sys/lock.h> 50 #include <sys/mutex.h> 51 #include <sys/proc.h> 52 #include <sys/sleepqueue.h> 53 #include <sys/sx.h> 54 #include <sys/sysctl.h> 55 #include <sys/systm.h> 56 57 #if defined(SMP) && !defined(NO_ADAPTIVE_SX) 58 #include <machine/cpu.h> 59 #endif 60 61 #ifdef DDB 62 #include <ddb/ddb.h> 63 #endif 64 65 #if defined(SMP) && !defined(NO_ADAPTIVE_SX) 66 #define ADAPTIVE_SX 67 #endif 68 69 CTASSERT((SX_NOADAPTIVE & LO_CLASSFLAGS) == SX_NOADAPTIVE); 70 71 /* Handy macros for sleep queues. */ 72 #define SQ_EXCLUSIVE_QUEUE 0 73 #define SQ_SHARED_QUEUE 1 74 75 /* 76 * Variations on DROP_GIANT()/PICKUP_GIANT() for use in this file. We 77 * drop Giant anytime we have to sleep or if we adaptively spin. 78 */ 79 #define GIANT_DECLARE \ 80 int _giantcnt = 0; \ 81 WITNESS_SAVE_DECL(Giant) \ 82 83 #define GIANT_SAVE() do { \ 84 if (mtx_owned(&Giant)) { \ 85 WITNESS_SAVE(&Giant.lock_object, Giant); \ 86 while (mtx_owned(&Giant)) { \ 87 _giantcnt++; \ 88 mtx_unlock(&Giant); \ 89 } \ 90 } \ 91 } while (0) 92 93 #define GIANT_RESTORE() do { \ 94 if (_giantcnt > 0) { \ 95 mtx_assert(&Giant, MA_NOTOWNED); \ 96 while (_giantcnt--) \ 97 mtx_lock(&Giant); \ 98 WITNESS_RESTORE(&Giant.lock_object, Giant); \ 99 } \ 100 } while (0) 101 102 /* 103 * Returns true if an exclusive lock is recursed. It assumes 104 * curthread currently has an exclusive lock. 105 */ 106 #define sx_recurse lock_object.lo_data 107 #define sx_recursed(sx) ((sx)->sx_recurse != 0) 108 109 static void assert_sx(struct lock_object *lock, int what); 110 #ifdef DDB 111 static void db_show_sx(struct lock_object *lock); 112 #endif 113 static void lock_sx(struct lock_object *lock, int how); 114 #ifdef KDTRACE_HOOKS 115 static int owner_sx(struct lock_object *lock, struct thread **owner); 116 #endif 117 static int unlock_sx(struct lock_object *lock); 118 119 struct lock_class lock_class_sx = { 120 .lc_name = "sx", 121 .lc_flags = LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE | LC_UPGRADABLE, 122 .lc_assert = assert_sx, 123 #ifdef DDB 124 .lc_ddb_show = db_show_sx, 125 #endif 126 .lc_lock = lock_sx, 127 .lc_unlock = unlock_sx, 128 #ifdef KDTRACE_HOOKS 129 .lc_owner = owner_sx, 130 #endif 131 }; 132 133 #ifndef INVARIANTS 134 #define _sx_assert(sx, what, file, line) 135 #endif 136 137 #ifdef ADAPTIVE_SX 138 static u_int asx_retries = 10; 139 static u_int asx_loops = 10000; 140 SYSCTL_NODE(_debug, OID_AUTO, sx, CTLFLAG_RD, NULL, "sxlock debugging"); 141 SYSCTL_INT(_debug_sx, OID_AUTO, retries, CTLFLAG_RW, &asx_retries, 0, ""); 142 SYSCTL_INT(_debug_sx, OID_AUTO, loops, CTLFLAG_RW, &asx_loops, 0, ""); 143 #endif 144 145 void 146 assert_sx(struct lock_object *lock, int what) 147 { 148 149 sx_assert((struct sx *)lock, what); 150 } 151 152 void 153 lock_sx(struct lock_object *lock, int how) 154 { 155 struct sx *sx; 156 157 sx = (struct sx *)lock; 158 if (how) 159 sx_xlock(sx); 160 else 161 sx_slock(sx); 162 } 163 164 int 165 unlock_sx(struct lock_object *lock) 166 { 167 struct sx *sx; 168 169 sx = (struct sx *)lock; 170 sx_assert(sx, SA_LOCKED | SA_NOTRECURSED); 171 if (sx_xlocked(sx)) { 172 sx_xunlock(sx); 173 return (1); 174 } else { 175 sx_sunlock(sx); 176 return (0); 177 } 178 } 179 180 #ifdef KDTRACE_HOOKS 181 int 182 owner_sx(struct lock_object *lock, struct thread **owner) 183 { 184 struct sx *sx = (struct sx *)lock; 185 uintptr_t x = sx->sx_lock; 186 187 *owner = (struct thread *)SX_OWNER(x); 188 return ((x & SX_LOCK_SHARED) != 0 ? (SX_SHARERS(x) != 0) : 189 (*owner != NULL)); 190 } 191 #endif 192 193 void 194 sx_sysinit(void *arg) 195 { 196 struct sx_args *sargs = arg; 197 198 sx_init(sargs->sa_sx, sargs->sa_desc); 199 } 200 201 void 202 sx_init_flags(struct sx *sx, const char *description, int opts) 203 { 204 int flags; 205 206 MPASS((opts & ~(SX_QUIET | SX_RECURSE | SX_NOWITNESS | SX_DUPOK | 207 SX_NOPROFILE | SX_NOADAPTIVE)) == 0); 208 ASSERT_ATOMIC_LOAD_PTR(sx->sx_lock, 209 ("%s: sx_lock not aligned for %s: %p", __func__, description, 210 &sx->sx_lock)); 211 212 flags = LO_SLEEPABLE | LO_UPGRADABLE; 213 if (opts & SX_DUPOK) 214 flags |= LO_DUPOK; 215 if (opts & SX_NOPROFILE) 216 flags |= LO_NOPROFILE; 217 if (!(opts & SX_NOWITNESS)) 218 flags |= LO_WITNESS; 219 if (opts & SX_RECURSE) 220 flags |= LO_RECURSABLE; 221 if (opts & SX_QUIET) 222 flags |= LO_QUIET; 223 224 flags |= opts & SX_NOADAPTIVE; 225 sx->sx_lock = SX_LOCK_UNLOCKED; 226 sx->sx_recurse = 0; 227 lock_init(&sx->lock_object, &lock_class_sx, description, NULL, flags); 228 } 229 230 void 231 sx_destroy(struct sx *sx) 232 { 233 234 KASSERT(sx->sx_lock == SX_LOCK_UNLOCKED, ("sx lock still held")); 235 KASSERT(sx->sx_recurse == 0, ("sx lock still recursed")); 236 sx->sx_lock = SX_LOCK_DESTROYED; 237 lock_destroy(&sx->lock_object); 238 } 239 240 int 241 _sx_slock(struct sx *sx, int opts, const char *file, int line) 242 { 243 int error = 0; 244 245 MPASS(curthread != NULL); 246 KASSERT(sx->sx_lock != SX_LOCK_DESTROYED, 247 ("sx_slock() of destroyed sx @ %s:%d", file, line)); 248 WITNESS_CHECKORDER(&sx->lock_object, LOP_NEWORDER, file, line, NULL); 249 error = __sx_slock(sx, opts, file, line); 250 if (!error) { 251 LOCK_LOG_LOCK("SLOCK", &sx->lock_object, 0, 0, file, line); 252 WITNESS_LOCK(&sx->lock_object, 0, file, line); 253 curthread->td_locks++; 254 } 255 256 return (error); 257 } 258 259 int 260 _sx_try_slock(struct sx *sx, const char *file, int line) 261 { 262 uintptr_t x; 263 264 for (;;) { 265 x = sx->sx_lock; 266 KASSERT(x != SX_LOCK_DESTROYED, 267 ("sx_try_slock() of destroyed sx @ %s:%d", file, line)); 268 if (!(x & SX_LOCK_SHARED)) 269 break; 270 if (atomic_cmpset_acq_ptr(&sx->sx_lock, x, x + SX_ONE_SHARER)) { 271 LOCK_LOG_TRY("SLOCK", &sx->lock_object, 0, 1, file, line); 272 WITNESS_LOCK(&sx->lock_object, LOP_TRYLOCK, file, line); 273 curthread->td_locks++; 274 return (1); 275 } 276 } 277 278 LOCK_LOG_TRY("SLOCK", &sx->lock_object, 0, 0, file, line); 279 return (0); 280 } 281 282 int 283 _sx_xlock(struct sx *sx, int opts, const char *file, int line) 284 { 285 int error = 0; 286 287 MPASS(curthread != NULL); 288 KASSERT(sx->sx_lock != SX_LOCK_DESTROYED, 289 ("sx_xlock() of destroyed sx @ %s:%d", file, line)); 290 WITNESS_CHECKORDER(&sx->lock_object, LOP_NEWORDER | LOP_EXCLUSIVE, file, 291 line, NULL); 292 error = __sx_xlock(sx, curthread, opts, file, line); 293 if (!error) { 294 LOCK_LOG_LOCK("XLOCK", &sx->lock_object, 0, sx->sx_recurse, 295 file, line); 296 WITNESS_LOCK(&sx->lock_object, LOP_EXCLUSIVE, file, line); 297 curthread->td_locks++; 298 } 299 300 return (error); 301 } 302 303 int 304 _sx_try_xlock(struct sx *sx, const char *file, int line) 305 { 306 int rval; 307 308 MPASS(curthread != NULL); 309 KASSERT(sx->sx_lock != SX_LOCK_DESTROYED, 310 ("sx_try_xlock() of destroyed sx @ %s:%d", file, line)); 311 312 if (sx_xlocked(sx) && 313 (sx->lock_object.lo_flags & LO_RECURSABLE) != 0) { 314 sx->sx_recurse++; 315 atomic_set_ptr(&sx->sx_lock, SX_LOCK_RECURSED); 316 rval = 1; 317 } else 318 rval = atomic_cmpset_acq_ptr(&sx->sx_lock, SX_LOCK_UNLOCKED, 319 (uintptr_t)curthread); 320 LOCK_LOG_TRY("XLOCK", &sx->lock_object, 0, rval, file, line); 321 if (rval) { 322 WITNESS_LOCK(&sx->lock_object, LOP_EXCLUSIVE | LOP_TRYLOCK, 323 file, line); 324 curthread->td_locks++; 325 } 326 327 return (rval); 328 } 329 330 void 331 _sx_sunlock(struct sx *sx, const char *file, int line) 332 { 333 334 MPASS(curthread != NULL); 335 KASSERT(sx->sx_lock != SX_LOCK_DESTROYED, 336 ("sx_sunlock() of destroyed sx @ %s:%d", file, line)); 337 _sx_assert(sx, SA_SLOCKED, file, line); 338 curthread->td_locks--; 339 WITNESS_UNLOCK(&sx->lock_object, 0, file, line); 340 LOCK_LOG_LOCK("SUNLOCK", &sx->lock_object, 0, 0, file, line); 341 __sx_sunlock(sx, file, line); 342 LOCKSTAT_PROFILE_RELEASE_LOCK(LS_SX_SUNLOCK_RELEASE, sx); 343 } 344 345 void 346 _sx_xunlock(struct sx *sx, const char *file, int line) 347 { 348 349 MPASS(curthread != NULL); 350 KASSERT(sx->sx_lock != SX_LOCK_DESTROYED, 351 ("sx_xunlock() of destroyed sx @ %s:%d", file, line)); 352 _sx_assert(sx, SA_XLOCKED, file, line); 353 curthread->td_locks--; 354 WITNESS_UNLOCK(&sx->lock_object, LOP_EXCLUSIVE, file, line); 355 LOCK_LOG_LOCK("XUNLOCK", &sx->lock_object, 0, sx->sx_recurse, file, 356 line); 357 if (!sx_recursed(sx)) 358 LOCKSTAT_PROFILE_RELEASE_LOCK(LS_SX_XUNLOCK_RELEASE, sx); 359 __sx_xunlock(sx, curthread, file, line); 360 } 361 362 /* 363 * Try to do a non-blocking upgrade from a shared lock to an exclusive lock. 364 * This will only succeed if this thread holds a single shared lock. 365 * Return 1 if if the upgrade succeed, 0 otherwise. 366 */ 367 int 368 _sx_try_upgrade(struct sx *sx, const char *file, int line) 369 { 370 uintptr_t x; 371 int success; 372 373 KASSERT(sx->sx_lock != SX_LOCK_DESTROYED, 374 ("sx_try_upgrade() of destroyed sx @ %s:%d", file, line)); 375 _sx_assert(sx, SA_SLOCKED, file, line); 376 377 /* 378 * Try to switch from one shared lock to an exclusive lock. We need 379 * to maintain the SX_LOCK_EXCLUSIVE_WAITERS flag if set so that 380 * we will wake up the exclusive waiters when we drop the lock. 381 */ 382 x = sx->sx_lock & SX_LOCK_EXCLUSIVE_WAITERS; 383 success = atomic_cmpset_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1) | x, 384 (uintptr_t)curthread | x); 385 LOCK_LOG_TRY("XUPGRADE", &sx->lock_object, 0, success, file, line); 386 if (success) { 387 WITNESS_UPGRADE(&sx->lock_object, LOP_EXCLUSIVE | LOP_TRYLOCK, 388 file, line); 389 LOCKSTAT_RECORD0(LS_SX_TRYUPGRADE_UPGRADE, sx); 390 } 391 return (success); 392 } 393 394 /* 395 * Downgrade an unrecursed exclusive lock into a single shared lock. 396 */ 397 void 398 _sx_downgrade(struct sx *sx, const char *file, int line) 399 { 400 uintptr_t x; 401 int wakeup_swapper; 402 403 KASSERT(sx->sx_lock != SX_LOCK_DESTROYED, 404 ("sx_downgrade() of destroyed sx @ %s:%d", file, line)); 405 _sx_assert(sx, SA_XLOCKED | SA_NOTRECURSED, file, line); 406 #ifndef INVARIANTS 407 if (sx_recursed(sx)) 408 panic("downgrade of a recursed lock"); 409 #endif 410 411 WITNESS_DOWNGRADE(&sx->lock_object, 0, file, line); 412 413 /* 414 * Try to switch from an exclusive lock with no shared waiters 415 * to one sharer with no shared waiters. If there are 416 * exclusive waiters, we don't need to lock the sleep queue so 417 * long as we preserve the flag. We do one quick try and if 418 * that fails we grab the sleepq lock to keep the flags from 419 * changing and do it the slow way. 420 * 421 * We have to lock the sleep queue if there are shared waiters 422 * so we can wake them up. 423 */ 424 x = sx->sx_lock; 425 if (!(x & SX_LOCK_SHARED_WAITERS) && 426 atomic_cmpset_rel_ptr(&sx->sx_lock, x, SX_SHARERS_LOCK(1) | 427 (x & SX_LOCK_EXCLUSIVE_WAITERS))) { 428 LOCK_LOG_LOCK("XDOWNGRADE", &sx->lock_object, 0, 0, file, line); 429 return; 430 } 431 432 /* 433 * Lock the sleep queue so we can read the waiters bits 434 * without any races and wakeup any shared waiters. 435 */ 436 sleepq_lock(&sx->lock_object); 437 438 /* 439 * Preserve SX_LOCK_EXCLUSIVE_WAITERS while downgraded to a single 440 * shared lock. If there are any shared waiters, wake them up. 441 */ 442 wakeup_swapper = 0; 443 x = sx->sx_lock; 444 atomic_store_rel_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1) | 445 (x & SX_LOCK_EXCLUSIVE_WAITERS)); 446 if (x & SX_LOCK_SHARED_WAITERS) 447 wakeup_swapper = sleepq_broadcast(&sx->lock_object, SLEEPQ_SX, 448 0, SQ_SHARED_QUEUE); 449 sleepq_release(&sx->lock_object); 450 451 LOCK_LOG_LOCK("XDOWNGRADE", &sx->lock_object, 0, 0, file, line); 452 LOCKSTAT_RECORD0(LS_SX_DOWNGRADE_DOWNGRADE, sx); 453 454 if (wakeup_swapper) 455 kick_proc0(); 456 } 457 458 /* 459 * This function represents the so-called 'hard case' for sx_xlock 460 * operation. All 'easy case' failures are redirected to this. Note 461 * that ideally this would be a static function, but it needs to be 462 * accessible from at least sx.h. 463 */ 464 int 465 _sx_xlock_hard(struct sx *sx, uintptr_t tid, int opts, const char *file, 466 int line) 467 { 468 GIANT_DECLARE; 469 #ifdef ADAPTIVE_SX 470 volatile struct thread *owner; 471 u_int i, spintries = 0; 472 #endif 473 uintptr_t x; 474 #ifdef LOCK_PROFILING 475 uint64_t waittime = 0; 476 int contested = 0; 477 #endif 478 int error = 0; 479 #ifdef KDTRACE_HOOKS 480 uint64_t spin_cnt = 0; 481 uint64_t sleep_cnt = 0; 482 int64_t sleep_time = 0; 483 #endif 484 485 /* If we already hold an exclusive lock, then recurse. */ 486 if (sx_xlocked(sx)) { 487 KASSERT((sx->lock_object.lo_flags & LO_RECURSABLE) != 0, 488 ("_sx_xlock_hard: recursed on non-recursive sx %s @ %s:%d\n", 489 sx->lock_object.lo_name, file, line)); 490 sx->sx_recurse++; 491 atomic_set_ptr(&sx->sx_lock, SX_LOCK_RECURSED); 492 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 493 CTR2(KTR_LOCK, "%s: %p recursing", __func__, sx); 494 return (0); 495 } 496 497 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 498 CTR5(KTR_LOCK, "%s: %s contested (lock=%p) at %s:%d", __func__, 499 sx->lock_object.lo_name, (void *)sx->sx_lock, file, line); 500 501 while (!atomic_cmpset_acq_ptr(&sx->sx_lock, SX_LOCK_UNLOCKED, tid)) { 502 #ifdef KDTRACE_HOOKS 503 spin_cnt++; 504 #endif 505 lock_profile_obtain_lock_failed(&sx->lock_object, &contested, 506 &waittime); 507 #ifdef ADAPTIVE_SX 508 /* 509 * If the lock is write locked and the owner is 510 * running on another CPU, spin until the owner stops 511 * running or the state of the lock changes. 512 */ 513 x = sx->sx_lock; 514 if ((sx->lock_object.lo_flags & SX_NOADAPTIVE) != 0) { 515 if ((x & SX_LOCK_SHARED) == 0) { 516 x = SX_OWNER(x); 517 owner = (struct thread *)x; 518 if (TD_IS_RUNNING(owner)) { 519 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 520 CTR3(KTR_LOCK, 521 "%s: spinning on %p held by %p", 522 __func__, sx, owner); 523 GIANT_SAVE(); 524 while (SX_OWNER(sx->sx_lock) == x && 525 TD_IS_RUNNING(owner)) { 526 cpu_spinwait(); 527 #ifdef KDTRACE_HOOKS 528 spin_cnt++; 529 #endif 530 } 531 continue; 532 } 533 } else if (SX_SHARERS(x) && spintries < asx_retries) { 534 GIANT_SAVE(); 535 spintries++; 536 for (i = 0; i < asx_loops; i++) { 537 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 538 CTR4(KTR_LOCK, 539 "%s: shared spinning on %p with %u and %u", 540 __func__, sx, spintries, i); 541 x = sx->sx_lock; 542 if ((x & SX_LOCK_SHARED) == 0 || 543 SX_SHARERS(x) == 0) 544 break; 545 cpu_spinwait(); 546 #ifdef KDTRACE_HOOKS 547 spin_cnt++; 548 #endif 549 } 550 if (i != asx_loops) 551 continue; 552 } 553 } 554 #endif 555 556 sleepq_lock(&sx->lock_object); 557 x = sx->sx_lock; 558 559 /* 560 * If the lock was released while spinning on the 561 * sleep queue chain lock, try again. 562 */ 563 if (x == SX_LOCK_UNLOCKED) { 564 sleepq_release(&sx->lock_object); 565 continue; 566 } 567 568 #ifdef ADAPTIVE_SX 569 /* 570 * The current lock owner might have started executing 571 * on another CPU (or the lock could have changed 572 * owners) while we were waiting on the sleep queue 573 * chain lock. If so, drop the sleep queue lock and try 574 * again. 575 */ 576 if (!(x & SX_LOCK_SHARED) && 577 (sx->lock_object.lo_flags & SX_NOADAPTIVE) == 0) { 578 owner = (struct thread *)SX_OWNER(x); 579 if (TD_IS_RUNNING(owner)) { 580 sleepq_release(&sx->lock_object); 581 continue; 582 } 583 } 584 #endif 585 586 /* 587 * If an exclusive lock was released with both shared 588 * and exclusive waiters and a shared waiter hasn't 589 * woken up and acquired the lock yet, sx_lock will be 590 * set to SX_LOCK_UNLOCKED | SX_LOCK_EXCLUSIVE_WAITERS. 591 * If we see that value, try to acquire it once. Note 592 * that we have to preserve SX_LOCK_EXCLUSIVE_WAITERS 593 * as there are other exclusive waiters still. If we 594 * fail, restart the loop. 595 */ 596 if (x == (SX_LOCK_UNLOCKED | SX_LOCK_EXCLUSIVE_WAITERS)) { 597 if (atomic_cmpset_acq_ptr(&sx->sx_lock, 598 SX_LOCK_UNLOCKED | SX_LOCK_EXCLUSIVE_WAITERS, 599 tid | SX_LOCK_EXCLUSIVE_WAITERS)) { 600 sleepq_release(&sx->lock_object); 601 CTR2(KTR_LOCK, "%s: %p claimed by new writer", 602 __func__, sx); 603 break; 604 } 605 sleepq_release(&sx->lock_object); 606 continue; 607 } 608 609 /* 610 * Try to set the SX_LOCK_EXCLUSIVE_WAITERS. If we fail, 611 * than loop back and retry. 612 */ 613 if (!(x & SX_LOCK_EXCLUSIVE_WAITERS)) { 614 if (!atomic_cmpset_ptr(&sx->sx_lock, x, 615 x | SX_LOCK_EXCLUSIVE_WAITERS)) { 616 sleepq_release(&sx->lock_object); 617 continue; 618 } 619 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 620 CTR2(KTR_LOCK, "%s: %p set excl waiters flag", 621 __func__, sx); 622 } 623 624 /* 625 * Since we have been unable to acquire the exclusive 626 * lock and the exclusive waiters flag is set, we have 627 * to sleep. 628 */ 629 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 630 CTR2(KTR_LOCK, "%s: %p blocking on sleep queue", 631 __func__, sx); 632 633 #ifdef KDTRACE_HOOKS 634 sleep_time -= lockstat_nsecs(); 635 #endif 636 GIANT_SAVE(); 637 sleepq_add(&sx->lock_object, NULL, sx->lock_object.lo_name, 638 SLEEPQ_SX | ((opts & SX_INTERRUPTIBLE) ? 639 SLEEPQ_INTERRUPTIBLE : 0), SQ_EXCLUSIVE_QUEUE); 640 if (!(opts & SX_INTERRUPTIBLE)) 641 sleepq_wait(&sx->lock_object, 0); 642 else 643 error = sleepq_wait_sig(&sx->lock_object, 0); 644 #ifdef KDTRACE_HOOKS 645 sleep_time += lockstat_nsecs(); 646 sleep_cnt++; 647 #endif 648 if (error) { 649 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 650 CTR2(KTR_LOCK, 651 "%s: interruptible sleep by %p suspended by signal", 652 __func__, sx); 653 break; 654 } 655 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 656 CTR2(KTR_LOCK, "%s: %p resuming from sleep queue", 657 __func__, sx); 658 } 659 660 GIANT_RESTORE(); 661 if (!error) 662 LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_SX_XLOCK_ACQUIRE, sx, 663 contested, waittime, file, line); 664 #ifdef KDTRACE_HOOKS 665 if (sleep_time) 666 LOCKSTAT_RECORD1(LS_SX_XLOCK_BLOCK, sx, sleep_time); 667 if (spin_cnt > sleep_cnt) 668 LOCKSTAT_RECORD1(LS_SX_XLOCK_SPIN, sx, (spin_cnt - sleep_cnt)); 669 #endif 670 return (error); 671 } 672 673 /* 674 * This function represents the so-called 'hard case' for sx_xunlock 675 * operation. All 'easy case' failures are redirected to this. Note 676 * that ideally this would be a static function, but it needs to be 677 * accessible from at least sx.h. 678 */ 679 void 680 _sx_xunlock_hard(struct sx *sx, uintptr_t tid, const char *file, int line) 681 { 682 uintptr_t x; 683 int queue, wakeup_swapper; 684 685 MPASS(!(sx->sx_lock & SX_LOCK_SHARED)); 686 687 /* If the lock is recursed, then unrecurse one level. */ 688 if (sx_xlocked(sx) && sx_recursed(sx)) { 689 if ((--sx->sx_recurse) == 0) 690 atomic_clear_ptr(&sx->sx_lock, SX_LOCK_RECURSED); 691 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 692 CTR2(KTR_LOCK, "%s: %p unrecursing", __func__, sx); 693 return; 694 } 695 MPASS(sx->sx_lock & (SX_LOCK_SHARED_WAITERS | 696 SX_LOCK_EXCLUSIVE_WAITERS)); 697 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 698 CTR2(KTR_LOCK, "%s: %p contested", __func__, sx); 699 700 sleepq_lock(&sx->lock_object); 701 x = SX_LOCK_UNLOCKED; 702 703 /* 704 * The wake up algorithm here is quite simple and probably not 705 * ideal. It gives precedence to shared waiters if they are 706 * present. For this condition, we have to preserve the 707 * state of the exclusive waiters flag. 708 */ 709 if (sx->sx_lock & SX_LOCK_SHARED_WAITERS) { 710 queue = SQ_SHARED_QUEUE; 711 x |= (sx->sx_lock & SX_LOCK_EXCLUSIVE_WAITERS); 712 } else 713 queue = SQ_EXCLUSIVE_QUEUE; 714 715 /* Wake up all the waiters for the specific queue. */ 716 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 717 CTR3(KTR_LOCK, "%s: %p waking up all threads on %s queue", 718 __func__, sx, queue == SQ_SHARED_QUEUE ? "shared" : 719 "exclusive"); 720 atomic_store_rel_ptr(&sx->sx_lock, x); 721 wakeup_swapper = sleepq_broadcast(&sx->lock_object, SLEEPQ_SX, 0, 722 queue); 723 sleepq_release(&sx->lock_object); 724 if (wakeup_swapper) 725 kick_proc0(); 726 } 727 728 /* 729 * This function represents the so-called 'hard case' for sx_slock 730 * operation. All 'easy case' failures are redirected to this. Note 731 * that ideally this would be a static function, but it needs to be 732 * accessible from at least sx.h. 733 */ 734 int 735 _sx_slock_hard(struct sx *sx, int opts, const char *file, int line) 736 { 737 GIANT_DECLARE; 738 #ifdef ADAPTIVE_SX 739 volatile struct thread *owner; 740 #endif 741 #ifdef LOCK_PROFILING 742 uint64_t waittime = 0; 743 int contested = 0; 744 #endif 745 uintptr_t x; 746 int error = 0; 747 #ifdef KDTRACE_HOOKS 748 uint64_t spin_cnt = 0; 749 uint64_t sleep_cnt = 0; 750 int64_t sleep_time = 0; 751 #endif 752 753 /* 754 * As with rwlocks, we don't make any attempt to try to block 755 * shared locks once there is an exclusive waiter. 756 */ 757 for (;;) { 758 #ifdef KDTRACE_HOOKS 759 spin_cnt++; 760 #endif 761 x = sx->sx_lock; 762 763 /* 764 * If no other thread has an exclusive lock then try to bump up 765 * the count of sharers. Since we have to preserve the state 766 * of SX_LOCK_EXCLUSIVE_WAITERS, if we fail to acquire the 767 * shared lock loop back and retry. 768 */ 769 if (x & SX_LOCK_SHARED) { 770 MPASS(!(x & SX_LOCK_SHARED_WAITERS)); 771 if (atomic_cmpset_acq_ptr(&sx->sx_lock, x, 772 x + SX_ONE_SHARER)) { 773 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 774 CTR4(KTR_LOCK, 775 "%s: %p succeed %p -> %p", __func__, 776 sx, (void *)x, 777 (void *)(x + SX_ONE_SHARER)); 778 break; 779 } 780 continue; 781 } 782 lock_profile_obtain_lock_failed(&sx->lock_object, &contested, 783 &waittime); 784 785 #ifdef ADAPTIVE_SX 786 /* 787 * If the owner is running on another CPU, spin until 788 * the owner stops running or the state of the lock 789 * changes. 790 */ 791 if ((sx->lock_object.lo_flags & SX_NOADAPTIVE) == 0) { 792 x = SX_OWNER(x); 793 owner = (struct thread *)x; 794 if (TD_IS_RUNNING(owner)) { 795 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 796 CTR3(KTR_LOCK, 797 "%s: spinning on %p held by %p", 798 __func__, sx, owner); 799 GIANT_SAVE(); 800 while (SX_OWNER(sx->sx_lock) == x && 801 TD_IS_RUNNING(owner)) { 802 #ifdef KDTRACE_HOOKS 803 spin_cnt++; 804 #endif 805 cpu_spinwait(); 806 } 807 continue; 808 } 809 } 810 #endif 811 812 /* 813 * Some other thread already has an exclusive lock, so 814 * start the process of blocking. 815 */ 816 sleepq_lock(&sx->lock_object); 817 x = sx->sx_lock; 818 819 /* 820 * The lock could have been released while we spun. 821 * In this case loop back and retry. 822 */ 823 if (x & SX_LOCK_SHARED) { 824 sleepq_release(&sx->lock_object); 825 continue; 826 } 827 828 #ifdef ADAPTIVE_SX 829 /* 830 * If the owner is running on another CPU, spin until 831 * the owner stops running or the state of the lock 832 * changes. 833 */ 834 if (!(x & SX_LOCK_SHARED) && 835 (sx->lock_object.lo_flags & SX_NOADAPTIVE) == 0) { 836 owner = (struct thread *)SX_OWNER(x); 837 if (TD_IS_RUNNING(owner)) { 838 sleepq_release(&sx->lock_object); 839 continue; 840 } 841 } 842 #endif 843 844 /* 845 * Try to set the SX_LOCK_SHARED_WAITERS flag. If we 846 * fail to set it drop the sleep queue lock and loop 847 * back. 848 */ 849 if (!(x & SX_LOCK_SHARED_WAITERS)) { 850 if (!atomic_cmpset_ptr(&sx->sx_lock, x, 851 x | SX_LOCK_SHARED_WAITERS)) { 852 sleepq_release(&sx->lock_object); 853 continue; 854 } 855 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 856 CTR2(KTR_LOCK, "%s: %p set shared waiters flag", 857 __func__, sx); 858 } 859 860 /* 861 * Since we have been unable to acquire the shared lock, 862 * we have to sleep. 863 */ 864 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 865 CTR2(KTR_LOCK, "%s: %p blocking on sleep queue", 866 __func__, sx); 867 868 #ifdef KDTRACE_HOOKS 869 sleep_time -= lockstat_nsecs(); 870 #endif 871 GIANT_SAVE(); 872 sleepq_add(&sx->lock_object, NULL, sx->lock_object.lo_name, 873 SLEEPQ_SX | ((opts & SX_INTERRUPTIBLE) ? 874 SLEEPQ_INTERRUPTIBLE : 0), SQ_SHARED_QUEUE); 875 if (!(opts & SX_INTERRUPTIBLE)) 876 sleepq_wait(&sx->lock_object, 0); 877 else 878 error = sleepq_wait_sig(&sx->lock_object, 0); 879 #ifdef KDTRACE_HOOKS 880 sleep_time += lockstat_nsecs(); 881 sleep_cnt++; 882 #endif 883 if (error) { 884 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 885 CTR2(KTR_LOCK, 886 "%s: interruptible sleep by %p suspended by signal", 887 __func__, sx); 888 break; 889 } 890 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 891 CTR2(KTR_LOCK, "%s: %p resuming from sleep queue", 892 __func__, sx); 893 } 894 if (error == 0) 895 LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_SX_SLOCK_ACQUIRE, sx, 896 contested, waittime, file, line); 897 #ifdef KDTRACE_HOOKS 898 if (sleep_time) 899 LOCKSTAT_RECORD1(LS_SX_XLOCK_BLOCK, sx, sleep_time); 900 if (spin_cnt > sleep_cnt) 901 LOCKSTAT_RECORD1(LS_SX_XLOCK_SPIN, sx, (spin_cnt - sleep_cnt)); 902 #endif 903 GIANT_RESTORE(); 904 return (error); 905 } 906 907 /* 908 * This function represents the so-called 'hard case' for sx_sunlock 909 * operation. All 'easy case' failures are redirected to this. Note 910 * that ideally this would be a static function, but it needs to be 911 * accessible from at least sx.h. 912 */ 913 void 914 _sx_sunlock_hard(struct sx *sx, const char *file, int line) 915 { 916 uintptr_t x; 917 int wakeup_swapper; 918 919 for (;;) { 920 x = sx->sx_lock; 921 922 /* 923 * We should never have sharers while at least one thread 924 * holds a shared lock. 925 */ 926 KASSERT(!(x & SX_LOCK_SHARED_WAITERS), 927 ("%s: waiting sharers", __func__)); 928 929 /* 930 * See if there is more than one shared lock held. If 931 * so, just drop one and return. 932 */ 933 if (SX_SHARERS(x) > 1) { 934 if (atomic_cmpset_rel_ptr(&sx->sx_lock, x, 935 x - SX_ONE_SHARER)) { 936 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 937 CTR4(KTR_LOCK, 938 "%s: %p succeeded %p -> %p", 939 __func__, sx, (void *)x, 940 (void *)(x - SX_ONE_SHARER)); 941 break; 942 } 943 continue; 944 } 945 946 /* 947 * If there aren't any waiters for an exclusive lock, 948 * then try to drop it quickly. 949 */ 950 if (!(x & SX_LOCK_EXCLUSIVE_WAITERS)) { 951 MPASS(x == SX_SHARERS_LOCK(1)); 952 if (atomic_cmpset_rel_ptr(&sx->sx_lock, 953 SX_SHARERS_LOCK(1), SX_LOCK_UNLOCKED)) { 954 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 955 CTR2(KTR_LOCK, "%s: %p last succeeded", 956 __func__, sx); 957 break; 958 } 959 continue; 960 } 961 962 /* 963 * At this point, there should just be one sharer with 964 * exclusive waiters. 965 */ 966 MPASS(x == (SX_SHARERS_LOCK(1) | SX_LOCK_EXCLUSIVE_WAITERS)); 967 968 sleepq_lock(&sx->lock_object); 969 970 /* 971 * Wake up semantic here is quite simple: 972 * Just wake up all the exclusive waiters. 973 * Note that the state of the lock could have changed, 974 * so if it fails loop back and retry. 975 */ 976 if (!atomic_cmpset_rel_ptr(&sx->sx_lock, 977 SX_SHARERS_LOCK(1) | SX_LOCK_EXCLUSIVE_WAITERS, 978 SX_LOCK_UNLOCKED)) { 979 sleepq_release(&sx->lock_object); 980 continue; 981 } 982 if (LOCK_LOG_TEST(&sx->lock_object, 0)) 983 CTR2(KTR_LOCK, "%s: %p waking up all thread on" 984 "exclusive queue", __func__, sx); 985 wakeup_swapper = sleepq_broadcast(&sx->lock_object, SLEEPQ_SX, 986 0, SQ_EXCLUSIVE_QUEUE); 987 sleepq_release(&sx->lock_object); 988 if (wakeup_swapper) 989 kick_proc0(); 990 break; 991 } 992 } 993 994 #ifdef INVARIANT_SUPPORT 995 #ifndef INVARIANTS 996 #undef _sx_assert 997 #endif 998 999 /* 1000 * In the non-WITNESS case, sx_assert() can only detect that at least 1001 * *some* thread owns an slock, but it cannot guarantee that *this* 1002 * thread owns an slock. 1003 */ 1004 void 1005 _sx_assert(struct sx *sx, int what, const char *file, int line) 1006 { 1007 #ifndef WITNESS 1008 int slocked = 0; 1009 #endif 1010 1011 if (panicstr != NULL) 1012 return; 1013 switch (what) { 1014 case SA_SLOCKED: 1015 case SA_SLOCKED | SA_NOTRECURSED: 1016 case SA_SLOCKED | SA_RECURSED: 1017 #ifndef WITNESS 1018 slocked = 1; 1019 /* FALLTHROUGH */ 1020 #endif 1021 case SA_LOCKED: 1022 case SA_LOCKED | SA_NOTRECURSED: 1023 case SA_LOCKED | SA_RECURSED: 1024 #ifdef WITNESS 1025 witness_assert(&sx->lock_object, what, file, line); 1026 #else 1027 /* 1028 * If some other thread has an exclusive lock or we 1029 * have one and are asserting a shared lock, fail. 1030 * Also, if no one has a lock at all, fail. 1031 */ 1032 if (sx->sx_lock == SX_LOCK_UNLOCKED || 1033 (!(sx->sx_lock & SX_LOCK_SHARED) && (slocked || 1034 sx_xholder(sx) != curthread))) 1035 panic("Lock %s not %slocked @ %s:%d\n", 1036 sx->lock_object.lo_name, slocked ? "share " : "", 1037 file, line); 1038 1039 if (!(sx->sx_lock & SX_LOCK_SHARED)) { 1040 if (sx_recursed(sx)) { 1041 if (what & SA_NOTRECURSED) 1042 panic("Lock %s recursed @ %s:%d\n", 1043 sx->lock_object.lo_name, file, 1044 line); 1045 } else if (what & SA_RECURSED) 1046 panic("Lock %s not recursed @ %s:%d\n", 1047 sx->lock_object.lo_name, file, line); 1048 } 1049 #endif 1050 break; 1051 case SA_XLOCKED: 1052 case SA_XLOCKED | SA_NOTRECURSED: 1053 case SA_XLOCKED | SA_RECURSED: 1054 if (sx_xholder(sx) != curthread) 1055 panic("Lock %s not exclusively locked @ %s:%d\n", 1056 sx->lock_object.lo_name, file, line); 1057 if (sx_recursed(sx)) { 1058 if (what & SA_NOTRECURSED) 1059 panic("Lock %s recursed @ %s:%d\n", 1060 sx->lock_object.lo_name, file, line); 1061 } else if (what & SA_RECURSED) 1062 panic("Lock %s not recursed @ %s:%d\n", 1063 sx->lock_object.lo_name, file, line); 1064 break; 1065 case SA_UNLOCKED: 1066 #ifdef WITNESS 1067 witness_assert(&sx->lock_object, what, file, line); 1068 #else 1069 /* 1070 * If we hold an exclusve lock fail. We can't 1071 * reliably check to see if we hold a shared lock or 1072 * not. 1073 */ 1074 if (sx_xholder(sx) == curthread) 1075 panic("Lock %s exclusively locked @ %s:%d\n", 1076 sx->lock_object.lo_name, file, line); 1077 #endif 1078 break; 1079 default: 1080 panic("Unknown sx lock assertion: %d @ %s:%d", what, file, 1081 line); 1082 } 1083 } 1084 #endif /* INVARIANT_SUPPORT */ 1085 1086 #ifdef DDB 1087 static void 1088 db_show_sx(struct lock_object *lock) 1089 { 1090 struct thread *td; 1091 struct sx *sx; 1092 1093 sx = (struct sx *)lock; 1094 1095 db_printf(" state: "); 1096 if (sx->sx_lock == SX_LOCK_UNLOCKED) 1097 db_printf("UNLOCKED\n"); 1098 else if (sx->sx_lock == SX_LOCK_DESTROYED) { 1099 db_printf("DESTROYED\n"); 1100 return; 1101 } else if (sx->sx_lock & SX_LOCK_SHARED) 1102 db_printf("SLOCK: %ju\n", (uintmax_t)SX_SHARERS(sx->sx_lock)); 1103 else { 1104 td = sx_xholder(sx); 1105 db_printf("XLOCK: %p (tid %d, pid %d, \"%s\")\n", td, 1106 td->td_tid, td->td_proc->p_pid, td->td_name); 1107 if (sx_recursed(sx)) 1108 db_printf(" recursed: %d\n", sx->sx_recurse); 1109 } 1110 1111 db_printf(" waiters: "); 1112 switch(sx->sx_lock & 1113 (SX_LOCK_SHARED_WAITERS | SX_LOCK_EXCLUSIVE_WAITERS)) { 1114 case SX_LOCK_SHARED_WAITERS: 1115 db_printf("shared\n"); 1116 break; 1117 case SX_LOCK_EXCLUSIVE_WAITERS: 1118 db_printf("exclusive\n"); 1119 break; 1120 case SX_LOCK_SHARED_WAITERS | SX_LOCK_EXCLUSIVE_WAITERS: 1121 db_printf("exclusive and shared\n"); 1122 break; 1123 default: 1124 db_printf("none\n"); 1125 } 1126 } 1127 1128 /* 1129 * Check to see if a thread that is blocked on a sleep queue is actually 1130 * blocked on an sx lock. If so, output some details and return true. 1131 * If the lock has an exclusive owner, return that in *ownerp. 1132 */ 1133 int 1134 sx_chain(struct thread *td, struct thread **ownerp) 1135 { 1136 struct sx *sx; 1137 1138 /* 1139 * Check to see if this thread is blocked on an sx lock. 1140 * First, we check the lock class. If that is ok, then we 1141 * compare the lock name against the wait message. 1142 */ 1143 sx = td->td_wchan; 1144 if (LOCK_CLASS(&sx->lock_object) != &lock_class_sx || 1145 sx->lock_object.lo_name != td->td_wmesg) 1146 return (0); 1147 1148 /* We think we have an sx lock, so output some details. */ 1149 db_printf("blocked on sx \"%s\" ", td->td_wmesg); 1150 *ownerp = sx_xholder(sx); 1151 if (sx->sx_lock & SX_LOCK_SHARED) 1152 db_printf("SLOCK (count %ju)\n", 1153 (uintmax_t)SX_SHARERS(sx->sx_lock)); 1154 else 1155 db_printf("XLOCK\n"); 1156 return (1); 1157 } 1158 #endif 1159