static void _dispatch_semaphore_create_port(semaphore_t *s4) { kern_return_t kr; semaphore_t tmp; if (*s4) { return; } _dispatch_safe_fork = false; // lazily allocate the semaphore port // Someday: // 1) Switch to a doubly-linked FIFO in user-space. // 2) User-space timers for the timeout. // 3) Use the per-thread semaphore port. while ((kr = semaphore_create(mach_task_self(), &tmp, SYNC_POLICY_FIFO, 0))) { DISPATCH_VERIFY_MIG(kr); sleep(1); } if (!dispatch_atomic_cmpxchg(s4, 0, tmp)) { kr = semaphore_destroy(mach_task_self(), tmp); DISPATCH_SEMAPHORE_VERIFY_KR(kr); } }
void _voucher_dealloc_mach_voucher(mach_voucher_t kv) { _dispatch_kvoucher_debug("dealloc", kv); _dispatch_voucher_debug_machport(kv); kern_return_t kr = mach_voucher_deallocate(kv); DISPATCH_VERIFY_MIG(kr); (void)dispatch_assume_zero(kr); }
static inline kern_return_t _voucher_create_mach_voucher(const mach_voucher_attr_recipe_data_t *recipes, size_t recipes_size, mach_voucher_t *kvp) { kern_return_t kr; mach_port_t mhp = _dispatch_get_mach_host_port(); mach_voucher_t kv = MACH_VOUCHER_NULL; mach_voucher_attr_raw_recipe_array_t kvr; mach_voucher_attr_recipe_size_t kvr_size; kvr = (mach_voucher_attr_raw_recipe_array_t)recipes; kvr_size = (mach_voucher_attr_recipe_size_t)recipes_size; kr = host_create_mach_voucher(mhp, kvr, kvr_size, &kv); DISPATCH_VERIFY_MIG(kr); if (!kr) { _dispatch_kvoucher_debug("create", kv); _dispatch_voucher_debug_machport(kv); } *kvp = kv; return kr; }
DISPATCH_NOINLINE static _dispatch_thread_semaphore_t _dispatch_thread_semaphore_create(void) { _dispatch_safe_fork = false; #if USE_MACH_SEM semaphore_t s4; kern_return_t kr; while (slowpath(kr = semaphore_create(mach_task_self(), &s4, SYNC_POLICY_FIFO, 0))) { DISPATCH_VERIFY_MIG(kr); sleep(1); } return s4; #elif USE_POSIX_SEM sem_t *s4 = malloc(sizeof(*s4)); int ret = sem_init(s4, 0, 0); DISPATCH_SEMAPHORE_VERIFY_RET(ret); return (_dispatch_thread_semaphore_t) s4; #endif }