locks.c
1 /* 2 * Copyright (c) 2000-2019 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 /* 29 * @OSF_COPYRIGHT@ 30 */ 31 /* 32 * Mach Operating System 33 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University 34 * All Rights Reserved. 35 * 36 * Permission to use, copy, modify and distribute this software and its 37 * documentation is hereby granted, provided that both the copyright 38 * notice and this permission notice appear in all copies of the 39 * software, derivative works or modified versions, and any portions 40 * thereof, and that both notices appear in supporting documentation. 41 * 42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 45 * 46 * Carnegie Mellon requests users of this software to return to 47 * 48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 49 * School of Computer Science 50 * Carnegie Mellon University 51 * Pittsburgh PA 15213-3890 52 * 53 * any improvements or extensions that they make and grant Carnegie Mellon 54 * the rights to redistribute these changes. 55 */ 56 57 #define LOCK_PRIVATE 1 58 59 #include <mach_ldebug.h> 60 #include <debug.h> 61 62 #include <mach/kern_return.h> 63 #include <mach/mach_host_server.h> 64 #include <mach_debug/lockgroup_info.h> 65 66 #include <kern/lock_stat.h> 67 #include <kern/locks.h> 68 #include <kern/misc_protos.h> 69 #include <kern/zalloc.h> 70 #include <kern/thread.h> 71 #include <kern/processor.h> 72 #include <kern/sched_prim.h> 73 #include <kern/debug.h> 74 #include <libkern/section_keywords.h> 75 #include <machine/atomic.h> 76 #include <machine/machine_cpu.h> 77 #include <string.h> 78 79 #include <sys/kdebug.h> 80 81 #define LCK_MTX_SLEEP_CODE 0 82 #define LCK_MTX_SLEEP_DEADLINE_CODE 1 83 #define LCK_MTX_LCK_WAIT_CODE 2 84 #define LCK_MTX_UNLCK_WAKEUP_CODE 3 85 86 #if MACH_LDEBUG 87 #define ALIGN_TEST(p, t) do{if((uintptr_t)p&(sizeof(t)-1)) __builtin_trap();}while(0) 88 #else 89 #define ALIGN_TEST(p, t) do{}while(0) 90 #endif 91 92 #define NOINLINE __attribute__((noinline)) 93 94 #define ordered_load_hw(lock) os_atomic_load(&(lock)->lock_data, compiler_acq_rel) 95 #define ordered_store_hw(lock, value) os_atomic_store(&(lock)->lock_data, (value), compiler_acq_rel) 96 97 98 queue_head_t lck_grp_queue; 99 unsigned int lck_grp_cnt; 100 101 decl_lck_mtx_data(, lck_grp_lock); 102 static lck_mtx_ext_t lck_grp_lock_ext; 103 104 SECURITY_READ_ONLY_LATE(boolean_t) spinlock_timeout_panic = TRUE; 105 106 /* Obtain "lcks" options:this currently controls lock statistics */ 107 TUNABLE(uint32_t, LcksOpts, "lcks", 0); 108 109 ZONE_VIEW_DEFINE(ZV_LCK_GRP_ATTR, "lck_grp_attr", 110 KHEAP_ID_DEFAULT, sizeof(lck_grp_attr_t)); 111 112 ZONE_VIEW_DEFINE(ZV_LCK_GRP, "lck_grp", 113 KHEAP_ID_DEFAULT, sizeof(lck_grp_t)); 114 115 ZONE_VIEW_DEFINE(ZV_LCK_ATTR, "lck_attr", 116 KHEAP_ID_DEFAULT, sizeof(lck_attr_t)); 117 118 lck_grp_attr_t LockDefaultGroupAttr; 119 lck_grp_t LockCompatGroup; 120 lck_attr_t LockDefaultLckAttr; 121 122 #if CONFIG_DTRACE 123 #if defined (__x86_64__) 124 uint64_t dtrace_spin_threshold = 500; // 500ns 125 #elif defined(__arm__) || defined(__arm64__) 126 uint64_t dtrace_spin_threshold = LOCK_PANIC_TIMEOUT / 1000000; // 500ns 127 #endif 128 #endif 129 130 uintptr_t 131 unslide_for_kdebug(void* object) 132 { 133 if (__improbable(kdebug_enable)) { 134 return VM_KERNEL_UNSLIDE_OR_PERM(object); 135 } else { 136 return 0; 137 } 138 } 139 140 __startup_func 141 static void 142 lck_mod_init(void) 143 { 144 queue_init(&lck_grp_queue); 145 146 /* 147 * Need to bootstrap the LockCompatGroup instead of calling lck_grp_init() here. This avoids 148 * grabbing the lck_grp_lock before it is initialized. 149 */ 150 151 bzero(&LockCompatGroup, sizeof(lck_grp_t)); 152 (void) strncpy(LockCompatGroup.lck_grp_name, "Compatibility APIs", LCK_GRP_MAX_NAME); 153 154 LockCompatGroup.lck_grp_attr = LCK_ATTR_NONE; 155 156 if (LcksOpts & enaLkStat) { 157 LockCompatGroup.lck_grp_attr |= LCK_GRP_ATTR_STAT; 158 } 159 if (LcksOpts & enaLkTimeStat) { 160 LockCompatGroup.lck_grp_attr |= LCK_GRP_ATTR_TIME_STAT; 161 } 162 163 os_ref_init(&LockCompatGroup.lck_grp_refcnt, NULL); 164 165 enqueue_tail(&lck_grp_queue, (queue_entry_t)&LockCompatGroup); 166 lck_grp_cnt = 1; 167 168 lck_grp_attr_setdefault(&LockDefaultGroupAttr); 169 lck_attr_setdefault(&LockDefaultLckAttr); 170 171 lck_mtx_init_ext(&lck_grp_lock, &lck_grp_lock_ext, &LockCompatGroup, &LockDefaultLckAttr); 172 } 173 STARTUP(LOCKS_EARLY, STARTUP_RANK_FIRST, lck_mod_init); 174 175 /* 176 * Routine: lck_grp_attr_alloc_init 177 */ 178 179 lck_grp_attr_t * 180 lck_grp_attr_alloc_init( 181 void) 182 { 183 lck_grp_attr_t *attr; 184 185 attr = zalloc(ZV_LCK_GRP_ATTR); 186 lck_grp_attr_setdefault(attr); 187 return attr; 188 } 189 190 191 /* 192 * Routine: lck_grp_attr_setdefault 193 */ 194 195 void 196 lck_grp_attr_setdefault( 197 lck_grp_attr_t *attr) 198 { 199 if (LcksOpts & enaLkStat) { 200 attr->grp_attr_val = LCK_GRP_ATTR_STAT; 201 } else { 202 attr->grp_attr_val = 0; 203 } 204 } 205 206 207 /* 208 * Routine: lck_grp_attr_setstat 209 */ 210 211 void 212 lck_grp_attr_setstat( 213 lck_grp_attr_t *attr) 214 { 215 #pragma unused(attr) 216 os_atomic_or(&attr->grp_attr_val, LCK_GRP_ATTR_STAT, relaxed); 217 } 218 219 220 /* 221 * Routine: lck_grp_attr_free 222 */ 223 224 void 225 lck_grp_attr_free( 226 lck_grp_attr_t *attr) 227 { 228 zfree(ZV_LCK_GRP_ATTR, attr); 229 } 230 231 232 /* 233 * Routine: lck_grp_alloc_init 234 */ 235 236 lck_grp_t * 237 lck_grp_alloc_init( 238 const char* grp_name, 239 lck_grp_attr_t *attr) 240 { 241 lck_grp_t *grp; 242 243 grp = zalloc(ZV_LCK_GRP); 244 lck_grp_init(grp, grp_name, attr); 245 return grp; 246 } 247 248 /* 249 * Routine: lck_grp_init 250 */ 251 252 void 253 lck_grp_init(lck_grp_t * grp, const char * grp_name, lck_grp_attr_t * attr) 254 { 255 /* make sure locking infrastructure has been initialized */ 256 assert(lck_grp_cnt > 0); 257 258 bzero((void *)grp, sizeof(lck_grp_t)); 259 260 (void)strlcpy(grp->lck_grp_name, grp_name, LCK_GRP_MAX_NAME); 261 262 if (attr != LCK_GRP_ATTR_NULL) { 263 grp->lck_grp_attr = attr->grp_attr_val; 264 } else { 265 grp->lck_grp_attr = 0; 266 if (LcksOpts & enaLkStat) { 267 grp->lck_grp_attr |= LCK_GRP_ATTR_STAT; 268 } 269 if (LcksOpts & enaLkTimeStat) { 270 grp->lck_grp_attr |= LCK_GRP_ATTR_TIME_STAT; 271 } 272 } 273 274 if (grp->lck_grp_attr & LCK_GRP_ATTR_STAT) { 275 lck_grp_stats_t *stats = &grp->lck_grp_stats; 276 277 #if LOCK_STATS 278 lck_grp_stat_enable(&stats->lgss_spin_held); 279 lck_grp_stat_enable(&stats->lgss_spin_miss); 280 #endif /* LOCK_STATS */ 281 282 lck_grp_stat_enable(&stats->lgss_mtx_held); 283 lck_grp_stat_enable(&stats->lgss_mtx_miss); 284 lck_grp_stat_enable(&stats->lgss_mtx_direct_wait); 285 lck_grp_stat_enable(&stats->lgss_mtx_wait); 286 } 287 if (grp->lck_grp_attr & LCK_GRP_ATTR_TIME_STAT) { 288 #if LOCK_STATS 289 lck_grp_stats_t *stats = &grp->lck_grp_stats; 290 lck_grp_stat_enable(&stats->lgss_spin_spin); 291 #endif /* LOCK_STATS */ 292 } 293 294 os_ref_init(&grp->lck_grp_refcnt, NULL); 295 296 lck_mtx_lock(&lck_grp_lock); 297 enqueue_tail(&lck_grp_queue, (queue_entry_t)grp); 298 lck_grp_cnt++; 299 lck_mtx_unlock(&lck_grp_lock); 300 } 301 302 /* 303 * Routine: lck_grp_free 304 */ 305 306 void 307 lck_grp_free( 308 lck_grp_t *grp) 309 { 310 lck_mtx_lock(&lck_grp_lock); 311 lck_grp_cnt--; 312 (void)remque((queue_entry_t)grp); 313 lck_mtx_unlock(&lck_grp_lock); 314 lck_grp_deallocate(grp); 315 } 316 317 318 /* 319 * Routine: lck_grp_reference 320 */ 321 322 void 323 lck_grp_reference( 324 lck_grp_t *grp) 325 { 326 os_ref_retain(&grp->lck_grp_refcnt); 327 } 328 329 330 /* 331 * Routine: lck_grp_deallocate 332 */ 333 334 void 335 lck_grp_deallocate( 336 lck_grp_t *grp) 337 { 338 if (os_ref_release(&grp->lck_grp_refcnt) != 0) { 339 return; 340 } 341 342 zfree(ZV_LCK_GRP, grp); 343 } 344 345 /* 346 * Routine: lck_grp_lckcnt_incr 347 */ 348 349 void 350 lck_grp_lckcnt_incr( 351 lck_grp_t *grp, 352 lck_type_t lck_type) 353 { 354 unsigned int *lckcnt; 355 356 switch (lck_type) { 357 case LCK_TYPE_SPIN: 358 lckcnt = &grp->lck_grp_spincnt; 359 break; 360 case LCK_TYPE_MTX: 361 lckcnt = &grp->lck_grp_mtxcnt; 362 break; 363 case LCK_TYPE_RW: 364 lckcnt = &grp->lck_grp_rwcnt; 365 break; 366 case LCK_TYPE_TICKET: 367 lckcnt = &grp->lck_grp_ticketcnt; 368 break; 369 default: 370 return panic("lck_grp_lckcnt_incr(): invalid lock type: %d\n", lck_type); 371 } 372 373 os_atomic_inc(lckcnt, relaxed); 374 } 375 376 /* 377 * Routine: lck_grp_lckcnt_decr 378 */ 379 380 void 381 lck_grp_lckcnt_decr( 382 lck_grp_t *grp, 383 lck_type_t lck_type) 384 { 385 unsigned int *lckcnt; 386 int updated; 387 388 switch (lck_type) { 389 case LCK_TYPE_SPIN: 390 lckcnt = &grp->lck_grp_spincnt; 391 break; 392 case LCK_TYPE_MTX: 393 lckcnt = &grp->lck_grp_mtxcnt; 394 break; 395 case LCK_TYPE_RW: 396 lckcnt = &grp->lck_grp_rwcnt; 397 break; 398 case LCK_TYPE_TICKET: 399 lckcnt = &grp->lck_grp_ticketcnt; 400 break; 401 default: 402 panic("lck_grp_lckcnt_decr(): invalid lock type: %d\n", lck_type); 403 return; 404 } 405 406 updated = os_atomic_dec(lckcnt, relaxed); 407 assert(updated >= 0); 408 } 409 410 /* 411 * Routine: lck_attr_alloc_init 412 */ 413 414 lck_attr_t * 415 lck_attr_alloc_init( 416 void) 417 { 418 lck_attr_t *attr; 419 420 attr = zalloc(ZV_LCK_ATTR); 421 lck_attr_setdefault(attr); 422 return attr; 423 } 424 425 426 /* 427 * Routine: lck_attr_setdefault 428 */ 429 430 void 431 lck_attr_setdefault( 432 lck_attr_t *attr) 433 { 434 #if __arm__ || __arm64__ 435 /* <rdar://problem/4404579>: Using LCK_ATTR_DEBUG here causes panic at boot time for arm */ 436 attr->lck_attr_val = LCK_ATTR_NONE; 437 #elif __i386__ || __x86_64__ 438 #if !DEBUG 439 if (LcksOpts & enaLkDeb) { 440 attr->lck_attr_val = LCK_ATTR_DEBUG; 441 } else { 442 attr->lck_attr_val = LCK_ATTR_NONE; 443 } 444 #else 445 attr->lck_attr_val = LCK_ATTR_DEBUG; 446 #endif /* !DEBUG */ 447 #else 448 #error Unknown architecture. 449 #endif /* __arm__ */ 450 } 451 452 453 /* 454 * Routine: lck_attr_setdebug 455 */ 456 void 457 lck_attr_setdebug( 458 lck_attr_t *attr) 459 { 460 os_atomic_or(&attr->lck_attr_val, LCK_ATTR_DEBUG, relaxed); 461 } 462 463 /* 464 * Routine: lck_attr_setdebug 465 */ 466 void 467 lck_attr_cleardebug( 468 lck_attr_t *attr) 469 { 470 os_atomic_andnot(&attr->lck_attr_val, LCK_ATTR_DEBUG, relaxed); 471 } 472 473 474 /* 475 * Routine: lck_attr_rw_shared_priority 476 */ 477 void 478 lck_attr_rw_shared_priority( 479 lck_attr_t *attr) 480 { 481 os_atomic_or(&attr->lck_attr_val, LCK_ATTR_RW_SHARED_PRIORITY, relaxed); 482 } 483 484 485 /* 486 * Routine: lck_attr_free 487 */ 488 void 489 lck_attr_free( 490 lck_attr_t *attr) 491 { 492 zfree(ZV_LCK_ATTR, attr); 493 } 494 495 /* 496 * Routine: hw_lock_init 497 * 498 * Initialize a hardware lock. 499 */ 500 MARK_AS_HIBERNATE_TEXT void 501 hw_lock_init(hw_lock_t lock) 502 { 503 ordered_store_hw(lock, 0); 504 } 505 506 static inline bool 507 hw_lock_trylock_contended(hw_lock_t lock, uintptr_t newval) 508 { 509 #if OS_ATOMIC_USE_LLSC 510 uintptr_t oldval; 511 os_atomic_rmw_loop(&lock->lock_data, oldval, newval, acquire, { 512 if (oldval != 0) { 513 wait_for_event(); // clears the monitor so we don't need give_up() 514 return false; 515 } 516 }); 517 return true; 518 #else // !OS_ATOMIC_USE_LLSC 519 #if OS_ATOMIC_HAS_LLSC 520 uintptr_t oldval = os_atomic_load_exclusive(&lock->lock_data, relaxed); 521 if (oldval != 0) { 522 wait_for_event(); // clears the monitor so we don't need give_up() 523 return false; 524 } 525 #endif // OS_ATOMIC_HAS_LLSC 526 return os_atomic_cmpxchg(&lock->lock_data, 0, newval, acquire); 527 #endif // !OS_ATOMIC_USE_LLSC 528 } 529 530 /* 531 * Routine: hw_lock_lock_contended 532 * 533 * Spin until lock is acquired or timeout expires. 534 * timeout is in mach_absolute_time ticks. Called with 535 * preemption disabled. 536 */ 537 static unsigned int NOINLINE 538 hw_lock_lock_contended(hw_lock_t lock, uintptr_t data, uint64_t timeout, boolean_t do_panic LCK_GRP_ARG(lck_grp_t *grp)) 539 { 540 uint64_t end = 0; 541 uintptr_t holder = lock->lock_data; 542 int i; 543 544 if (timeout == 0) { 545 timeout = LOCK_PANIC_TIMEOUT; 546 } 547 #if CONFIG_DTRACE || LOCK_STATS 548 uint64_t begin = 0; 549 boolean_t stat_enabled = lck_grp_spin_spin_enabled(lock LCK_GRP_ARG(grp)); 550 #endif /* CONFIG_DTRACE || LOCK_STATS */ 551 552 #if LOCK_STATS || CONFIG_DTRACE 553 if (__improbable(stat_enabled)) { 554 begin = mach_absolute_time(); 555 } 556 #endif /* LOCK_STATS || CONFIG_DTRACE */ 557 for (;;) { 558 for (i = 0; i < LOCK_SNOOP_SPINS; i++) { 559 cpu_pause(); 560 #if (!__ARM_ENABLE_WFE_) || (LOCK_PRETEST) 561 holder = ordered_load_hw(lock); 562 if (holder != 0) { 563 continue; 564 } 565 #endif 566 if (hw_lock_trylock_contended(lock, data)) { 567 #if CONFIG_DTRACE || LOCK_STATS 568 if (__improbable(stat_enabled)) { 569 lck_grp_spin_update_spin(lock LCK_GRP_ARG(grp), mach_absolute_time() - begin); 570 } 571 lck_grp_spin_update_miss(lock LCK_GRP_ARG(grp)); 572 #endif /* CONFIG_DTRACE || LOCK_STATS */ 573 return 1; 574 } 575 } 576 if (end == 0) { 577 end = ml_get_timebase() + timeout; 578 } else if (ml_get_timebase() >= end) { 579 break; 580 } 581 } 582 if (do_panic) { 583 // Capture the actual time spent blocked, which may be higher than the timeout 584 // if a misbehaving interrupt stole this thread's CPU time. 585 panic("Spinlock timeout after %llu ticks, %p = %lx", 586 (ml_get_timebase() - end + timeout), lock, holder); 587 } 588 return 0; 589 } 590 591 void * 592 hw_wait_while_equals(void **address, void *current) 593 { 594 void *v; 595 uint64_t end = 0; 596 597 for (;;) { 598 for (int i = 0; i < LOCK_SNOOP_SPINS; i++) { 599 cpu_pause(); 600 #if OS_ATOMIC_HAS_LLSC 601 v = os_atomic_load_exclusive(address, relaxed); 602 if (__probable(v != current)) { 603 os_atomic_clear_exclusive(); 604 return v; 605 } 606 wait_for_event(); 607 #else 608 v = os_atomic_load(address, relaxed); 609 if (__probable(v != current)) { 610 return v; 611 } 612 #endif // OS_ATOMIC_HAS_LLSC 613 } 614 if (end == 0) { 615 end = ml_get_timebase() + LOCK_PANIC_TIMEOUT; 616 } else if (ml_get_timebase() >= end) { 617 panic("Wait while equals timeout @ *%p == %p", address, v); 618 } 619 } 620 } 621 622 static inline void 623 hw_lock_lock_internal(hw_lock_t lock, thread_t thread LCK_GRP_ARG(lck_grp_t *grp)) 624 { 625 uintptr_t state; 626 627 state = LCK_MTX_THREAD_TO_STATE(thread) | PLATFORM_LCK_ILOCK; 628 #if LOCK_PRETEST 629 if (ordered_load_hw(lock)) { 630 goto contended; 631 } 632 #endif // LOCK_PRETEST 633 if (hw_lock_trylock_contended(lock, state)) { 634 goto end; 635 } 636 #if LOCK_PRETEST 637 contended: 638 #endif // LOCK_PRETEST 639 hw_lock_lock_contended(lock, state, 0, spinlock_timeout_panic LCK_GRP_ARG(grp)); 640 end: 641 lck_grp_spin_update_held(lock LCK_GRP_ARG(grp)); 642 643 return; 644 } 645 646 /* 647 * Routine: hw_lock_lock 648 * 649 * Acquire lock, spinning until it becomes available, 650 * return with preemption disabled. 651 */ 652 void 653 (hw_lock_lock)(hw_lock_t lock LCK_GRP_ARG(lck_grp_t *grp)) 654 { 655 thread_t thread = current_thread(); 656 disable_preemption_for_thread(thread); 657 hw_lock_lock_internal(lock, thread LCK_GRP_ARG(grp)); 658 } 659 660 /* 661 * Routine: hw_lock_lock_nopreempt 662 * 663 * Acquire lock, spinning until it becomes available. 664 */ 665 void 666 (hw_lock_lock_nopreempt)(hw_lock_t lock LCK_GRP_ARG(lck_grp_t *grp)) 667 { 668 thread_t thread = current_thread(); 669 if (__improbable(!preemption_disabled_for_thread(thread))) { 670 panic("Attempt to take no-preempt spinlock %p in preemptible context", lock); 671 } 672 hw_lock_lock_internal(lock, thread LCK_GRP_ARG(grp)); 673 } 674 675 static inline unsigned int 676 hw_lock_to_internal(hw_lock_t lock, uint64_t timeout, thread_t thread 677 LCK_GRP_ARG(lck_grp_t *grp)) 678 { 679 uintptr_t state; 680 unsigned int success = 0; 681 682 state = LCK_MTX_THREAD_TO_STATE(thread) | PLATFORM_LCK_ILOCK; 683 #if LOCK_PRETEST 684 if (ordered_load_hw(lock)) { 685 goto contended; 686 } 687 #endif // LOCK_PRETEST 688 if (hw_lock_trylock_contended(lock, state)) { 689 success = 1; 690 goto end; 691 } 692 #if LOCK_PRETEST 693 contended: 694 #endif // LOCK_PRETEST 695 success = hw_lock_lock_contended(lock, state, timeout, FALSE LCK_GRP_ARG(grp)); 696 end: 697 if (success) { 698 lck_grp_spin_update_held(lock LCK_GRP_ARG(grp)); 699 } 700 return success; 701 } 702 703 /* 704 * Routine: hw_lock_to 705 * 706 * Acquire lock, spinning until it becomes available or timeout. 707 * Timeout is in mach_absolute_time ticks, return with 708 * preemption disabled. 709 */ 710 unsigned 711 int 712 (hw_lock_to)(hw_lock_t lock, uint64_t timeout LCK_GRP_ARG(lck_grp_t *grp)) 713 { 714 thread_t thread = current_thread(); 715 disable_preemption_for_thread(thread); 716 return hw_lock_to_internal(lock, timeout, thread LCK_GRP_ARG(grp)); 717 } 718 719 /* 720 * Routine: hw_lock_to_nopreempt 721 * 722 * Acquire lock, spinning until it becomes available or timeout. 723 * Timeout is in mach_absolute_time ticks, called and return with 724 * preemption disabled. 725 */ 726 unsigned 727 int 728 (hw_lock_to_nopreempt)(hw_lock_t lock, uint64_t timeout LCK_GRP_ARG(lck_grp_t *grp)) 729 { 730 thread_t thread = current_thread(); 731 if (__improbable(!preemption_disabled_for_thread(thread))) { 732 panic("Attempt to test no-preempt spinlock %p in preemptible context", lock); 733 } 734 return hw_lock_to_internal(lock, timeout, thread LCK_GRP_ARG(grp)); 735 } 736 737 /* 738 * Routine: hw_lock_try 739 * 740 * returns with preemption disabled on success. 741 */ 742 static inline unsigned int 743 hw_lock_try_internal(hw_lock_t lock, thread_t thread LCK_GRP_ARG(lck_grp_t *grp)) 744 { 745 int success = 0; 746 747 #if LOCK_PRETEST 748 if (ordered_load_hw(lock)) { 749 goto failed; 750 } 751 #endif // LOCK_PRETEST 752 success = os_atomic_cmpxchg(&lock->lock_data, 0, 753 LCK_MTX_THREAD_TO_STATE(thread) | PLATFORM_LCK_ILOCK, acquire); 754 755 #if LOCK_PRETEST 756 failed: 757 #endif // LOCK_PRETEST 758 if (success) { 759 lck_grp_spin_update_held(lock LCK_GRP_ARG(grp)); 760 } 761 return success; 762 } 763 764 unsigned 765 int 766 (hw_lock_try)(hw_lock_t lock LCK_GRP_ARG(lck_grp_t *grp)) 767 { 768 thread_t thread = current_thread(); 769 disable_preemption_for_thread(thread); 770 unsigned int success = hw_lock_try_internal(lock, thread LCK_GRP_ARG(grp)); 771 if (!success) { 772 enable_preemption(); 773 } 774 return success; 775 } 776 777 unsigned 778 int 779 (hw_lock_try_nopreempt)(hw_lock_t lock LCK_GRP_ARG(lck_grp_t *grp)) 780 { 781 thread_t thread = current_thread(); 782 if (__improbable(!preemption_disabled_for_thread(thread))) { 783 panic("Attempt to test no-preempt spinlock %p in preemptible context", lock); 784 } 785 return hw_lock_try_internal(lock, thread LCK_GRP_ARG(grp)); 786 } 787 788 /* 789 * Routine: hw_lock_unlock 790 * 791 * Unconditionally release lock, release preemption level. 792 */ 793 static inline void 794 hw_lock_unlock_internal(hw_lock_t lock) 795 { 796 os_atomic_store(&lock->lock_data, 0, release); 797 #if __arm__ || __arm64__ 798 // ARM tests are only for open-source exclusion 799 set_event(); 800 #endif // __arm__ || __arm64__ 801 #if CONFIG_DTRACE 802 LOCKSTAT_RECORD(LS_LCK_SPIN_UNLOCK_RELEASE, lock, 0); 803 #endif /* CONFIG_DTRACE */ 804 } 805 806 void 807 (hw_lock_unlock)(hw_lock_t lock) 808 { 809 hw_lock_unlock_internal(lock); 810 enable_preemption(); 811 } 812 813 void 814 (hw_lock_unlock_nopreempt)(hw_lock_t lock) 815 { 816 if (__improbable(!preemption_disabled_for_thread(current_thread()))) { 817 panic("Attempt to release no-preempt spinlock %p in preemptible context", lock); 818 } 819 hw_lock_unlock_internal(lock); 820 } 821 822 /* 823 * Routine hw_lock_held, doesn't change preemption state. 824 * N.B. Racy, of course. 825 */ 826 unsigned int 827 hw_lock_held(hw_lock_t lock) 828 { 829 return ordered_load_hw(lock) != 0; 830 } 831 832 static unsigned int 833 hw_lock_bit_to_contended(hw_lock_bit_t *lock, uint32_t mask, uint32_t timeout LCK_GRP_ARG(lck_grp_t *grp)); 834 835 static inline unsigned int 836 hw_lock_bit_to_internal(hw_lock_bit_t *lock, unsigned int bit, uint32_t timeout LCK_GRP_ARG(lck_grp_t *grp)) 837 { 838 unsigned int success = 0; 839 uint32_t mask = (1 << bit); 840 841 if (__improbable(!hw_atomic_test_and_set32(lock, mask, mask, memory_order_acquire, FALSE))) { 842 success = hw_lock_bit_to_contended(lock, mask, timeout LCK_GRP_ARG(grp)); 843 } else { 844 success = 1; 845 } 846 847 if (success) { 848 lck_grp_spin_update_held(lock LCK_GRP_ARG(grp)); 849 } 850 851 return success; 852 } 853 854 unsigned 855 int 856 (hw_lock_bit_to)(hw_lock_bit_t * lock, unsigned int bit, uint32_t timeout LCK_GRP_ARG(lck_grp_t *grp)) 857 { 858 _disable_preemption(); 859 return hw_lock_bit_to_internal(lock, bit, timeout LCK_GRP_ARG(grp)); 860 } 861 862 static unsigned int NOINLINE 863 hw_lock_bit_to_contended(hw_lock_bit_t *lock, uint32_t mask, uint32_t timeout LCK_GRP_ARG(lck_grp_t *grp)) 864 { 865 uint64_t end = 0; 866 int i; 867 #if CONFIG_DTRACE || LOCK_STATS 868 uint64_t begin = 0; 869 boolean_t stat_enabled = lck_grp_spin_spin_enabled(lock LCK_GRP_ARG(grp)); 870 #endif /* CONFIG_DTRACE || LOCK_STATS */ 871 872 #if LOCK_STATS || CONFIG_DTRACE 873 if (__improbable(stat_enabled)) { 874 begin = mach_absolute_time(); 875 } 876 #endif /* LOCK_STATS || CONFIG_DTRACE */ 877 for (;;) { 878 for (i = 0; i < LOCK_SNOOP_SPINS; i++) { 879 // Always load-exclusive before wfe 880 // This grabs the monitor and wakes up on a release event 881 if (hw_atomic_test_and_set32(lock, mask, mask, memory_order_acquire, TRUE)) { 882 goto end; 883 } 884 } 885 if (end == 0) { 886 end = ml_get_timebase() + timeout; 887 } else if (ml_get_timebase() >= end) { 888 break; 889 } 890 } 891 return 0; 892 end: 893 #if CONFIG_DTRACE || LOCK_STATS 894 if (__improbable(stat_enabled)) { 895 lck_grp_spin_update_spin(lock LCK_GRP_ARG(grp), mach_absolute_time() - begin); 896 } 897 lck_grp_spin_update_miss(lock LCK_GRP_ARG(grp)); 898 #endif /* CONFIG_DTRACE || LCK_GRP_STAT */ 899 900 return 1; 901 } 902 903 void 904 (hw_lock_bit)(hw_lock_bit_t * lock, unsigned int bit LCK_GRP_ARG(lck_grp_t *grp)) 905 { 906 if (hw_lock_bit_to(lock, bit, LOCK_PANIC_TIMEOUT, LCK_GRP_PROBEARG(grp))) { 907 return; 908 } 909 panic("hw_lock_bit(): timed out (%p)", lock); 910 } 911 912 void 913 (hw_lock_bit_nopreempt)(hw_lock_bit_t * lock, unsigned int bit LCK_GRP_ARG(lck_grp_t *grp)) 914 { 915 if (__improbable(get_preemption_level() == 0)) { 916 panic("Attempt to take no-preempt bitlock %p in preemptible context", lock); 917 } 918 if (hw_lock_bit_to_internal(lock, bit, LOCK_PANIC_TIMEOUT LCK_GRP_ARG(grp))) { 919 return; 920 } 921 panic("hw_lock_bit_nopreempt(): timed out (%p)", lock); 922 } 923 924 unsigned 925 int 926 (hw_lock_bit_try)(hw_lock_bit_t * lock, unsigned int bit LCK_GRP_ARG(lck_grp_t *grp)) 927 { 928 uint32_t mask = (1 << bit); 929 boolean_t success = FALSE; 930 931 _disable_preemption(); 932 // TODO: consider weak (non-looping) atomic test-and-set 933 success = hw_atomic_test_and_set32(lock, mask, mask, memory_order_acquire, FALSE); 934 if (!success) { 935 _enable_preemption(); 936 } 937 938 if (success) { 939 lck_grp_spin_update_held(lock LCK_GRP_ARG(grp)); 940 } 941 942 return success; 943 } 944 945 static inline void 946 hw_unlock_bit_internal(hw_lock_bit_t *lock, unsigned int bit) 947 { 948 uint32_t mask = (1 << bit); 949 950 os_atomic_andnot(lock, mask, release); 951 #if __arm__ 952 set_event(); 953 #endif 954 #if CONFIG_DTRACE 955 LOCKSTAT_RECORD(LS_LCK_SPIN_UNLOCK_RELEASE, lock, bit); 956 #endif 957 } 958 959 /* 960 * Routine: hw_unlock_bit 961 * 962 * Release spin-lock. The second parameter is the bit number to test and set. 963 * Decrement the preemption level. 964 */ 965 void 966 hw_unlock_bit(hw_lock_bit_t * lock, unsigned int bit) 967 { 968 hw_unlock_bit_internal(lock, bit); 969 _enable_preemption(); 970 } 971 972 void 973 hw_unlock_bit_nopreempt(hw_lock_bit_t * lock, unsigned int bit) 974 { 975 if (__improbable(get_preemption_level() == 0)) { 976 panic("Attempt to release no-preempt bitlock %p in preemptible context", lock); 977 } 978 hw_unlock_bit_internal(lock, bit); 979 } 980 981 /* 982 * Routine: lck_spin_sleep 983 */ 984 wait_result_t 985 lck_spin_sleep_grp( 986 lck_spin_t *lck, 987 lck_sleep_action_t lck_sleep_action, 988 event_t event, 989 wait_interrupt_t interruptible, 990 lck_grp_t *grp) 991 { 992 wait_result_t res; 993 994 if ((lck_sleep_action & ~LCK_SLEEP_MASK) != 0) { 995 panic("Invalid lock sleep action %x\n", lck_sleep_action); 996 } 997 998 res = assert_wait(event, interruptible); 999 if (res == THREAD_WAITING) { 1000 lck_spin_unlock(lck); 1001 res = thread_block(THREAD_CONTINUE_NULL); 1002 if (!(lck_sleep_action & LCK_SLEEP_UNLOCK)) { 1003 lck_spin_lock_grp(lck, grp); 1004 } 1005 } else if (lck_sleep_action & LCK_SLEEP_UNLOCK) { 1006 lck_spin_unlock(lck); 1007 } 1008 1009 return res; 1010 } 1011 1012 wait_result_t 1013 lck_spin_sleep( 1014 lck_spin_t *lck, 1015 lck_sleep_action_t lck_sleep_action, 1016 event_t event, 1017 wait_interrupt_t interruptible) 1018 { 1019 return lck_spin_sleep_grp(lck, lck_sleep_action, event, interruptible, LCK_GRP_NULL); 1020 } 1021 1022 /* 1023 * Routine: lck_spin_sleep_deadline 1024 */ 1025 wait_result_t 1026 lck_spin_sleep_deadline( 1027 lck_spin_t *lck, 1028 lck_sleep_action_t lck_sleep_action, 1029 event_t event, 1030 wait_interrupt_t interruptible, 1031 uint64_t deadline) 1032 { 1033 wait_result_t res; 1034 1035 if ((lck_sleep_action & ~LCK_SLEEP_MASK) != 0) { 1036 panic("Invalid lock sleep action %x\n", lck_sleep_action); 1037 } 1038 1039 res = assert_wait_deadline(event, interruptible, deadline); 1040 if (res == THREAD_WAITING) { 1041 lck_spin_unlock(lck); 1042 res = thread_block(THREAD_CONTINUE_NULL); 1043 if (!(lck_sleep_action & LCK_SLEEP_UNLOCK)) { 1044 lck_spin_lock(lck); 1045 } 1046 } else if (lck_sleep_action & LCK_SLEEP_UNLOCK) { 1047 lck_spin_unlock(lck); 1048 } 1049 1050 return res; 1051 } 1052 1053 /* 1054 * Routine: lck_mtx_sleep 1055 */ 1056 wait_result_t 1057 lck_mtx_sleep( 1058 lck_mtx_t *lck, 1059 lck_sleep_action_t lck_sleep_action, 1060 event_t event, 1061 wait_interrupt_t interruptible) 1062 { 1063 wait_result_t res; 1064 thread_t thread = current_thread(); 1065 1066 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_MTX_SLEEP_CODE) | DBG_FUNC_START, 1067 VM_KERNEL_UNSLIDE_OR_PERM(lck), (int)lck_sleep_action, VM_KERNEL_UNSLIDE_OR_PERM(event), (int)interruptible, 0); 1068 1069 if ((lck_sleep_action & ~LCK_SLEEP_MASK) != 0) { 1070 panic("Invalid lock sleep action %x\n", lck_sleep_action); 1071 } 1072 1073 if (lck_sleep_action & LCK_SLEEP_PROMOTED_PRI) { 1074 /* 1075 * We overload the RW lock promotion to give us a priority ceiling 1076 * during the time that this thread is asleep, so that when it 1077 * is re-awakened (and not yet contending on the mutex), it is 1078 * runnable at a reasonably high priority. 1079 */ 1080 thread->rwlock_count++; 1081 } 1082 1083 res = assert_wait(event, interruptible); 1084 if (res == THREAD_WAITING) { 1085 lck_mtx_unlock(lck); 1086 res = thread_block(THREAD_CONTINUE_NULL); 1087 if (!(lck_sleep_action & LCK_SLEEP_UNLOCK)) { 1088 if ((lck_sleep_action & LCK_SLEEP_SPIN)) { 1089 lck_mtx_lock_spin(lck); 1090 } else if ((lck_sleep_action & LCK_SLEEP_SPIN_ALWAYS)) { 1091 lck_mtx_lock_spin_always(lck); 1092 } else { 1093 lck_mtx_lock(lck); 1094 } 1095 } 1096 } else if (lck_sleep_action & LCK_SLEEP_UNLOCK) { 1097 lck_mtx_unlock(lck); 1098 } 1099 1100 if (lck_sleep_action & LCK_SLEEP_PROMOTED_PRI) { 1101 if ((thread->rwlock_count-- == 1 /* field now 0 */) && (thread->sched_flags & TH_SFLAG_RW_PROMOTED)) { 1102 /* sched_flags checked without lock, but will be rechecked while clearing */ 1103 lck_rw_clear_promotion(thread, unslide_for_kdebug(event)); 1104 } 1105 } 1106 1107 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_MTX_SLEEP_CODE) | DBG_FUNC_END, (int)res, 0, 0, 0, 0); 1108 1109 return res; 1110 } 1111 1112 1113 /* 1114 * Routine: lck_mtx_sleep_deadline 1115 */ 1116 wait_result_t 1117 lck_mtx_sleep_deadline( 1118 lck_mtx_t *lck, 1119 lck_sleep_action_t lck_sleep_action, 1120 event_t event, 1121 wait_interrupt_t interruptible, 1122 uint64_t deadline) 1123 { 1124 wait_result_t res; 1125 thread_t thread = current_thread(); 1126 1127 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_MTX_SLEEP_DEADLINE_CODE) | DBG_FUNC_START, 1128 VM_KERNEL_UNSLIDE_OR_PERM(lck), (int)lck_sleep_action, VM_KERNEL_UNSLIDE_OR_PERM(event), (int)interruptible, 0); 1129 1130 if ((lck_sleep_action & ~LCK_SLEEP_MASK) != 0) { 1131 panic("Invalid lock sleep action %x\n", lck_sleep_action); 1132 } 1133 1134 if (lck_sleep_action & LCK_SLEEP_PROMOTED_PRI) { 1135 /* 1136 * See lck_mtx_sleep(). 1137 */ 1138 thread->rwlock_count++; 1139 } 1140 1141 res = assert_wait_deadline(event, interruptible, deadline); 1142 if (res == THREAD_WAITING) { 1143 lck_mtx_unlock(lck); 1144 res = thread_block(THREAD_CONTINUE_NULL); 1145 if (!(lck_sleep_action & LCK_SLEEP_UNLOCK)) { 1146 if ((lck_sleep_action & LCK_SLEEP_SPIN)) { 1147 lck_mtx_lock_spin(lck); 1148 } else { 1149 lck_mtx_lock(lck); 1150 } 1151 } 1152 } else if (lck_sleep_action & LCK_SLEEP_UNLOCK) { 1153 lck_mtx_unlock(lck); 1154 } 1155 1156 if (lck_sleep_action & LCK_SLEEP_PROMOTED_PRI) { 1157 if ((thread->rwlock_count-- == 1 /* field now 0 */) && (thread->sched_flags & TH_SFLAG_RW_PROMOTED)) { 1158 /* sched_flags checked without lock, but will be rechecked while clearing */ 1159 lck_rw_clear_promotion(thread, unslide_for_kdebug(event)); 1160 } 1161 } 1162 1163 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_MTX_SLEEP_DEADLINE_CODE) | DBG_FUNC_END, (int)res, 0, 0, 0, 0); 1164 1165 return res; 1166 } 1167 1168 /* 1169 * Lock Boosting Invariants: 1170 * 1171 * The lock owner is always promoted to the max priority of all its waiters. 1172 * Max priority is capped at MAXPRI_PROMOTE. 1173 * 1174 * The last waiter is not given a promotion when it wakes up or acquires the lock. 1175 * When the last waiter is waking up, a new contender can always come in and 1176 * steal the lock without having to wait for the last waiter to make forward progress. 1177 */ 1178 1179 /* 1180 * Routine: lck_mtx_lock_wait 1181 * 1182 * Invoked in order to wait on contention. 1183 * 1184 * Called with the interlock locked and 1185 * returns it unlocked. 1186 * 1187 * Always aggressively sets the owning thread to promoted, 1188 * even if it's the same or higher priority 1189 * This prevents it from lowering its own priority while holding a lock 1190 * 1191 * TODO: Come up with a more efficient way to handle same-priority promotions 1192 * <rdar://problem/30737670> ARM mutex contention logic could avoid taking the thread lock 1193 */ 1194 void 1195 lck_mtx_lock_wait( 1196 lck_mtx_t *lck, 1197 thread_t holder, 1198 struct turnstile **ts) 1199 { 1200 thread_t thread = current_thread(); 1201 lck_mtx_t *mutex; 1202 __kdebug_only uintptr_t trace_lck = unslide_for_kdebug(lck); 1203 1204 #if CONFIG_DTRACE 1205 uint64_t sleep_start = 0; 1206 1207 if (lockstat_probemap[LS_LCK_MTX_LOCK_BLOCK] || lockstat_probemap[LS_LCK_MTX_EXT_LOCK_BLOCK]) { 1208 sleep_start = mach_absolute_time(); 1209 } 1210 #endif 1211 1212 if (lck->lck_mtx_tag != LCK_MTX_TAG_INDIRECT) { 1213 mutex = lck; 1214 } else { 1215 mutex = &lck->lck_mtx_ptr->lck_mtx; 1216 } 1217 1218 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_MTX_LCK_WAIT_CODE) | DBG_FUNC_START, 1219 trace_lck, (uintptr_t)thread_tid(thread), 0, 0, 0); 1220 1221 assert(thread->waiting_for_mutex == NULL); 1222 thread->waiting_for_mutex = mutex; 1223 mutex->lck_mtx_waiters++; 1224 1225 if (*ts == NULL) { 1226 *ts = turnstile_prepare((uintptr_t)mutex, NULL, TURNSTILE_NULL, TURNSTILE_KERNEL_MUTEX); 1227 } 1228 1229 struct turnstile *turnstile = *ts; 1230 thread_set_pending_block_hint(thread, kThreadWaitKernelMutex); 1231 turnstile_update_inheritor(turnstile, holder, (TURNSTILE_DELAYED_UPDATE | TURNSTILE_INHERITOR_THREAD)); 1232 1233 waitq_assert_wait64(&turnstile->ts_waitq, CAST_EVENT64_T(LCK_MTX_EVENT(mutex)), THREAD_UNINT | THREAD_WAIT_NOREPORT_USER, TIMEOUT_WAIT_FOREVER); 1234 1235 lck_mtx_ilk_unlock(mutex); 1236 1237 turnstile_update_inheritor_complete(turnstile, TURNSTILE_INTERLOCK_NOT_HELD); 1238 1239 thread_block(THREAD_CONTINUE_NULL); 1240 1241 thread->waiting_for_mutex = NULL; 1242 1243 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_MTX_LCK_WAIT_CODE) | DBG_FUNC_END, 0, 0, 0, 0, 0); 1244 #if CONFIG_DTRACE 1245 /* 1246 * Record the DTrace lockstat probe for blocking, block time 1247 * measured from when we were entered. 1248 */ 1249 if (sleep_start) { 1250 if (lck->lck_mtx_tag != LCK_MTX_TAG_INDIRECT) { 1251 LOCKSTAT_RECORD(LS_LCK_MTX_LOCK_BLOCK, lck, 1252 mach_absolute_time() - sleep_start); 1253 } else { 1254 LOCKSTAT_RECORD(LS_LCK_MTX_EXT_LOCK_BLOCK, lck, 1255 mach_absolute_time() - sleep_start); 1256 } 1257 } 1258 #endif 1259 } 1260 1261 /* 1262 * Routine: lck_mtx_lock_acquire 1263 * 1264 * Invoked on acquiring the mutex when there is 1265 * contention. 1266 * 1267 * Returns the current number of waiters. 1268 * 1269 * Called with the interlock locked. 1270 */ 1271 int 1272 lck_mtx_lock_acquire( 1273 lck_mtx_t *lck, 1274 struct turnstile *ts) 1275 { 1276 thread_t thread = current_thread(); 1277 lck_mtx_t *mutex; 1278 1279 if (lck->lck_mtx_tag != LCK_MTX_TAG_INDIRECT) { 1280 mutex = lck; 1281 } else { 1282 mutex = &lck->lck_mtx_ptr->lck_mtx; 1283 } 1284 1285 assert(thread->waiting_for_mutex == NULL); 1286 1287 if (mutex->lck_mtx_waiters > 0) { 1288 if (ts == NULL) { 1289 ts = turnstile_prepare((uintptr_t)mutex, NULL, TURNSTILE_NULL, TURNSTILE_KERNEL_MUTEX); 1290 } 1291 1292 turnstile_update_inheritor(ts, thread, (TURNSTILE_IMMEDIATE_UPDATE | TURNSTILE_INHERITOR_THREAD)); 1293 turnstile_update_inheritor_complete(ts, TURNSTILE_INTERLOCK_HELD); 1294 } 1295 1296 if (ts != NULL) { 1297 turnstile_complete((uintptr_t)mutex, NULL, NULL, TURNSTILE_KERNEL_MUTEX); 1298 } 1299 1300 return mutex->lck_mtx_waiters; 1301 } 1302 1303 /* 1304 * Routine: lck_mtx_unlock_wakeup 1305 * 1306 * Invoked on unlock when there is contention. 1307 * 1308 * Called with the interlock locked. 1309 * 1310 * NOTE: callers should call turnstile_clenup after 1311 * dropping the interlock. 1312 */ 1313 boolean_t 1314 lck_mtx_unlock_wakeup( 1315 lck_mtx_t *lck, 1316 thread_t holder) 1317 { 1318 thread_t thread = current_thread(); 1319 lck_mtx_t *mutex; 1320 __kdebug_only uintptr_t trace_lck = unslide_for_kdebug(lck); 1321 struct turnstile *ts; 1322 kern_return_t did_wake; 1323 1324 if (lck->lck_mtx_tag != LCK_MTX_TAG_INDIRECT) { 1325 mutex = lck; 1326 } else { 1327 mutex = &lck->lck_mtx_ptr->lck_mtx; 1328 } 1329 1330 if (thread != holder) { 1331 panic("lck_mtx_unlock_wakeup: mutex %p holder %p\n", mutex, holder); 1332 } 1333 1334 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_MTX_UNLCK_WAKEUP_CODE) | DBG_FUNC_START, 1335 trace_lck, (uintptr_t)thread_tid(thread), 0, 0, 0); 1336 1337 assert(mutex->lck_mtx_waiters > 0); 1338 assert(thread->waiting_for_mutex == NULL); 1339 1340 ts = turnstile_prepare((uintptr_t)mutex, NULL, TURNSTILE_NULL, TURNSTILE_KERNEL_MUTEX); 1341 1342 if (mutex->lck_mtx_waiters > 1) { 1343 /* WAITQ_PROMOTE_ON_WAKE will call turnstile_update_inheritor on the wokenup thread */ 1344 did_wake = waitq_wakeup64_one(&ts->ts_waitq, CAST_EVENT64_T(LCK_MTX_EVENT(mutex)), THREAD_AWAKENED, WAITQ_PROMOTE_ON_WAKE); 1345 } else { 1346 did_wake = waitq_wakeup64_one(&ts->ts_waitq, CAST_EVENT64_T(LCK_MTX_EVENT(mutex)), THREAD_AWAKENED, WAITQ_ALL_PRIORITIES); 1347 turnstile_update_inheritor(ts, NULL, TURNSTILE_IMMEDIATE_UPDATE); 1348 } 1349 assert(did_wake == KERN_SUCCESS); 1350 1351 turnstile_update_inheritor_complete(ts, TURNSTILE_INTERLOCK_HELD); 1352 turnstile_complete((uintptr_t)mutex, NULL, NULL, TURNSTILE_KERNEL_MUTEX); 1353 1354 mutex->lck_mtx_waiters--; 1355 1356 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_MTX_UNLCK_WAKEUP_CODE) | DBG_FUNC_END, 0, 0, 0, 0, 0); 1357 1358 return mutex->lck_mtx_waiters > 0; 1359 } 1360 1361 /* 1362 * Routine: mutex_pause 1363 * 1364 * Called by former callers of simple_lock_pause(). 1365 */ 1366 #define MAX_COLLISION_COUNTS 32 1367 #define MAX_COLLISION 8 1368 1369 unsigned int max_collision_count[MAX_COLLISION_COUNTS]; 1370 1371 uint32_t collision_backoffs[MAX_COLLISION] = { 1372 10, 50, 100, 200, 400, 600, 800, 1000 1373 }; 1374 1375 1376 void 1377 mutex_pause(uint32_t collisions) 1378 { 1379 wait_result_t wait_result; 1380 uint32_t back_off; 1381 1382 if (collisions >= MAX_COLLISION_COUNTS) { 1383 collisions = MAX_COLLISION_COUNTS - 1; 1384 } 1385 max_collision_count[collisions]++; 1386 1387 if (collisions >= MAX_COLLISION) { 1388 collisions = MAX_COLLISION - 1; 1389 } 1390 back_off = collision_backoffs[collisions]; 1391 1392 wait_result = assert_wait_timeout((event_t)mutex_pause, THREAD_UNINT, back_off, NSEC_PER_USEC); 1393 assert(wait_result == THREAD_WAITING); 1394 1395 wait_result = thread_block(THREAD_CONTINUE_NULL); 1396 assert(wait_result == THREAD_TIMED_OUT); 1397 } 1398 1399 1400 unsigned int mutex_yield_wait = 0; 1401 unsigned int mutex_yield_no_wait = 0; 1402 1403 void 1404 lck_mtx_yield( 1405 lck_mtx_t *lck) 1406 { 1407 int waiters; 1408 1409 #if DEBUG 1410 lck_mtx_assert(lck, LCK_MTX_ASSERT_OWNED); 1411 #endif /* DEBUG */ 1412 1413 if (lck->lck_mtx_tag == LCK_MTX_TAG_INDIRECT) { 1414 waiters = lck->lck_mtx_ptr->lck_mtx.lck_mtx_waiters; 1415 } else { 1416 waiters = lck->lck_mtx_waiters; 1417 } 1418 1419 if (!waiters) { 1420 mutex_yield_no_wait++; 1421 } else { 1422 mutex_yield_wait++; 1423 lck_mtx_unlock(lck); 1424 mutex_pause(0); 1425 lck_mtx_lock(lck); 1426 } 1427 } 1428 1429 1430 /* 1431 * Routine: lck_rw_sleep 1432 */ 1433 wait_result_t 1434 lck_rw_sleep( 1435 lck_rw_t *lck, 1436 lck_sleep_action_t lck_sleep_action, 1437 event_t event, 1438 wait_interrupt_t interruptible) 1439 { 1440 wait_result_t res; 1441 lck_rw_type_t lck_rw_type; 1442 thread_t thread = current_thread(); 1443 1444 if ((lck_sleep_action & ~LCK_SLEEP_MASK) != 0) { 1445 panic("Invalid lock sleep action %x\n", lck_sleep_action); 1446 } 1447 1448 if (lck_sleep_action & LCK_SLEEP_PROMOTED_PRI) { 1449 /* 1450 * Although we are dropping the RW lock, the intent in most cases 1451 * is that this thread remains as an observer, since it may hold 1452 * some secondary resource, but must yield to avoid deadlock. In 1453 * this situation, make sure that the thread is boosted to the 1454 * RW lock ceiling while blocked, so that it can re-acquire the 1455 * RW lock at that priority. 1456 */ 1457 thread->rwlock_count++; 1458 } 1459 1460 res = assert_wait(event, interruptible); 1461 if (res == THREAD_WAITING) { 1462 lck_rw_type = lck_rw_done(lck); 1463 res = thread_block(THREAD_CONTINUE_NULL); 1464 if (!(lck_sleep_action & LCK_SLEEP_UNLOCK)) { 1465 if (!(lck_sleep_action & (LCK_SLEEP_SHARED | LCK_SLEEP_EXCLUSIVE))) { 1466 lck_rw_lock(lck, lck_rw_type); 1467 } else if (lck_sleep_action & LCK_SLEEP_EXCLUSIVE) { 1468 lck_rw_lock_exclusive(lck); 1469 } else { 1470 lck_rw_lock_shared(lck); 1471 } 1472 } 1473 } else if (lck_sleep_action & LCK_SLEEP_UNLOCK) { 1474 (void)lck_rw_done(lck); 1475 } 1476 1477 if (lck_sleep_action & LCK_SLEEP_PROMOTED_PRI) { 1478 if ((thread->rwlock_count-- == 1 /* field now 0 */) && (thread->sched_flags & TH_SFLAG_RW_PROMOTED)) { 1479 /* sched_flags checked without lock, but will be rechecked while clearing */ 1480 1481 /* Only if the caller wanted the lck_rw_t returned unlocked should we drop to 0 */ 1482 assert(lck_sleep_action & LCK_SLEEP_UNLOCK); 1483 1484 lck_rw_clear_promotion(thread, unslide_for_kdebug(event)); 1485 } 1486 } 1487 1488 return res; 1489 } 1490 1491 1492 /* 1493 * Routine: lck_rw_sleep_deadline 1494 */ 1495 wait_result_t 1496 lck_rw_sleep_deadline( 1497 lck_rw_t *lck, 1498 lck_sleep_action_t lck_sleep_action, 1499 event_t event, 1500 wait_interrupt_t interruptible, 1501 uint64_t deadline) 1502 { 1503 wait_result_t res; 1504 lck_rw_type_t lck_rw_type; 1505 thread_t thread = current_thread(); 1506 1507 if ((lck_sleep_action & ~LCK_SLEEP_MASK) != 0) { 1508 panic("Invalid lock sleep action %x\n", lck_sleep_action); 1509 } 1510 1511 if (lck_sleep_action & LCK_SLEEP_PROMOTED_PRI) { 1512 thread->rwlock_count++; 1513 } 1514 1515 res = assert_wait_deadline(event, interruptible, deadline); 1516 if (res == THREAD_WAITING) { 1517 lck_rw_type = lck_rw_done(lck); 1518 res = thread_block(THREAD_CONTINUE_NULL); 1519 if (!(lck_sleep_action & LCK_SLEEP_UNLOCK)) { 1520 if (!(lck_sleep_action & (LCK_SLEEP_SHARED | LCK_SLEEP_EXCLUSIVE))) { 1521 lck_rw_lock(lck, lck_rw_type); 1522 } else if (lck_sleep_action & LCK_SLEEP_EXCLUSIVE) { 1523 lck_rw_lock_exclusive(lck); 1524 } else { 1525 lck_rw_lock_shared(lck); 1526 } 1527 } 1528 } else if (lck_sleep_action & LCK_SLEEP_UNLOCK) { 1529 (void)lck_rw_done(lck); 1530 } 1531 1532 if (lck_sleep_action & LCK_SLEEP_PROMOTED_PRI) { 1533 if ((thread->rwlock_count-- == 1 /* field now 0 */) && (thread->sched_flags & TH_SFLAG_RW_PROMOTED)) { 1534 /* sched_flags checked without lock, but will be rechecked while clearing */ 1535 1536 /* Only if the caller wanted the lck_rw_t returned unlocked should we drop to 0 */ 1537 assert(lck_sleep_action & LCK_SLEEP_UNLOCK); 1538 1539 lck_rw_clear_promotion(thread, unslide_for_kdebug(event)); 1540 } 1541 } 1542 1543 return res; 1544 } 1545 1546 /* 1547 * Reader-writer lock promotion 1548 * 1549 * We support a limited form of reader-writer 1550 * lock promotion whose effects are: 1551 * 1552 * * Qualifying threads have decay disabled 1553 * * Scheduler priority is reset to a floor of 1554 * of their statically assigned priority 1555 * or MINPRI_RWLOCK 1556 * 1557 * The rationale is that lck_rw_ts do not have 1558 * a single owner, so we cannot apply a directed 1559 * priority boost from all waiting threads 1560 * to all holding threads without maintaining 1561 * lists of all shared owners and all waiting 1562 * threads for every lock. 1563 * 1564 * Instead (and to preserve the uncontended fast- 1565 * path), acquiring (or attempting to acquire) 1566 * a RW lock in shared or exclusive lock increments 1567 * a per-thread counter. Only if that thread stops 1568 * making forward progress (for instance blocking 1569 * on a mutex, or being preempted) do we consult 1570 * the counter and apply the priority floor. 1571 * When the thread becomes runnable again (or in 1572 * the case of preemption it never stopped being 1573 * runnable), it has the priority boost and should 1574 * be in a good position to run on the CPU and 1575 * release all RW locks (at which point the priority 1576 * boost is cleared). 1577 * 1578 * Care must be taken to ensure that priority 1579 * boosts are not retained indefinitely, since unlike 1580 * mutex priority boosts (where the boost is tied 1581 * to the mutex lifecycle), the boost is tied 1582 * to the thread and independent of any particular 1583 * lck_rw_t. Assertions are in place on return 1584 * to userspace so that the boost is not held 1585 * indefinitely. 1586 * 1587 * The routines that increment/decrement the 1588 * per-thread counter should err on the side of 1589 * incrementing any time a preemption is possible 1590 * and the lock would be visible to the rest of the 1591 * system as held (so it should be incremented before 1592 * interlocks are dropped/preemption is enabled, or 1593 * before a CAS is executed to acquire the lock). 1594 * 1595 */ 1596 1597 /* 1598 * lck_rw_clear_promotion: Undo priority promotions when the last RW 1599 * lock is released by a thread (if a promotion was active) 1600 */ 1601 void 1602 lck_rw_clear_promotion(thread_t thread, uintptr_t trace_obj) 1603 { 1604 assert(thread->rwlock_count == 0); 1605 1606 /* Cancel any promotions if the thread had actually blocked while holding a RW lock */ 1607 spl_t s = splsched(); 1608 thread_lock(thread); 1609 1610 if (thread->sched_flags & TH_SFLAG_RW_PROMOTED) { 1611 sched_thread_unpromote_reason(thread, TH_SFLAG_RW_PROMOTED, trace_obj); 1612 } 1613 1614 thread_unlock(thread); 1615 splx(s); 1616 } 1617 1618 /* 1619 * Callout from context switch if the thread goes 1620 * off core with a positive rwlock_count 1621 * 1622 * Called at splsched with the thread locked 1623 */ 1624 void 1625 lck_rw_set_promotion_locked(thread_t thread) 1626 { 1627 if (LcksOpts & disLkRWPrio) { 1628 return; 1629 } 1630 1631 assert(thread->rwlock_count > 0); 1632 1633 if (!(thread->sched_flags & TH_SFLAG_RW_PROMOTED)) { 1634 sched_thread_promote_reason(thread, TH_SFLAG_RW_PROMOTED, 0); 1635 } 1636 } 1637 1638 kern_return_t 1639 host_lockgroup_info( 1640 host_t host, 1641 lockgroup_info_array_t *lockgroup_infop, 1642 mach_msg_type_number_t *lockgroup_infoCntp) 1643 { 1644 lockgroup_info_t *lockgroup_info_base; 1645 lockgroup_info_t *lockgroup_info; 1646 vm_offset_t lockgroup_info_addr; 1647 vm_size_t lockgroup_info_size; 1648 vm_size_t lockgroup_info_vmsize; 1649 lck_grp_t *lck_grp; 1650 unsigned int i; 1651 vm_map_copy_t copy; 1652 kern_return_t kr; 1653 1654 if (host == HOST_NULL) { 1655 return KERN_INVALID_HOST; 1656 } 1657 1658 lck_mtx_lock(&lck_grp_lock); 1659 1660 lockgroup_info_size = lck_grp_cnt * sizeof(*lockgroup_info); 1661 lockgroup_info_vmsize = round_page(lockgroup_info_size); 1662 kr = kmem_alloc_pageable(ipc_kernel_map, 1663 &lockgroup_info_addr, lockgroup_info_vmsize, VM_KERN_MEMORY_IPC); 1664 if (kr != KERN_SUCCESS) { 1665 lck_mtx_unlock(&lck_grp_lock); 1666 return kr; 1667 } 1668 1669 lockgroup_info_base = (lockgroup_info_t *) lockgroup_info_addr; 1670 lck_grp = (lck_grp_t *)queue_first(&lck_grp_queue); 1671 lockgroup_info = lockgroup_info_base; 1672 1673 for (i = 0; i < lck_grp_cnt; i++) { 1674 lockgroup_info->lock_spin_cnt = lck_grp->lck_grp_spincnt; 1675 lockgroup_info->lock_rw_cnt = lck_grp->lck_grp_rwcnt; 1676 lockgroup_info->lock_mtx_cnt = lck_grp->lck_grp_mtxcnt; 1677 1678 #if LOCK_STATS 1679 lockgroup_info->lock_spin_held_cnt = lck_grp->lck_grp_stats.lgss_spin_held.lgs_count; 1680 lockgroup_info->lock_spin_miss_cnt = lck_grp->lck_grp_stats.lgss_spin_miss.lgs_count; 1681 #endif /* LOCK_STATS */ 1682 1683 // Historically on x86, held was used for "direct wait" and util for "held" 1684 lockgroup_info->lock_mtx_util_cnt = lck_grp->lck_grp_stats.lgss_mtx_held.lgs_count; 1685 lockgroup_info->lock_mtx_held_cnt = lck_grp->lck_grp_stats.lgss_mtx_direct_wait.lgs_count; 1686 lockgroup_info->lock_mtx_miss_cnt = lck_grp->lck_grp_stats.lgss_mtx_miss.lgs_count; 1687 lockgroup_info->lock_mtx_wait_cnt = lck_grp->lck_grp_stats.lgss_mtx_wait.lgs_count; 1688 1689 (void) strncpy(lockgroup_info->lockgroup_name, lck_grp->lck_grp_name, LOCKGROUP_MAX_NAME); 1690 1691 lck_grp = (lck_grp_t *)(queue_next((queue_entry_t)(lck_grp))); 1692 lockgroup_info++; 1693 } 1694 1695 *lockgroup_infoCntp = lck_grp_cnt; 1696 lck_mtx_unlock(&lck_grp_lock); 1697 1698 if (lockgroup_info_size != lockgroup_info_vmsize) { 1699 bzero((char *)lockgroup_info, lockgroup_info_vmsize - lockgroup_info_size); 1700 } 1701 1702 kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)lockgroup_info_addr, 1703 (vm_map_size_t)lockgroup_info_size, TRUE, ©); 1704 assert(kr == KERN_SUCCESS); 1705 1706 *lockgroup_infop = (lockgroup_info_t *) copy; 1707 1708 return KERN_SUCCESS; 1709 } 1710 1711 /* 1712 * sleep_with_inheritor and wakeup_with_inheritor KPI 1713 * 1714 * Functions that allow to sleep on an event and use turnstile to propagate the priority of the sleeping threads to 1715 * the latest thread specified as inheritor. 1716 * 1717 * The inheritor management is delegated to the caller, the caller needs to store a thread identifier to provide to this functions to specified upon whom 1718 * direct the push. The inheritor cannot run in user space while holding a push from an event. Therefore is the caller responsibility to call a 1719 * wakeup_with_inheritor from inheritor before running in userspace or specify another inheritor before letting the old inheritor run in userspace. 1720 * 1721 * sleep_with_inheritor requires to hold a locking primitive while invoked, but wakeup_with_inheritor and change_sleep_inheritor don't require it. 1722 * 1723 * Turnstile requires a non blocking primitive as interlock to synchronize the turnstile data structure manipulation, threfore sleep_with_inheritor, change_sleep_inheritor and 1724 * wakeup_with_inheritor will require the same interlock to manipulate turnstiles. 1725 * If sleep_with_inheritor is associated with a locking primitive that can block (like lck_mtx_t or lck_rw_t), an handoff to a non blocking primitive is required before 1726 * invoking any turnstile operation. 1727 * 1728 * All functions will save the turnstile associated with the event on the turnstile kernel hash table and will use the the turnstile kernel hash table bucket 1729 * spinlock as the turnstile interlock. Because we do not want to hold interrupt disabled while holding the bucket interlock a new turnstile kernel hash table 1730 * is instantiated for this KPI to manage the hash without interrupt disabled. 1731 * Also: 1732 * - all events on the system that hash on the same bucket will contend on the same spinlock. 1733 * - every event will have a dedicated wait_queue. 1734 * 1735 * Different locking primitives can be associated with sleep_with_inheritor as long as the primitive_lock() and primitive_unlock() functions are provided to 1736 * sleep_with_inheritor_turnstile to perform the handoff with the bucket spinlock. 1737 */ 1738 1739 kern_return_t 1740 wakeup_with_inheritor_and_turnstile_type(event_t event, turnstile_type_t type, wait_result_t result, bool wake_one, lck_wake_action_t action, thread_t *thread_wokenup) 1741 { 1742 uint32_t index; 1743 struct turnstile *ts = NULL; 1744 kern_return_t ret = KERN_NOT_WAITING; 1745 int priority; 1746 thread_t wokeup; 1747 1748 /* 1749 * the hash bucket spinlock is used as turnstile interlock 1750 */ 1751 turnstile_hash_bucket_lock((uintptr_t)event, &index, type); 1752 1753 ts = turnstile_prepare((uintptr_t)event, NULL, TURNSTILE_NULL, type); 1754 1755 if (wake_one) { 1756 if (action == LCK_WAKE_DEFAULT) { 1757 priority = WAITQ_PROMOTE_ON_WAKE; 1758 } else { 1759 assert(action == LCK_WAKE_DO_NOT_TRANSFER_PUSH); 1760 priority = WAITQ_ALL_PRIORITIES; 1761 } 1762 1763 /* 1764 * WAITQ_PROMOTE_ON_WAKE will call turnstile_update_inheritor 1765 * if it finds a thread 1766 */ 1767 wokeup = waitq_wakeup64_identify(&ts->ts_waitq, CAST_EVENT64_T(event), result, priority); 1768 if (wokeup != NULL) { 1769 if (thread_wokenup != NULL) { 1770 *thread_wokenup = wokeup; 1771 } else { 1772 thread_deallocate_safe(wokeup); 1773 } 1774 ret = KERN_SUCCESS; 1775 if (action == LCK_WAKE_DO_NOT_TRANSFER_PUSH) { 1776 goto complete; 1777 } 1778 } else { 1779 if (thread_wokenup != NULL) { 1780 *thread_wokenup = NULL; 1781 } 1782 turnstile_update_inheritor(ts, TURNSTILE_INHERITOR_NULL, TURNSTILE_IMMEDIATE_UPDATE); 1783 ret = KERN_NOT_WAITING; 1784 } 1785 } else { 1786 ret = waitq_wakeup64_all(&ts->ts_waitq, CAST_EVENT64_T(event), result, WAITQ_ALL_PRIORITIES); 1787 turnstile_update_inheritor(ts, TURNSTILE_INHERITOR_NULL, TURNSTILE_IMMEDIATE_UPDATE); 1788 } 1789 1790 /* 1791 * turnstile_update_inheritor_complete could be called while holding the interlock. 1792 * In this case the new inheritor or is null, or is a thread that is just been woken up 1793 * and have not blocked because it is racing with the same interlock used here 1794 * after the wait. 1795 * So there is no chain to update for the new inheritor. 1796 * 1797 * However unless the current thread is the old inheritor, 1798 * old inheritor can be blocked and requires a chain update. 1799 * 1800 * The chain should be short because kernel turnstiles cannot have user turnstiles 1801 * chained after them. 1802 * 1803 * We can anyway optimize this by asking turnstile to tell us 1804 * if old inheritor needs an update and drop the lock 1805 * just in that case. 1806 */ 1807 turnstile_hash_bucket_unlock((uintptr_t)NULL, &index, type, 0); 1808 1809 turnstile_update_inheritor_complete(ts, TURNSTILE_INTERLOCK_NOT_HELD); 1810 1811 turnstile_hash_bucket_lock((uintptr_t)NULL, &index, type); 1812 1813 complete: 1814 turnstile_complete((uintptr_t)event, NULL, NULL, type); 1815 1816 turnstile_hash_bucket_unlock((uintptr_t)NULL, &index, type, 0); 1817 1818 turnstile_cleanup(); 1819 1820 return ret; 1821 } 1822 1823 static wait_result_t 1824 sleep_with_inheritor_and_turnstile_type(event_t event, 1825 thread_t inheritor, 1826 wait_interrupt_t interruptible, 1827 uint64_t deadline, 1828 turnstile_type_t type, 1829 void (^primitive_lock)(void), 1830 void (^primitive_unlock)(void)) 1831 { 1832 wait_result_t ret; 1833 uint32_t index; 1834 struct turnstile *ts = NULL; 1835 1836 /* 1837 * the hash bucket spinlock is used as turnstile interlock, 1838 * lock it before releasing the primitive lock 1839 */ 1840 turnstile_hash_bucket_lock((uintptr_t)event, &index, type); 1841 1842 primitive_unlock(); 1843 1844 ts = turnstile_prepare((uintptr_t)event, NULL, TURNSTILE_NULL, type); 1845 1846 thread_set_pending_block_hint(current_thread(), kThreadWaitSleepWithInheritor); 1847 /* 1848 * We need TURNSTILE_DELAYED_UPDATE because we will call 1849 * waitq_assert_wait64 after. 1850 */ 1851 turnstile_update_inheritor(ts, inheritor, (TURNSTILE_DELAYED_UPDATE | TURNSTILE_INHERITOR_THREAD)); 1852 1853 ret = waitq_assert_wait64(&ts->ts_waitq, CAST_EVENT64_T(event), interruptible, deadline); 1854 1855 turnstile_hash_bucket_unlock((uintptr_t)NULL, &index, type, 0); 1856 1857 /* 1858 * Update new and old inheritor chains outside the interlock; 1859 */ 1860 turnstile_update_inheritor_complete(ts, TURNSTILE_INTERLOCK_NOT_HELD); 1861 1862 if (ret == THREAD_WAITING) { 1863 ret = thread_block(THREAD_CONTINUE_NULL); 1864 } 1865 1866 turnstile_hash_bucket_lock((uintptr_t)NULL, &index, type); 1867 1868 turnstile_complete((uintptr_t)event, NULL, NULL, type); 1869 1870 turnstile_hash_bucket_unlock((uintptr_t)NULL, &index, type, 0); 1871 1872 turnstile_cleanup(); 1873 1874 primitive_lock(); 1875 1876 return ret; 1877 } 1878 1879 kern_return_t 1880 change_sleep_inheritor_and_turnstile_type(event_t event, 1881 thread_t inheritor, 1882 turnstile_type_t type) 1883 { 1884 uint32_t index; 1885 struct turnstile *ts = NULL; 1886 kern_return_t ret = KERN_SUCCESS; 1887 /* 1888 * the hash bucket spinlock is used as turnstile interlock 1889 */ 1890 turnstile_hash_bucket_lock((uintptr_t)event, &index, type); 1891 1892 ts = turnstile_prepare((uintptr_t)event, NULL, TURNSTILE_NULL, type); 1893 1894 if (!turnstile_has_waiters(ts)) { 1895 ret = KERN_NOT_WAITING; 1896 } 1897 1898 /* 1899 * We will not call an assert_wait later so use TURNSTILE_IMMEDIATE_UPDATE 1900 */ 1901 turnstile_update_inheritor(ts, inheritor, (TURNSTILE_IMMEDIATE_UPDATE | TURNSTILE_INHERITOR_THREAD)); 1902 1903 turnstile_hash_bucket_unlock((uintptr_t)NULL, &index, type, 0); 1904 1905 /* 1906 * update the chains outside the interlock 1907 */ 1908 turnstile_update_inheritor_complete(ts, TURNSTILE_INTERLOCK_NOT_HELD); 1909 1910 turnstile_hash_bucket_lock((uintptr_t)NULL, &index, type); 1911 1912 turnstile_complete((uintptr_t)event, NULL, NULL, type); 1913 1914 turnstile_hash_bucket_unlock((uintptr_t)NULL, &index, type, 0); 1915 1916 turnstile_cleanup(); 1917 1918 return ret; 1919 } 1920 1921 typedef void (^void_block_void)(void); 1922 1923 /* 1924 * sleep_with_inheritor functions with lck_mtx_t as locking primitive. 1925 */ 1926 1927 wait_result_t 1928 lck_mtx_sleep_with_inheritor_and_turnstile_type(lck_mtx_t *lock, lck_sleep_action_t lck_sleep_action, event_t event, thread_t inheritor, wait_interrupt_t interruptible, uint64_t deadline, turnstile_type_t type) 1929 { 1930 LCK_MTX_ASSERT(lock, LCK_MTX_ASSERT_OWNED); 1931 1932 if (lck_sleep_action & LCK_SLEEP_UNLOCK) { 1933 return sleep_with_inheritor_and_turnstile_type(event, 1934 inheritor, 1935 interruptible, 1936 deadline, 1937 type, 1938 ^{;}, 1939 ^{lck_mtx_unlock(lock);}); 1940 } else if (lck_sleep_action & LCK_SLEEP_SPIN) { 1941 return sleep_with_inheritor_and_turnstile_type(event, 1942 inheritor, 1943 interruptible, 1944 deadline, 1945 type, 1946 ^{lck_mtx_lock_spin(lock);}, 1947 ^{lck_mtx_unlock(lock);}); 1948 } else if (lck_sleep_action & LCK_SLEEP_SPIN_ALWAYS) { 1949 return sleep_with_inheritor_and_turnstile_type(event, 1950 inheritor, 1951 interruptible, 1952 deadline, 1953 type, 1954 ^{lck_mtx_lock_spin_always(lock);}, 1955 ^{lck_mtx_unlock(lock);}); 1956 } else { 1957 return sleep_with_inheritor_and_turnstile_type(event, 1958 inheritor, 1959 interruptible, 1960 deadline, 1961 type, 1962 ^{lck_mtx_lock(lock);}, 1963 ^{lck_mtx_unlock(lock);}); 1964 } 1965 } 1966 1967 /* 1968 * Name: lck_spin_sleep_with_inheritor 1969 * 1970 * Description: deschedule the current thread and wait on the waitq associated with event to be woken up. 1971 * While waiting, the sched priority of the waiting thread will contribute to the push of the event that will 1972 * be directed to the inheritor specified. 1973 * An interruptible mode and deadline can be specified to return earlier from the wait. 1974 * 1975 * Args: 1976 * Arg1: lck_spin_t lock used to protect the sleep. The lock will be dropped while sleeping and reaquired before returning according to the sleep action specified. 1977 * Arg2: sleep action. LCK_SLEEP_DEFAULT, LCK_SLEEP_UNLOCK. 1978 * Arg3: event to wait on. 1979 * Arg4: thread to propagate the event push to. 1980 * Arg5: interruptible flag for wait. 1981 * Arg6: deadline for wait. 1982 * 1983 * Conditions: Lock must be held. Returns with the lock held according to the sleep action specified. 1984 * Lock will be dropped while waiting. 1985 * The inheritor specified cannot run in user space until another inheritor is specified for the event or a 1986 * wakeup for the event is called. 1987 * 1988 * Returns: result of the wait. 1989 */ 1990 wait_result_t 1991 lck_spin_sleep_with_inheritor( 1992 lck_spin_t *lock, 1993 lck_sleep_action_t lck_sleep_action, 1994 event_t event, 1995 thread_t inheritor, 1996 wait_interrupt_t interruptible, 1997 uint64_t deadline) 1998 { 1999 if (lck_sleep_action & LCK_SLEEP_UNLOCK) { 2000 return sleep_with_inheritor_and_turnstile_type(event, inheritor, 2001 interruptible, deadline, TURNSTILE_SLEEP_INHERITOR, 2002 ^{}, ^{ lck_spin_unlock(lock); }); 2003 } else { 2004 return sleep_with_inheritor_and_turnstile_type(event, inheritor, 2005 interruptible, deadline, TURNSTILE_SLEEP_INHERITOR, 2006 ^{ lck_spin_lock(lock); }, ^{ lck_spin_unlock(lock); }); 2007 } 2008 } 2009 2010 /* 2011 * Name: lck_mtx_sleep_with_inheritor 2012 * 2013 * Description: deschedule the current thread and wait on the waitq associated with event to be woken up. 2014 * While waiting, the sched priority of the waiting thread will contribute to the push of the event that will 2015 * be directed to the inheritor specified. 2016 * An interruptible mode and deadline can be specified to return earlier from the wait. 2017 * 2018 * Args: 2019 * Arg1: lck_mtx_t lock used to protect the sleep. The lock will be dropped while sleeping and reaquired before returning according to the sleep action specified. 2020 * Arg2: sleep action. LCK_SLEEP_DEFAULT, LCK_SLEEP_UNLOCK, LCK_SLEEP_SPIN, LCK_SLEEP_SPIN_ALWAYS. 2021 * Arg3: event to wait on. 2022 * Arg4: thread to propagate the event push to. 2023 * Arg5: interruptible flag for wait. 2024 * Arg6: deadline for wait. 2025 * 2026 * Conditions: Lock must be held. Returns with the lock held according to the sleep action specified. 2027 * Lock will be dropped while waiting. 2028 * The inheritor specified cannot run in user space until another inheritor is specified for the event or a 2029 * wakeup for the event is called. 2030 * 2031 * Returns: result of the wait. 2032 */ 2033 wait_result_t 2034 lck_mtx_sleep_with_inheritor(lck_mtx_t *lock, lck_sleep_action_t lck_sleep_action, event_t event, thread_t inheritor, wait_interrupt_t interruptible, uint64_t deadline) 2035 { 2036 return lck_mtx_sleep_with_inheritor_and_turnstile_type(lock, lck_sleep_action, event, inheritor, interruptible, deadline, TURNSTILE_SLEEP_INHERITOR); 2037 } 2038 2039 /* 2040 * sleep_with_inheritor functions with lck_rw_t as locking primitive. 2041 */ 2042 2043 wait_result_t 2044 lck_rw_sleep_with_inheritor_and_turnstile_type(lck_rw_t *lock, lck_sleep_action_t lck_sleep_action, event_t event, thread_t inheritor, wait_interrupt_t interruptible, uint64_t deadline, turnstile_type_t type) 2045 { 2046 __block lck_rw_type_t lck_rw_type = LCK_RW_TYPE_EXCLUSIVE; 2047 2048 LCK_RW_ASSERT(lock, LCK_RW_ASSERT_HELD); 2049 2050 if (lck_sleep_action & LCK_SLEEP_UNLOCK) { 2051 return sleep_with_inheritor_and_turnstile_type(event, 2052 inheritor, 2053 interruptible, 2054 deadline, 2055 type, 2056 ^{;}, 2057 ^{lck_rw_type = lck_rw_done(lock);}); 2058 } else if (!(lck_sleep_action & (LCK_SLEEP_SHARED | LCK_SLEEP_EXCLUSIVE))) { 2059 return sleep_with_inheritor_and_turnstile_type(event, 2060 inheritor, 2061 interruptible, 2062 deadline, 2063 type, 2064 ^{lck_rw_lock(lock, lck_rw_type);}, 2065 ^{lck_rw_type = lck_rw_done(lock);}); 2066 } else if (lck_sleep_action & LCK_SLEEP_EXCLUSIVE) { 2067 return sleep_with_inheritor_and_turnstile_type(event, 2068 inheritor, 2069 interruptible, 2070 deadline, 2071 type, 2072 ^{lck_rw_lock_exclusive(lock);}, 2073 ^{lck_rw_type = lck_rw_done(lock);}); 2074 } else { 2075 return sleep_with_inheritor_and_turnstile_type(event, 2076 inheritor, 2077 interruptible, 2078 deadline, 2079 type, 2080 ^{lck_rw_lock_shared(lock);}, 2081 ^{lck_rw_type = lck_rw_done(lock);}); 2082 } 2083 } 2084 2085 /* 2086 * Name: lck_rw_sleep_with_inheritor 2087 * 2088 * Description: deschedule the current thread and wait on the waitq associated with event to be woken up. 2089 * While waiting, the sched priority of the waiting thread will contribute to the push of the event that will 2090 * be directed to the inheritor specified. 2091 * An interruptible mode and deadline can be specified to return earlier from the wait. 2092 * 2093 * Args: 2094 * Arg1: lck_rw_t lock used to protect the sleep. The lock will be dropped while sleeping and reaquired before returning according to the sleep action specified. 2095 * Arg2: sleep action. LCK_SLEEP_DEFAULT, LCK_SLEEP_SHARED, LCK_SLEEP_EXCLUSIVE. 2096 * Arg3: event to wait on. 2097 * Arg4: thread to propagate the event push to. 2098 * Arg5: interruptible flag for wait. 2099 * Arg6: deadline for wait. 2100 * 2101 * Conditions: Lock must be held. Returns with the lock held according to the sleep action specified. 2102 * Lock will be dropped while waiting. 2103 * The inheritor specified cannot run in user space until another inheritor is specified for the event or a 2104 * wakeup for the event is called. 2105 * 2106 * Returns: result of the wait. 2107 */ 2108 wait_result_t 2109 lck_rw_sleep_with_inheritor(lck_rw_t *lock, lck_sleep_action_t lck_sleep_action, event_t event, thread_t inheritor, wait_interrupt_t interruptible, uint64_t deadline) 2110 { 2111 return lck_rw_sleep_with_inheritor_and_turnstile_type(lock, lck_sleep_action, event, inheritor, interruptible, deadline, TURNSTILE_SLEEP_INHERITOR); 2112 } 2113 2114 /* 2115 * wakeup_with_inheritor functions are independent from the locking primitive. 2116 */ 2117 2118 /* 2119 * Name: wakeup_one_with_inheritor 2120 * 2121 * Description: wake up one waiter for event if any. The thread woken up will be the one with the higher sched priority waiting on event. 2122 * The push for the event will be transferred from the last inheritor to the woken up thread if LCK_WAKE_DEFAULT is specified. 2123 * If LCK_WAKE_DO_NOT_TRANSFER_PUSH is specified the push will not be transferred. 2124 * 2125 * Args: 2126 * Arg1: event to wake from. 2127 * Arg2: wait result to pass to the woken up thread. 2128 * Arg3: wake flag. LCK_WAKE_DEFAULT or LCK_WAKE_DO_NOT_TRANSFER_PUSH. 2129 * Arg4: pointer for storing the thread wokenup. 2130 * 2131 * Returns: KERN_NOT_WAITING if no threads were waiting, KERN_SUCCESS otherwise. 2132 * 2133 * Conditions: The new inheritor wokenup cannot run in user space until another inheritor is specified for the event or a 2134 * wakeup for the event is called. 2135 * A reference for the wokenup thread is acquired. 2136 * NOTE: this cannot be called from interrupt context. 2137 */ 2138 kern_return_t 2139 wakeup_one_with_inheritor(event_t event, wait_result_t result, lck_wake_action_t action, thread_t *thread_wokenup) 2140 { 2141 return wakeup_with_inheritor_and_turnstile_type(event, 2142 TURNSTILE_SLEEP_INHERITOR, 2143 result, 2144 TRUE, 2145 action, 2146 thread_wokenup); 2147 } 2148 2149 /* 2150 * Name: wakeup_all_with_inheritor 2151 * 2152 * Description: wake up all waiters waiting for event. The old inheritor will lose the push. 2153 * 2154 * Args: 2155 * Arg1: event to wake from. 2156 * Arg2: wait result to pass to the woken up threads. 2157 * 2158 * Returns: KERN_NOT_WAITING if no threads were waiting, KERN_SUCCESS otherwise. 2159 * 2160 * Conditions: NOTE: this cannot be called from interrupt context. 2161 */ 2162 kern_return_t 2163 wakeup_all_with_inheritor(event_t event, wait_result_t result) 2164 { 2165 return wakeup_with_inheritor_and_turnstile_type(event, 2166 TURNSTILE_SLEEP_INHERITOR, 2167 result, 2168 FALSE, 2169 0, 2170 NULL); 2171 } 2172 2173 /* 2174 * change_sleep_inheritor is independent from the locking primitive. 2175 */ 2176 2177 /* 2178 * Name: change_sleep_inheritor 2179 * 2180 * Description: Redirect the push of the waiting threads of event to the new inheritor specified. 2181 * 2182 * Args: 2183 * Arg1: event to redirect the push. 2184 * Arg2: new inheritor for event. 2185 * 2186 * Returns: KERN_NOT_WAITING if no threads were waiting, KERN_SUCCESS otherwise. 2187 * 2188 * Conditions: In case of success, the new inheritor cannot run in user space until another inheritor is specified for the event or a 2189 * wakeup for the event is called. 2190 * NOTE: this cannot be called from interrupt context. 2191 */ 2192 kern_return_t 2193 change_sleep_inheritor(event_t event, thread_t inheritor) 2194 { 2195 return change_sleep_inheritor_and_turnstile_type(event, 2196 inheritor, 2197 TURNSTILE_SLEEP_INHERITOR); 2198 } 2199 2200 void 2201 kdp_sleep_with_inheritor_find_owner(struct waitq * waitq, __unused event64_t event, thread_waitinfo_t * waitinfo) 2202 { 2203 assert(waitinfo->wait_type == kThreadWaitSleepWithInheritor); 2204 assert(waitq_is_turnstile_queue(waitq)); 2205 waitinfo->owner = 0; 2206 waitinfo->context = 0; 2207 2208 if (waitq_held(waitq)) { 2209 return; 2210 } 2211 2212 struct turnstile *turnstile = waitq_to_turnstile(waitq); 2213 assert(turnstile->ts_inheritor_flags & TURNSTILE_INHERITOR_THREAD); 2214 waitinfo->owner = thread_tid(turnstile->ts_inheritor); 2215 } 2216 2217 typedef void (*void_func_void)(void); 2218 2219 static kern_return_t 2220 gate_try_close(gate_t *gate) 2221 { 2222 uintptr_t state; 2223 thread_t holder; 2224 kern_return_t ret; 2225 __assert_only bool waiters; 2226 thread_t thread = current_thread(); 2227 2228 if (os_atomic_cmpxchg(&gate->gate_data, 0, GATE_THREAD_TO_STATE(thread), acquire)) { 2229 return KERN_SUCCESS; 2230 } 2231 2232 gate_ilock(gate); 2233 state = ordered_load_gate(gate); 2234 holder = GATE_STATE_TO_THREAD(state); 2235 2236 if (holder == NULL) { 2237 waiters = gate_has_waiters(state); 2238 assert(waiters == FALSE); 2239 2240 state = GATE_THREAD_TO_STATE(current_thread()); 2241 state |= GATE_ILOCK; 2242 ordered_store_gate(gate, state); 2243 ret = KERN_SUCCESS; 2244 } else { 2245 if (holder == current_thread()) { 2246 panic("Trying to close a gate already owned by current thread %p", current_thread()); 2247 } 2248 ret = KERN_FAILURE; 2249 } 2250 2251 gate_iunlock(gate); 2252 return ret; 2253 } 2254 2255 static void 2256 gate_close(gate_t* gate) 2257 { 2258 uintptr_t state; 2259 thread_t holder; 2260 __assert_only bool waiters; 2261 thread_t thread = current_thread(); 2262 2263 if (os_atomic_cmpxchg(&gate->gate_data, 0, GATE_THREAD_TO_STATE(thread), acquire)) { 2264 return; 2265 } 2266 2267 gate_ilock(gate); 2268 state = ordered_load_gate(gate); 2269 holder = GATE_STATE_TO_THREAD(state); 2270 2271 if (holder != NULL) { 2272 panic("Closing a gate already owned by %p from current thread %p", holder, current_thread()); 2273 } 2274 2275 waiters = gate_has_waiters(state); 2276 assert(waiters == FALSE); 2277 2278 state = GATE_THREAD_TO_STATE(thread); 2279 state |= GATE_ILOCK; 2280 ordered_store_gate(gate, state); 2281 2282 gate_iunlock(gate); 2283 } 2284 2285 static void 2286 gate_open_turnstile(gate_t *gate) 2287 { 2288 struct turnstile *ts = NULL; 2289 2290 ts = turnstile_prepare((uintptr_t)gate, &gate->turnstile, TURNSTILE_NULL, TURNSTILE_KERNEL_MUTEX); 2291 waitq_wakeup64_all(&ts->ts_waitq, CAST_EVENT64_T(GATE_EVENT(gate)), THREAD_AWAKENED, WAITQ_ALL_PRIORITIES); 2292 turnstile_update_inheritor(ts, TURNSTILE_INHERITOR_NULL, TURNSTILE_IMMEDIATE_UPDATE); 2293 turnstile_update_inheritor_complete(ts, TURNSTILE_INTERLOCK_HELD); 2294 turnstile_complete((uintptr_t)gate, &gate->turnstile, NULL, TURNSTILE_KERNEL_MUTEX); 2295 /* 2296 * We can do the cleanup while holding the interlock. 2297 * It is ok because: 2298 * 1. current_thread is the previous inheritor and it is running 2299 * 2. new inheritor is NULL. 2300 * => No chain of turnstiles needs to be updated. 2301 */ 2302 turnstile_cleanup(); 2303 } 2304 2305 static void 2306 gate_open(gate_t *gate) 2307 { 2308 uintptr_t state; 2309 thread_t holder; 2310 bool waiters; 2311 thread_t thread = current_thread(); 2312 2313 if (os_atomic_cmpxchg(&gate->gate_data, GATE_THREAD_TO_STATE(thread), 0, release)) { 2314 return; 2315 } 2316 2317 gate_ilock(gate); 2318 state = ordered_load_gate(gate); 2319 holder = GATE_STATE_TO_THREAD(state); 2320 waiters = gate_has_waiters(state); 2321 2322 if (holder != thread) { 2323 panic("Opening gate owned by %p from current thread %p", holder, thread); 2324 } 2325 2326 if (waiters) { 2327 gate_open_turnstile(gate); 2328 } 2329 2330 state = GATE_ILOCK; 2331 ordered_store_gate(gate, state); 2332 2333 gate_iunlock(gate); 2334 } 2335 2336 static kern_return_t 2337 gate_handoff_turnstile(gate_t *gate, 2338 int flags, 2339 thread_t *thread_woken_up, 2340 bool *waiters) 2341 { 2342 struct turnstile *ts = NULL; 2343 kern_return_t ret = KERN_FAILURE; 2344 thread_t hp_thread; 2345 2346 ts = turnstile_prepare((uintptr_t)gate, &gate->turnstile, TURNSTILE_NULL, TURNSTILE_KERNEL_MUTEX); 2347 /* 2348 * Wake up the higest priority thread waiting on the gate 2349 */ 2350 hp_thread = waitq_wakeup64_identify(&ts->ts_waitq, CAST_EVENT64_T(GATE_EVENT(gate)), THREAD_AWAKENED, WAITQ_PROMOTE_ON_WAKE); 2351 2352 if (hp_thread != NULL) { 2353 /* 2354 * In this case waitq_wakeup64_identify has called turnstile_update_inheritor for us 2355 */ 2356 turnstile_update_inheritor_complete(ts, TURNSTILE_INTERLOCK_HELD); 2357 *thread_woken_up = hp_thread; 2358 *waiters = turnstile_has_waiters(ts); 2359 /* 2360 * Note: hp_thread is the new holder and the new inheritor. 2361 * In case there are no more waiters, it doesn't need to be the inheritor 2362 * and it shouldn't be it by the time it finishes the wait, so that its next open or 2363 * handoff can go through the fast path. 2364 * We could set the inheritor to NULL here, or the new holder itself can set it 2365 * on its way back from the sleep. In the latter case there are more chanses that 2366 * new waiters will come by, avoiding to do the opearation at all. 2367 */ 2368 ret = KERN_SUCCESS; 2369 } else { 2370 /* 2371 * waiters can have been woken up by an interrupt and still not 2372 * have updated gate->waiters, so we couldn't find them on the waitq. 2373 * Update the inheritor to NULL here, so that the current thread can return to userspace 2374 * indipendently from when the interrupted waiters will finish the wait. 2375 */ 2376 if (flags == GATE_HANDOFF_OPEN_IF_NO_WAITERS) { 2377 turnstile_update_inheritor(ts, TURNSTILE_INHERITOR_NULL, TURNSTILE_IMMEDIATE_UPDATE); 2378 turnstile_update_inheritor_complete(ts, TURNSTILE_INTERLOCK_HELD); 2379 } 2380 // there are no waiters. 2381 ret = KERN_NOT_WAITING; 2382 } 2383 2384 turnstile_complete((uintptr_t)gate, &gate->turnstile, NULL, TURNSTILE_KERNEL_MUTEX); 2385 2386 /* 2387 * We can do the cleanup while holding the interlock. 2388 * It is ok because: 2389 * 1. current_thread is the previous inheritor and it is running 2390 * 2. new inheritor is NULL or it is a just wokenup thread that will race acquiring the lock 2391 * of the gate before trying to sleep. 2392 * => No chain of turnstiles needs to be updated. 2393 */ 2394 turnstile_cleanup(); 2395 2396 return ret; 2397 } 2398 2399 static kern_return_t 2400 gate_handoff(gate_t *gate, 2401 int flags) 2402 { 2403 kern_return_t ret; 2404 thread_t new_holder = NULL; 2405 uintptr_t state; 2406 thread_t holder; 2407 bool waiters; 2408 thread_t thread = current_thread(); 2409 2410 assert(flags == GATE_HANDOFF_OPEN_IF_NO_WAITERS || flags == GATE_HANDOFF_DEFAULT); 2411 2412 if (flags == GATE_HANDOFF_OPEN_IF_NO_WAITERS) { 2413 if (os_atomic_cmpxchg(&gate->gate_data, GATE_THREAD_TO_STATE(thread), 0, release)) { 2414 //gate opened but there were no waiters, so return KERN_NOT_WAITING. 2415 return KERN_NOT_WAITING; 2416 } 2417 } 2418 2419 gate_ilock(gate); 2420 state = ordered_load_gate(gate); 2421 holder = GATE_STATE_TO_THREAD(state); 2422 waiters = gate_has_waiters(state); 2423 2424 if (holder != current_thread()) { 2425 panic("Handing off gate owned by %p from current thread %p", holder, current_thread()); 2426 } 2427 2428 if (waiters) { 2429 ret = gate_handoff_turnstile(gate, flags, &new_holder, &waiters); 2430 if (ret == KERN_SUCCESS) { 2431 state = GATE_THREAD_TO_STATE(new_holder); 2432 if (waiters) { 2433 state |= GATE_WAITERS; 2434 } 2435 } else { 2436 if (flags == GATE_HANDOFF_OPEN_IF_NO_WAITERS) { 2437 state = 0; 2438 } 2439 } 2440 } else { 2441 if (flags == GATE_HANDOFF_OPEN_IF_NO_WAITERS) { 2442 state = 0; 2443 } 2444 ret = KERN_NOT_WAITING; 2445 } 2446 state |= GATE_ILOCK; 2447 ordered_store_gate(gate, state); 2448 2449 gate_iunlock(gate); 2450 2451 if (new_holder) { 2452 thread_deallocate(new_holder); 2453 } 2454 return ret; 2455 } 2456 2457 static void_func_void 2458 gate_steal_turnstile(gate_t *gate, 2459 thread_t new_inheritor) 2460 { 2461 struct turnstile *ts = NULL; 2462 2463 ts = turnstile_prepare((uintptr_t)gate, &gate->turnstile, TURNSTILE_NULL, TURNSTILE_KERNEL_MUTEX); 2464 2465 turnstile_update_inheritor(ts, new_inheritor, (TURNSTILE_IMMEDIATE_UPDATE | TURNSTILE_INHERITOR_THREAD)); 2466 turnstile_update_inheritor_complete(ts, TURNSTILE_INTERLOCK_HELD); 2467 turnstile_complete((uintptr_t)gate, &gate->turnstile, NULL, TURNSTILE_KERNEL_MUTEX); 2468 2469 /* 2470 * turnstile_cleanup might need to update the chain of the old holder. 2471 * This operation should happen without the turnstile interlock held. 2472 */ 2473 return turnstile_cleanup; 2474 } 2475 2476 static void 2477 gate_steal(gate_t *gate) 2478 { 2479 uintptr_t state; 2480 thread_t holder; 2481 thread_t thread = current_thread(); 2482 bool waiters; 2483 2484 void_func_void func_after_interlock_unlock; 2485 2486 gate_ilock(gate); 2487 state = ordered_load_gate(gate); 2488 holder = GATE_STATE_TO_THREAD(state); 2489 waiters = gate_has_waiters(state); 2490 2491 assert(holder != NULL); 2492 state = GATE_THREAD_TO_STATE(thread) | GATE_ILOCK; 2493 if (waiters) { 2494 state |= GATE_WAITERS; 2495 ordered_store_gate(gate, state); 2496 func_after_interlock_unlock = gate_steal_turnstile(gate, thread); 2497 gate_iunlock(gate); 2498 2499 func_after_interlock_unlock(); 2500 } else { 2501 ordered_store_gate(gate, state); 2502 gate_iunlock(gate); 2503 } 2504 } 2505 2506 static void_func_void 2507 gate_wait_turnstile(gate_t *gate, 2508 wait_interrupt_t interruptible, 2509 uint64_t deadline, 2510 thread_t holder, 2511 wait_result_t* wait, 2512 bool* waiters) 2513 { 2514 struct turnstile *ts; 2515 uintptr_t state; 2516 2517 ts = turnstile_prepare((uintptr_t)gate, &gate->turnstile, TURNSTILE_NULL, TURNSTILE_KERNEL_MUTEX); 2518 2519 turnstile_update_inheritor(ts, holder, (TURNSTILE_DELAYED_UPDATE | TURNSTILE_INHERITOR_THREAD)); 2520 waitq_assert_wait64(&ts->ts_waitq, CAST_EVENT64_T(GATE_EVENT(gate)), interruptible, deadline); 2521 2522 gate_iunlock(gate); 2523 2524 turnstile_update_inheritor_complete(ts, TURNSTILE_INTERLOCK_NOT_HELD); 2525 2526 *wait = thread_block(THREAD_CONTINUE_NULL); 2527 2528 gate_ilock(gate); 2529 2530 *waiters = turnstile_has_waiters(ts); 2531 2532 if (!*waiters) { 2533 /* 2534 * We want to enable the fast path as soon as we see that there are no more waiters. 2535 * On the fast path the holder will not do any turnstile operations. 2536 * Set the inheritor as NULL here. 2537 * 2538 * NOTE: if it was an open operation that woke this thread up, the inheritor has 2539 * already been set to NULL. 2540 */ 2541 state = ordered_load_gate(gate); 2542 holder = GATE_STATE_TO_THREAD(state); 2543 if (holder && 2544 ((*wait != THREAD_AWAKENED) || // thread interrupted or timedout 2545 holder == current_thread())) { // thread was woken up and it is the new holder 2546 turnstile_update_inheritor(ts, TURNSTILE_INHERITOR_NULL, TURNSTILE_IMMEDIATE_UPDATE); 2547 turnstile_update_inheritor_complete(ts, TURNSTILE_INTERLOCK_NOT_HELD); 2548 } 2549 } 2550 2551 turnstile_complete((uintptr_t)gate, &gate->turnstile, NULL, TURNSTILE_KERNEL_MUTEX); 2552 2553 /* 2554 * turnstile_cleanup might need to update the chain of the old holder. 2555 * This operation should happen without the turnstile primitive interlock held. 2556 */ 2557 return turnstile_cleanup; 2558 } 2559 2560 static gate_wait_result_t 2561 gate_wait(gate_t* gate, 2562 wait_interrupt_t interruptible, 2563 uint64_t deadline, 2564 void (^primitive_unlock)(void), 2565 void (^primitive_lock)(void)) 2566 { 2567 gate_wait_result_t ret; 2568 void_func_void func_after_interlock_unlock; 2569 wait_result_t wait_result; 2570 uintptr_t state; 2571 thread_t holder; 2572 bool waiters; 2573 2574 2575 gate_ilock(gate); 2576 state = ordered_load_gate(gate); 2577 holder = GATE_STATE_TO_THREAD(state); 2578 2579 if (holder == NULL) { 2580 panic("Trying to wait on open gate thread %p gate %p", current_thread(), gate); 2581 } 2582 2583 state |= GATE_WAITERS; 2584 ordered_store_gate(gate, state); 2585 2586 /* 2587 * Release the primitive lock before any 2588 * turnstile operation. Turnstile 2589 * does not support a blocking primitive as 2590 * interlock. 2591 * 2592 * In this way, concurrent threads will be 2593 * able to acquire the primitive lock 2594 * but still will wait for me through the 2595 * gate interlock. 2596 */ 2597 primitive_unlock(); 2598 2599 func_after_interlock_unlock = gate_wait_turnstile( gate, 2600 interruptible, 2601 deadline, 2602 holder, 2603 &wait_result, 2604 &waiters); 2605 2606 state = ordered_load_gate(gate); 2607 holder = GATE_STATE_TO_THREAD(state); 2608 2609 switch (wait_result) { 2610 case THREAD_INTERRUPTED: 2611 case THREAD_TIMED_OUT: 2612 assert(holder != current_thread()); 2613 2614 if (waiters) { 2615 state |= GATE_WAITERS; 2616 } else { 2617 state &= ~GATE_WAITERS; 2618 } 2619 ordered_store_gate(gate, state); 2620 2621 if (wait_result == THREAD_INTERRUPTED) { 2622 ret = GATE_INTERRUPTED; 2623 } else { 2624 ret = GATE_TIMED_OUT; 2625 } 2626 break; 2627 default: 2628 /* 2629 * Note it is possible that even if the gate was handed off to 2630 * me, someone called gate_steal() before I woke up. 2631 * 2632 * As well as it is possible that the gate was opened, but someone 2633 * closed it while I was waking up. 2634 * 2635 * In both cases we return GATE_OPENED, as the gate was opened to me 2636 * at one point, it is the caller responsibility to check again if 2637 * the gate is open. 2638 */ 2639 if (holder == current_thread()) { 2640 ret = GATE_HANDOFF; 2641 } else { 2642 ret = GATE_OPENED; 2643 } 2644 break; 2645 } 2646 2647 gate_iunlock(gate); 2648 2649 /* 2650 * turnstile func that needs to be executed without 2651 * holding the primitive interlock 2652 */ 2653 func_after_interlock_unlock(); 2654 2655 primitive_lock(); 2656 2657 return ret; 2658 } 2659 static void 2660 gate_assert(gate_t *gate, int flags) 2661 { 2662 uintptr_t state; 2663 thread_t holder; 2664 2665 gate_ilock(gate); 2666 state = ordered_load_gate(gate); 2667 holder = GATE_STATE_TO_THREAD(state); 2668 2669 switch (flags) { 2670 case GATE_ASSERT_CLOSED: 2671 assert(holder != NULL); 2672 break; 2673 case GATE_ASSERT_OPEN: 2674 assert(holder == NULL); 2675 break; 2676 case GATE_ASSERT_HELD: 2677 assert(holder == current_thread()); 2678 break; 2679 default: 2680 panic("invalid %s flag %d", __func__, flags); 2681 } 2682 2683 gate_iunlock(gate); 2684 } 2685 2686 static void 2687 gate_init(gate_t *gate) 2688 { 2689 gate->gate_data = 0; 2690 gate->turnstile = NULL; 2691 } 2692 2693 static void 2694 gate_destroy(__assert_only gate_t *gate) 2695 { 2696 assert(gate->gate_data == 0); 2697 assert(gate->turnstile == NULL); 2698 } 2699 2700 /* 2701 * Name: lck_rw_gate_init 2702 * 2703 * Description: initializes a variable declared with decl_lck_rw_gate_data. 2704 * 2705 * Args: 2706 * Arg1: lck_rw_t lock used to protect the gate. 2707 * Arg2: pointer to the gate data declared with decl_lck_rw_gate_data. 2708 */ 2709 void 2710 lck_rw_gate_init(lck_rw_t *lock, gate_t *gate) 2711 { 2712 (void) lock; 2713 gate_init(gate); 2714 } 2715 2716 /* 2717 * Name: lck_rw_gate_destroy 2718 * 2719 * Description: destroys a variable previously initialized. 2720 * 2721 * Args: 2722 * Arg1: lck_rw_t lock used to protect the gate. 2723 * Arg2: pointer to the gate data declared with decl_lck_rw_gate_data. 2724 */ 2725 void 2726 lck_rw_gate_destroy(lck_rw_t *lock, gate_t *gate) 2727 { 2728 (void) lock; 2729 gate_destroy(gate); 2730 } 2731 2732 /* 2733 * Name: lck_rw_gate_try_close 2734 * 2735 * Description: Tries to close the gate. 2736 * In case of success the current thread will be set as 2737 * the holder of the gate. 2738 * 2739 * Args: 2740 * Arg1: lck_rw_t lock used to protect the gate. 2741 * Arg2: pointer to the gate data declared with decl_lck_rw_gate_data. 2742 * 2743 * Conditions: Lock must be held. Returns with the lock held. 2744 * 2745 * Returns: 2746 * KERN_SUCCESS in case the gate was successfully closed. The current thread is the new holder 2747 * of the gate. 2748 * A matching lck_rw_gate_open() or lck_rw_gate_handoff() needs to be called later on 2749 * to wake up possible waiters on the gate before returning to userspace. 2750 * If the intent is to conditionally probe the gate before waiting, the lock must not be dropped 2751 * between the calls to lck_rw_gate_try_close() and lck_rw_gate_wait(). 2752 * 2753 * KERN_FAILURE in case the gate was already closed. Will panic if the current thread was already the holder of the gate. 2754 * lck_rw_gate_wait() should be called instead if the intent is to unconditionally wait on this gate. 2755 * The calls to lck_rw_gate_try_close() and lck_rw_gate_wait() should 2756 * be done without dropping the lock that is protecting the gate in between. 2757 */ 2758 int 2759 lck_rw_gate_try_close(__assert_only lck_rw_t *lock, gate_t *gate) 2760 { 2761 LCK_RW_ASSERT(lock, LCK_RW_ASSERT_HELD); 2762 2763 return gate_try_close(gate); 2764 } 2765 2766 /* 2767 * Name: lck_rw_gate_close 2768 * 2769 * Description: Closes the gate. The current thread will be set as 2770 * the holder of the gate. Will panic if the gate is already closed. 2771 * A matching lck_rw_gate_open() or lck_rw_gate_handoff() needs to be called later on 2772 * to wake up possible waiters on the gate before returning to userspace. 2773 * 2774 * Args: 2775 * Arg1: lck_rw_t lock used to protect the gate. 2776 * Arg2: pointer to the gate data declared with decl_lck_rw_gate_data. 2777 * 2778 * Conditions: Lock must be held. Returns with the lock held. 2779 * The gate must be open. 2780 * 2781 */ 2782 void 2783 lck_rw_gate_close(__assert_only lck_rw_t *lock, gate_t *gate) 2784 { 2785 LCK_RW_ASSERT(lock, LCK_RW_ASSERT_HELD); 2786 2787 return gate_close(gate); 2788 } 2789 2790 /* 2791 * Name: lck_rw_gate_open 2792 * 2793 * Description: Opens the gate and wakes up possible waiters. 2794 * 2795 * Args: 2796 * Arg1: lck_rw_t lock used to protect the gate. 2797 * Arg2: pointer to the gate data declared with decl_lck_rw_gate_data. 2798 * 2799 * Conditions: Lock must be held. Returns with the lock held. 2800 * The current thread must be the holder of the gate. 2801 * 2802 */ 2803 void 2804 lck_rw_gate_open(__assert_only lck_rw_t *lock, gate_t *gate) 2805 { 2806 LCK_RW_ASSERT(lock, LCK_RW_ASSERT_HELD); 2807 2808 gate_open(gate); 2809 } 2810 2811 /* 2812 * Name: lck_rw_gate_handoff 2813 * 2814 * Description: Tries to transfer the ownership of the gate. The waiter with highest sched 2815 * priority will be selected as the new holder of the gate, and woken up, 2816 * with the gate remaining in the closed state throughout. 2817 * If no waiters are present, the gate will be kept closed and KERN_NOT_WAITING 2818 * will be returned. 2819 * GATE_HANDOFF_OPEN_IF_NO_WAITERS flag can be used to specify if the gate should be opened in 2820 * case no waiters were found. 2821 * 2822 * 2823 * Args: 2824 * Arg1: lck_rw_t lock used to protect the gate. 2825 * Arg2: pointer to the gate data declared with decl_lck_rw_gate_data. 2826 * Arg3: flags - GATE_HANDOFF_DEFAULT or GATE_HANDOFF_OPEN_IF_NO_WAITERS 2827 * 2828 * Conditions: Lock must be held. Returns with the lock held. 2829 * The current thread must be the holder of the gate. 2830 * 2831 * Returns: 2832 * KERN_SUCCESS in case one of the waiters became the new holder. 2833 * KERN_NOT_WAITING in case there were no waiters. 2834 * 2835 */ 2836 kern_return_t 2837 lck_rw_gate_handoff(__assert_only lck_rw_t *lock, gate_t *gate, int flags) 2838 { 2839 LCK_RW_ASSERT(lock, LCK_RW_ASSERT_HELD); 2840 2841 return gate_handoff(gate, flags); 2842 } 2843 2844 /* 2845 * Name: lck_rw_gate_steal 2846 * 2847 * Description: Set the current ownership of the gate. It sets the current thread as the 2848 * new holder of the gate. 2849 * A matching lck_rw_gate_open() or lck_rw_gate_handoff() needs to be called later on 2850 * to wake up possible waiters on the gate before returning to userspace. 2851 * NOTE: the previous holder should not call lck_rw_gate_open() or lck_rw_gate_handoff() 2852 * anymore. 2853 * 2854 * 2855 * Args: 2856 * Arg1: lck_rw_t lock used to protect the gate. 2857 * Arg2: pointer to the gate data declared with decl_lck_rw_gate_data. 2858 * 2859 * Conditions: Lock must be held. Returns with the lock held. 2860 * The gate must be closed and the current thread must not already be the holder. 2861 * 2862 */ 2863 void 2864 lck_rw_gate_steal(__assert_only lck_rw_t *lock, gate_t *gate) 2865 { 2866 LCK_RW_ASSERT(lock, LCK_RW_ASSERT_HELD); 2867 2868 gate_steal(gate); 2869 } 2870 2871 /* 2872 * Name: lck_rw_gate_wait 2873 * 2874 * Description: Waits for the current thread to become the holder of the gate or for the 2875 * gate to become open. An interruptible mode and deadline can be specified 2876 * to return earlier from the wait. 2877 * 2878 * Args: 2879 * Arg1: lck_rw_t lock used to protect the gate. 2880 * Arg2: pointer to the gate data declared with decl_lck_rw_gate_data. 2881 * Arg3: sleep action. LCK_SLEEP_DEFAULT, LCK_SLEEP_SHARED, LCK_SLEEP_EXCLUSIVE. 2882 * Arg3: interruptible flag for wait. 2883 * Arg4: deadline 2884 * 2885 * Conditions: Lock must be held. Returns with the lock held according to the sleep action specified. 2886 * Lock will be dropped while waiting. 2887 * The gate must be closed. 2888 * 2889 * Returns: Reason why the thread was woken up. 2890 * GATE_HANDOFF - the current thread was handed off the ownership of the gate. 2891 * A matching lck_rw_gate_open() or lck_rw_gate_handoff() needs to be called later on 2892 * to wake up possible waiters on the gate before returning to userspace. 2893 * GATE_OPENED - the gate was opened by the holder. 2894 * GATE_TIMED_OUT - the thread was woken up by a timeout. 2895 * GATE_INTERRUPTED - the thread was interrupted while sleeping. 2896 * 2897 */ 2898 gate_wait_result_t 2899 lck_rw_gate_wait(lck_rw_t *lock, gate_t *gate, lck_sleep_action_t lck_sleep_action, wait_interrupt_t interruptible, uint64_t deadline) 2900 { 2901 __block lck_rw_type_t lck_rw_type = LCK_RW_TYPE_EXCLUSIVE; 2902 2903 LCK_RW_ASSERT(lock, LCK_RW_ASSERT_HELD); 2904 2905 if (lck_sleep_action & LCK_SLEEP_UNLOCK) { 2906 return gate_wait(gate, 2907 interruptible, 2908 deadline, 2909 ^{lck_rw_type = lck_rw_done(lock);}, 2910 ^{;}); 2911 } else if (!(lck_sleep_action & (LCK_SLEEP_SHARED | LCK_SLEEP_EXCLUSIVE))) { 2912 return gate_wait(gate, 2913 interruptible, 2914 deadline, 2915 ^{lck_rw_type = lck_rw_done(lock);}, 2916 ^{lck_rw_lock(lock, lck_rw_type);}); 2917 } else if (lck_sleep_action & LCK_SLEEP_EXCLUSIVE) { 2918 return gate_wait(gate, 2919 interruptible, 2920 deadline, 2921 ^{lck_rw_type = lck_rw_done(lock);}, 2922 ^{lck_rw_lock_exclusive(lock);}); 2923 } else { 2924 return gate_wait(gate, 2925 interruptible, 2926 deadline, 2927 ^{lck_rw_type = lck_rw_done(lock);}, 2928 ^{lck_rw_lock_shared(lock);}); 2929 } 2930 } 2931 2932 /* 2933 * Name: lck_rw_gate_assert 2934 * 2935 * Description: asserts that the gate is in the specified state. 2936 * 2937 * Args: 2938 * Arg1: lck_rw_t lock used to protect the gate. 2939 * Arg2: pointer to the gate data declared with decl_lck_rw_gate_data. 2940 * Arg3: flags to specified assert type. 2941 * GATE_ASSERT_CLOSED - the gate is currently closed 2942 * GATE_ASSERT_OPEN - the gate is currently opened 2943 * GATE_ASSERT_HELD - the gate is currently closed and the current thread is the holder 2944 */ 2945 void 2946 lck_rw_gate_assert(__assert_only lck_rw_t *lock, gate_t *gate, int flags) 2947 { 2948 LCK_RW_ASSERT(lock, LCK_RW_ASSERT_HELD); 2949 2950 gate_assert(gate, flags); 2951 return; 2952 } 2953 2954 /* 2955 * Name: lck_mtx_gate_init 2956 * 2957 * Description: initializes a variable declared with decl_lck_mtx_gate_data. 2958 * 2959 * Args: 2960 * Arg1: lck_mtx_t lock used to protect the gate. 2961 * Arg2: pointer to the gate data declared with decl_lck_mtx_gate_data. 2962 */ 2963 void 2964 lck_mtx_gate_init(lck_mtx_t *lock, gate_t *gate) 2965 { 2966 (void) lock; 2967 gate_init(gate); 2968 } 2969 2970 /* 2971 * Name: lck_mtx_gate_destroy 2972 * 2973 * Description: destroys a variable previously initialized 2974 * 2975 * Args: 2976 * Arg1: lck_mtx_t lock used to protect the gate. 2977 * Arg2: pointer to the gate data declared with decl_lck_mtx_gate_data. 2978 */ 2979 void 2980 lck_mtx_gate_destroy(lck_mtx_t *lock, gate_t *gate) 2981 { 2982 (void) lock; 2983 gate_destroy(gate); 2984 } 2985 2986 /* 2987 * Name: lck_mtx_gate_try_close 2988 * 2989 * Description: Tries to close the gate. 2990 * In case of success the current thread will be set as 2991 * the holder of the gate. 2992 * 2993 * Args: 2994 * Arg1: lck_mtx_t lock used to protect the gate. 2995 * Arg2: pointer to the gate data declared with decl_lck_mtx_gate_data. 2996 * 2997 * Conditions: Lock must be held. Returns with the lock held. 2998 * 2999 * Returns: 3000 * KERN_SUCCESS in case the gate was successfully closed. The current thread is the new holder 3001 * of the gate. 3002 * A matching lck_mtx_gate_open() or lck_mtx_gate_handoff() needs to be called later on 3003 * to wake up possible waiters on the gate before returning to userspace. 3004 * If the intent is to conditionally probe the gate before waiting, the lock must not be dropped 3005 * between the calls to lck_mtx_gate_try_close() and lck_mtx_gate_wait(). 3006 * 3007 * KERN_FAILURE in case the gate was already closed. Will panic if the current thread was already the holder of the gate. 3008 * lck_mtx_gate_wait() should be called instead if the intent is to unconditionally wait on this gate. 3009 * The calls to lck_mtx_gate_try_close() and lck_mtx_gate_wait() should 3010 * be done without dropping the lock that is protecting the gate in between. 3011 */ 3012 int 3013 lck_mtx_gate_try_close(__assert_only lck_mtx_t *lock, gate_t *gate) 3014 { 3015 LCK_MTX_ASSERT(lock, LCK_MTX_ASSERT_OWNED); 3016 3017 return gate_try_close(gate); 3018 } 3019 3020 /* 3021 * Name: lck_mtx_gate_close 3022 * 3023 * Description: Closes the gate. The current thread will be set as 3024 * the holder of the gate. Will panic if the gate is already closed. 3025 * A matching lck_mtx_gate_open() or lck_mtx_gate_handoff() needs to be called later on 3026 * to wake up possible waiters on the gate before returning to userspace. 3027 * 3028 * Args: 3029 * Arg1: lck_mtx_t lock used to protect the gate. 3030 * Arg2: pointer to the gate data declared with decl_lck_mtx_gate_data. 3031 * 3032 * Conditions: Lock must be held. Returns with the lock held. 3033 * The gate must be open. 3034 * 3035 */ 3036 void 3037 lck_mtx_gate_close(__assert_only lck_mtx_t *lock, gate_t *gate) 3038 { 3039 LCK_MTX_ASSERT(lock, LCK_MTX_ASSERT_OWNED); 3040 3041 return gate_close(gate); 3042 } 3043 3044 /* 3045 * Name: lck_mtx_gate_open 3046 * 3047 * Description: Opens of the gate and wakes up possible waiters. 3048 * 3049 * Args: 3050 * Arg1: lck_mtx_t lock used to protect the gate. 3051 * Arg2: pointer to the gate data declared with decl_lck_mtx_gate_data. 3052 * 3053 * Conditions: Lock must be held. Returns with the lock held. 3054 * The current thread must be the holder of the gate. 3055 * 3056 */ 3057 void 3058 lck_mtx_gate_open(__assert_only lck_mtx_t *lock, gate_t *gate) 3059 { 3060 LCK_MTX_ASSERT(lock, LCK_MTX_ASSERT_OWNED); 3061 3062 gate_open(gate); 3063 } 3064 3065 /* 3066 * Name: lck_mtx_gate_handoff 3067 * 3068 * Description: Set the current ownership of the gate. The waiter with highest sched 3069 * priority will be selected as the new holder of the gate, and woken up, 3070 * with the gate remaining in the closed state throughout. 3071 * If no waiters are present, the gate will be kept closed and KERN_NOT_WAITING 3072 * will be returned. 3073 * OPEN_ON_FAILURE flag can be used to specify if the gate should be opened in 3074 * case no waiters were found. 3075 * 3076 * 3077 * Args: 3078 * Arg1: lck_mtx_t lock used to protect the gate. 3079 * Arg2: pointer to the gate data declared with decl_lck_mtx_gate_data. 3080 * Arg3: flags - GATE_NO_FALGS or OPEN_ON_FAILURE 3081 * 3082 * Conditions: Lock must be held. Returns with the lock held. 3083 * The current thread must be the holder of the gate. 3084 * 3085 * Returns: 3086 * KERN_SUCCESS in case one of the waiters became the new holder. 3087 * KERN_NOT_WAITING in case there were no waiters. 3088 * 3089 */ 3090 kern_return_t 3091 lck_mtx_gate_handoff(__assert_only lck_mtx_t *lock, gate_t *gate, int flags) 3092 { 3093 LCK_MTX_ASSERT(lock, LCK_MTX_ASSERT_OWNED); 3094 3095 return gate_handoff(gate, flags); 3096 } 3097 3098 /* 3099 * Name: lck_mtx_gate_steal 3100 * 3101 * Description: Steals the ownership of the gate. It sets the current thread as the 3102 * new holder of the gate. 3103 * A matching lck_mtx_gate_open() or lck_mtx_gate_handoff() needs to be called later on 3104 * to wake up possible waiters on the gate before returning to userspace. 3105 * NOTE: the previous holder should not call lck_mtx_gate_open() or lck_mtx_gate_handoff() 3106 * anymore. 3107 * 3108 * 3109 * Args: 3110 * Arg1: lck_mtx_t lock used to protect the gate. 3111 * Arg2: pointer to the gate data declared with decl_lck_mtx_gate_data. 3112 * 3113 * Conditions: Lock must be held. Returns with the lock held. 3114 * The gate must be closed and the current thread must not already be the holder. 3115 * 3116 */ 3117 void 3118 lck_mtx_gate_steal(__assert_only lck_mtx_t *lock, gate_t *gate) 3119 { 3120 LCK_MTX_ASSERT(lock, LCK_MTX_ASSERT_OWNED); 3121 3122 gate_steal(gate); 3123 } 3124 3125 /* 3126 * Name: lck_mtx_gate_wait 3127 * 3128 * Description: Waits for the current thread to become the holder of the gate or for the 3129 * gate to become open. An interruptible mode and deadline can be specified 3130 * to return earlier from the wait. 3131 * 3132 * Args: 3133 * Arg1: lck_mtx_t lock used to protect the gate. 3134 * Arg2: pointer to the gate data declared with decl_lck_mtx_gate_data. 3135 * Arg3: sleep action. LCK_SLEEP_DEFAULT, LCK_SLEEP_UNLOCK, LCK_SLEEP_SPIN, LCK_SLEEP_SPIN_ALWAYS. 3136 * Arg3: interruptible flag for wait. 3137 * Arg4: deadline 3138 * 3139 * Conditions: Lock must be held. Returns with the lock held according to the sleep action specified. 3140 * Lock will be dropped while waiting. 3141 * The gate must be closed. 3142 * 3143 * Returns: Reason why the thread was woken up. 3144 * GATE_HANDOFF - the current thread was handed off the ownership of the gate. 3145 * A matching lck_mtx_gate_open() or lck_mtx_gate_handoff() needs to be called later on 3146 * to wake up possible waiters on the gate before returning to userspace. 3147 * GATE_OPENED - the gate was opened by the holder. 3148 * GATE_TIMED_OUT - the thread was woken up by a timeout. 3149 * GATE_INTERRUPTED - the thread was interrupted while sleeping. 3150 * 3151 */ 3152 gate_wait_result_t 3153 lck_mtx_gate_wait(lck_mtx_t *lock, gate_t *gate, lck_sleep_action_t lck_sleep_action, wait_interrupt_t interruptible, uint64_t deadline) 3154 { 3155 LCK_MTX_ASSERT(lock, LCK_MTX_ASSERT_OWNED); 3156 3157 if (lck_sleep_action & LCK_SLEEP_UNLOCK) { 3158 return gate_wait(gate, 3159 interruptible, 3160 deadline, 3161 ^{lck_mtx_unlock(lock);}, 3162 ^{;}); 3163 } else if (lck_sleep_action & LCK_SLEEP_SPIN) { 3164 return gate_wait(gate, 3165 interruptible, 3166 deadline, 3167 ^{lck_mtx_unlock(lock);}, 3168 ^{lck_mtx_lock_spin(lock);}); 3169 } else if (lck_sleep_action & LCK_SLEEP_SPIN_ALWAYS) { 3170 return gate_wait(gate, 3171 interruptible, 3172 deadline, 3173 ^{lck_mtx_unlock(lock);}, 3174 ^{lck_mtx_lock_spin_always(lock);}); 3175 } else { 3176 return gate_wait(gate, 3177 interruptible, 3178 deadline, 3179 ^{lck_mtx_unlock(lock);}, 3180 ^{lck_mtx_lock(lock);}); 3181 } 3182 } 3183 3184 /* 3185 * Name: lck_mtx_gate_assert 3186 * 3187 * Description: asserts that the gate is in the specified state. 3188 * 3189 * Args: 3190 * Arg1: lck_mtx_t lock used to protect the gate. 3191 * Arg2: pointer to the gate data declared with decl_lck_mtx_gate_data. 3192 * Arg3: flags to specified assert type. 3193 * GATE_ASSERT_CLOSED - the gate is currently closed 3194 * GATE_ASSERT_OPEN - the gate is currently opened 3195 * GATE_ASSERT_HELD - the gate is currently closed and the current thread is the holder 3196 */ 3197 void 3198 lck_mtx_gate_assert(__assert_only lck_mtx_t *lock, gate_t *gate, int flags) 3199 { 3200 LCK_MTX_ASSERT(lock, LCK_MTX_ASSERT_OWNED); 3201 3202 gate_assert(gate, flags); 3203 } 3204 3205 #pragma mark - LCK_*_DECLARE support 3206 3207 __startup_func 3208 void 3209 lck_grp_attr_startup_init(struct lck_grp_attr_startup_spec *sp) 3210 { 3211 lck_grp_attr_t *attr = sp->grp_attr; 3212 lck_grp_attr_setdefault(attr); 3213 attr->grp_attr_val |= sp->grp_attr_set_flags; 3214 attr->grp_attr_val &= ~sp->grp_attr_clear_flags; 3215 } 3216 3217 __startup_func 3218 void 3219 lck_grp_startup_init(struct lck_grp_startup_spec *sp) 3220 { 3221 lck_grp_init(sp->grp, sp->grp_name, sp->grp_attr); 3222 } 3223 3224 __startup_func 3225 void 3226 lck_attr_startup_init(struct lck_attr_startup_spec *sp) 3227 { 3228 lck_attr_t *attr = sp->lck_attr; 3229 lck_attr_setdefault(attr); 3230 attr->lck_attr_val |= sp->lck_attr_set_flags; 3231 attr->lck_attr_val &= ~sp->lck_attr_clear_flags; 3232 } 3233 3234 __startup_func 3235 void 3236 lck_spin_startup_init(struct lck_spin_startup_spec *sp) 3237 { 3238 lck_spin_init(sp->lck, sp->lck_grp, sp->lck_attr); 3239 } 3240 3241 __startup_func 3242 void 3243 lck_mtx_startup_init(struct lck_mtx_startup_spec *sp) 3244 { 3245 if (sp->lck_ext) { 3246 lck_mtx_init_ext(sp->lck, sp->lck_ext, sp->lck_grp, sp->lck_attr); 3247 } else { 3248 lck_mtx_init(sp->lck, sp->lck_grp, sp->lck_attr); 3249 } 3250 } 3251 3252 __startup_func 3253 void 3254 lck_rw_startup_init(struct lck_rw_startup_spec *sp) 3255 { 3256 lck_rw_init(sp->lck, sp->lck_grp, sp->lck_attr); 3257 } 3258 3259 __startup_func 3260 void 3261 usimple_lock_startup_init(struct usimple_lock_startup_spec *sp) 3262 { 3263 simple_lock_init(sp->lck, sp->lck_init_arg); 3264 }