From c6e5f90c4dd303939f631da331df7b356da942e6 Mon Sep 17 00:00:00 2001 From: Apple Date: Fri, 31 Jan 2020 01:57:10 +0000 Subject: [PATCH] libpthread-416.11.1.tar.gz --- kern/kern_support.c | 155 +++++--- kern/kern_synch.c | 22 +- libpthread.xcodeproj/project.pbxproj | 185 +++++----- man/pthread_setname_np.3 | 2 +- private/private.h | 11 +- private/tsd_private.h | 7 + private/workqueue_private.h | 17 + pthread/pthread.h | 2 +- src/internal.h | 57 ++- src/pthread.c | 467 +++++++++++++----------- src/pthread_asm.s | 157 ++++++-- src/pthread_cancelable.c | 15 +- src/pthread_cond.c | 57 +-- src/pthread_cwd.c | 4 +- src/pthread_dependency.c | 3 +- src/pthread_mutex.c | 9 +- src/pthread_rwlock.c | 15 +- src/pthread_support.c | 55 --- src/pthread_tsd.c | 22 +- src/qos.c | 4 +- src/thread_setup.c | 112 ------ sys/qos.h | 2 + sys/qos_private.h | 2 +- tests/Makefile | 14 + tests/cond_timed.c | 13 + tests/helpers/stackoverflow_crash.c | 56 +++ tests/pthread_create_from_mach_thread.c | 93 +++++ tests/pthread_threadid_np.c | 16 +- tests/setrlimit_sigsegv.c | 52 +++ tests/stack.c | 15 +- tests/stack_size.c | 4 + xcodescripts/install-codes.sh | 3 + xcodescripts/install-lldbmacros.sh | 6 + xcodescripts/install-manpages.sh | 1 + xcodescripts/install-symlinks.sh | 2 + xcodescripts/install-sys-headers.sh | 2 + xcodescripts/kext.xcconfig | 4 +- xcodescripts/pthread.dirty | 1 - xcodescripts/pthread.xcconfig | 33 +- 39 files changed, 1038 insertions(+), 659 deletions(-) delete mode 100644 src/pthread_support.c delete mode 100644 src/thread_setup.c create mode 100644 tests/helpers/stackoverflow_crash.c create mode 100644 tests/pthread_create_from_mach_thread.c create mode 100644 tests/setrlimit_sigsegv.c diff --git a/kern/kern_support.c b/kern/kern_support.c index e424cce..0e576c2 100644 --- a/kern/kern_support.c +++ b/kern/kern_support.c @@ -122,12 +122,18 @@ lck_attr_t *pthread_lck_attr; #define C_32_STK_ALIGN 16 #define C_64_STK_ALIGN 16 -#define C_64_REDZONE_LEN 128 // WORKQ use the largest alignment any platform needs #define C_WORKQ_STK_ALIGN 16 +#if defined(__arm64__) +/* Pull the pthread_t into the same page as the top of the stack so we dirty one less page. + * The _pthread struct at the top of the stack shouldn't be page-aligned + */ +#define PTHREAD_T_OFFSET (12*1024) +#else #define PTHREAD_T_OFFSET 0 +#endif /* * Flags filed passed to bsdthread_create and back in pthread_start @@ -169,11 +175,13 @@ stack_addr_hint(proc_t p, vm_map_t vmap) mach_vm_offset_t stackaddr; mach_vm_offset_t aslr_offset; bool proc64bit = proc_is64bit(p); + bool proc64bit_data = proc_is64bit_data(p); // We can't safely take random values % something unless its a power-of-two _Static_assert(powerof2(PTH_DEFAULT_STACKSIZE), "PTH_DEFAULT_STACKSIZE is a power-of-two"); #if defined(__i386__) || defined(__x86_64__) + (void)proc64bit_data; if (proc64bit) { // Matches vm_map_get_max_aslr_slide_pages's image shift in xnu aslr_offset = random() % (1 << 28); // about 512 stacks @@ -211,7 +219,13 @@ stack_addr_hint(proc_t p, vm_map_t vmap) stackaddr = SHARED_REGION_BASE_ARM64 - 64 * PTH_DEFAULT_STACKSIZE - aslr_offset; } else { // If you try to slide down from this point, you risk ending up in memory consumed by malloc - stackaddr = SHARED_REGION_BASE_ARM - 32 * PTH_DEFAULT_STACKSIZE + aslr_offset; + if (proc64bit_data) { + stackaddr = SHARED_REGION_BASE_ARM64_32; + } else { + stackaddr = SHARED_REGION_BASE_ARM; + } + + stackaddr -= 32 * PTH_DEFAULT_STACKSIZE + aslr_offset; } } #else @@ -308,7 +322,7 @@ _bsdthread_create(struct proc *p, .r8 = (uint64_t)user_stack, /* golang wants this */ .r9 = (uint64_t)flags, - .rsp = (uint64_t)(user_stack - C_64_REDZONE_LEN) + .rsp = (uint64_t)user_stack, }; (void)pthread_kern->thread_set_wq_state64(th, (thread_state_t)&state); @@ -322,7 +336,41 @@ _bsdthread_create(struct proc *p, .edi = (uint32_t)user_stack, /* golang wants this */ .esi = (uint32_t)flags, - .esp = (int)((vm_offset_t)(user_stack - C_32_STK_ALIGN)) + .esp = (uint32_t)user_stack, + }; + + (void)pthread_kern->thread_set_wq_state32(th, (thread_state_t)&state); + } +#elif defined(__arm__) || defined(__arm64__) + if (proc_is64bit_data(p)) { +#ifdef __arm64__ + arm_thread_state64_t state = { + .pc = (uint64_t)pthread_kern->proc_get_threadstart(p), + .x[0] = (uint64_t)user_pthread, + .x[1] = (uint64_t)th_thport, + .x[2] = (uint64_t)user_func, /* golang wants this */ + .x[3] = (uint64_t)user_funcarg, /* golang wants this */ + .x[4] = (uint64_t)user_stack, /* golang wants this */ + .x[5] = (uint64_t)flags, + + .sp = (uint64_t)user_stack, + }; + + (void)pthread_kern->thread_set_wq_state64(th, (thread_state_t)&state); +#else + panic("Shouldn't have a 64-bit thread on a 32-bit kernel..."); +#endif // defined(__arm64__) + } else { + arm_thread_state_t state = { + .pc = (uint32_t)pthread_kern->proc_get_threadstart(p), + .r[0] = (uint32_t)user_pthread, + .r[1] = (uint32_t)th_thport, + .r[2] = (uint32_t)user_func, /* golang wants this */ + .r[3] = (uint32_t)user_funcarg, /* golang wants this */ + .r[4] = (uint32_t)user_stack, /* golang wants this */ + .r[5] = (uint32_t)flags, + + .sp = (uint32_t)user_stack, }; (void)pthread_kern->thread_set_wq_state32(th, (thread_state_t)&state); @@ -755,63 +803,77 @@ workq_set_register_state(proc_t p, thread_t th, panic(__func__ ": thread_set_wq_state failed: %d", error); } } +#elif defined(__arm__) || defined(__arm64__) + if (!proc_is64bit_data(p)) { + arm_thread_state_t state = { + .pc = (int)wqstart_fnptr, + .r[0] = (unsigned int)addrs->self, + .r[1] = (unsigned int)kport, + .r[2] = (unsigned int)addrs->stack_bottom, + .r[3] = (unsigned int)kevent_list, + // will be pushed onto the stack as arg4/5 + .r[4] = (unsigned int)upcall_flags, + .r[5] = (unsigned int)kevent_count, + + .sp = (int)(addrs->stack_top) + }; + + int error = pthread_kern->thread_set_wq_state32(th, (thread_state_t)&state); + if (error != KERN_SUCCESS) { + panic(__func__ ": thread_set_wq_state failed: %d", error); + } + } else { +#if defined(__arm64__) + arm_thread_state64_t state = { + .pc = (uint64_t)wqstart_fnptr, + .x[0] = (uint64_t)addrs->self, + .x[1] = (uint64_t)kport, + .x[2] = (uint64_t)addrs->stack_bottom, + .x[3] = (uint64_t)kevent_list, + .x[4] = (uint64_t)upcall_flags, + .x[5] = (uint64_t)kevent_count, + + .sp = (uint64_t)((vm_offset_t)addrs->stack_top), + }; + + int error = pthread_kern->thread_set_wq_state64(th, (thread_state_t)&state); + if (error != KERN_SUCCESS) { + panic(__func__ ": thread_set_wq_state failed: %d", error); + } +#else /* defined(__arm64__) */ + panic("Shouldn't have a 64-bit thread on a 32-bit kernel..."); +#endif /* defined(__arm64__) */ + } #else #error setup_wqthread not defined for this architecture #endif } -static int -workq_kevent(proc_t p, struct workq_thread_addrs *th_addrs, int upcall_flags, +static inline int +workq_kevent(proc_t p, struct workq_thread_addrs *th_addrs, user_addr_t eventlist, int nevents, int kevent_flags, user_addr_t *kevent_list_out, int *kevent_count_out) { - bool workloop = upcall_flags & WQ_FLAG_THREAD_WORKLOOP; - int kevent_count = WQ_KEVENT_LIST_LEN; - user_addr_t kevent_list = th_addrs->self - WQ_KEVENT_LIST_LEN * sizeof(struct kevent_qos_s); - user_addr_t kevent_id_addr = kevent_list; - kqueue_id_t kevent_id = -1; int ret; - if (workloop) { - /* - * The kevent ID goes just below the kevent list. Sufficiently new - * userspace will know to look there. Old userspace will just - * ignore it. - */ - kevent_id_addr -= sizeof(kqueue_id_t); - } + user_addr_t kevent_list = th_addrs->self - + WQ_KEVENT_LIST_LEN * sizeof(struct kevent_qos_s); + user_addr_t data_buf = kevent_list - WQ_KEVENT_DATA_SIZE; + user_size_t data_available = WQ_KEVENT_DATA_SIZE; - user_addr_t kevent_data_buf = kevent_id_addr - WQ_KEVENT_DATA_SIZE; - user_size_t kevent_data_available = WQ_KEVENT_DATA_SIZE; - - if (workloop) { - kevent_flags |= KEVENT_FLAG_WORKLOOP; - ret = kevent_id_internal(p, &kevent_id, - eventlist, nevents, kevent_list, kevent_count, - kevent_data_buf, &kevent_data_available, - kevent_flags, &kevent_count); - copyout(&kevent_id, kevent_id_addr, sizeof(kevent_id)); - } else { - kevent_flags |= KEVENT_FLAG_WORKQ; - ret = kevent_qos_internal(p, -1, eventlist, nevents, kevent_list, - kevent_count, kevent_data_buf, &kevent_data_available, - kevent_flags, &kevent_count); - } + ret = pthread_kern->kevent_workq_internal(p, eventlist, nevents, + kevent_list, WQ_KEVENT_LIST_LEN, + data_buf, &data_available, + kevent_flags, kevent_count_out); // squash any errors into just empty output - if (ret != 0 || kevent_count == -1) { + if (ret != 0 || *kevent_count_out == -1) { *kevent_list_out = NULL; *kevent_count_out = 0; return ret; } - if (kevent_data_available == WQ_KEVENT_DATA_SIZE) { - workq_thread_set_top_addr(th_addrs, kevent_id_addr); - } else { - workq_thread_set_top_addr(th_addrs, - kevent_data_buf + kevent_data_available); - } - *kevent_count_out = kevent_count; + workq_thread_set_top_addr(th_addrs, data_buf + data_available); *kevent_list_out = kevent_list; return ret; } @@ -833,7 +895,7 @@ workq_kevent(proc_t p, struct workq_thread_addrs *th_addrs, int upcall_flags, * |pthread_t | th_stackaddr + DEFAULT_STACKSIZE + guardsize + PTHREAD_STACK_OFFSET * |kevent list| optionally - at most WQ_KEVENT_LIST_LEN events * |kevent data| optionally - at most WQ_KEVENT_DATA_SIZE bytes - * |stack gap | bottom aligned to 16 bytes, and at least as big as stack_gap_min + * |stack gap | bottom aligned to 16 bytes * | STACK | * | ⇓ | * | | @@ -880,8 +942,7 @@ workq_setup_thread(proc_t p, thread_t th, vm_map_t map, user_addr_t stackaddr, kevent_count = WORKQ_EXIT_THREAD_NKEVENT; } else if (upcall_flags & WQ_FLAG_THREAD_KEVENT) { unsigned int flags = KEVENT_FLAG_STACK_DATA | KEVENT_FLAG_IMMEDIATE; - workq_kevent(p, &th_addrs, upcall_flags, NULL, 0, flags, - &kevent_list, &kevent_count); + workq_kevent(p, &th_addrs, NULL, 0, flags, &kevent_list, &kevent_count); } workq_set_register_state(p, th, &th_addrs, kport, @@ -909,7 +970,7 @@ workq_handle_stack_events(proc_t p, thread_t th, vm_map_t map, unsigned int flags = KEVENT_FLAG_STACK_DATA | KEVENT_FLAG_IMMEDIATE | KEVENT_FLAG_PARKING; - error = workq_kevent(p, &th_addrs, upcall_flags, events, nevents, flags, + error = workq_kevent(p, &th_addrs, events, nevents, flags, &kevent_list, &kevent_count); if (error || kevent_count == 0) { diff --git a/kern/kern_synch.c b/kern/kern_synch.c index 7dabe41..583bea2 100644 --- a/kern/kern_synch.c +++ b/kern/kern_synch.c @@ -246,7 +246,7 @@ _kwq_use_turnstile(ksyn_wait_queue_t kwq) #define KW_UNLOCK_PREPOST_READLOCK 0x08 #define KW_UNLOCK_PREPOST_WRLOCK 0x20 -static int ksyn_wq_hash_lookup(user_addr_t uaddr, proc_t p, int flags, ksyn_wait_queue_t *kwq, struct pthhashhead **hashptr, uint64_t *object, uint64_t *offset); +static int ksyn_wq_hash_lookup(user_addr_t uaddr, proc_t p, int flags, ksyn_wait_queue_t *kwq, struct pthhashhead **hashptr, uint64_t object, uint64_t offset); static int ksyn_wqfind(user_addr_t mutex, uint32_t mgen, uint32_t ugen, uint32_t rw_wc, int flags, int wqtype , ksyn_wait_queue_t *wq); static void ksyn_wqrelease(ksyn_wait_queue_t mkwq, int qfreenow, int wqtype); static int ksyn_findobj(user_addr_t uaddr, uint64_t *objectp, uint64_t *offsetp); @@ -509,7 +509,7 @@ _kwq_handle_interrupted_wakeup(ksyn_wait_queue_t kwq, kwq_intr_type_t type, static void pthread_list_lock(void) { - lck_mtx_lock(pthread_list_mlock); + lck_mtx_lock_spin(pthread_list_mlock); } static void @@ -1553,23 +1553,17 @@ _pth_proc_hashinit(proc_t p) static int ksyn_wq_hash_lookup(user_addr_t uaddr, proc_t p, int flags, ksyn_wait_queue_t *out_kwq, struct pthhashhead **out_hashptr, - uint64_t *out_object, uint64_t *out_offset) + uint64_t object, uint64_t offset) { int res = 0; ksyn_wait_queue_t kwq; - uint64_t object = 0, offset = 0; struct pthhashhead *hashptr; if ((flags & PTHREAD_PSHARED_FLAGS_MASK) == PTHREAD_PROCESS_SHARED) { hashptr = pth_glob_hashtbl; - res = ksyn_findobj(uaddr, &object, &offset); - if (res == 0) { - LIST_FOREACH(kwq, &hashptr[object & pthhash], kw_hash) { - if (kwq->kw_object == object && kwq->kw_offset == offset) { - break; - } + LIST_FOREACH(kwq, &hashptr[object & pthhash], kw_hash) { + if (kwq->kw_object == object && kwq->kw_offset == offset) { + break; } - } else { - kwq = NULL; } } else { hashptr = pthread_kern->proc_get_pthhash(p); @@ -1580,8 +1574,6 @@ ksyn_wq_hash_lookup(user_addr_t uaddr, proc_t p, int flags, } } *out_kwq = kwq; - *out_object = object; - *out_offset = offset; *out_hashptr = hashptr; return res; } @@ -1692,7 +1684,7 @@ ksyn_wqfind(user_addr_t uaddr, uint32_t mgen, uint32_t ugen, uint32_t sgen, while (res == 0) { pthread_list_lock(); res = ksyn_wq_hash_lookup(uaddr, current_proc(), flags, &kwq, &hashptr, - &object, &offset); + object, offset); if (res != 0) { pthread_list_unlock(); break; diff --git a/libpthread.xcodeproj/project.pbxproj b/libpthread.xcodeproj/project.pbxproj index 1c4fd1a..5c193fd 100644 --- a/libpthread.xcodeproj/project.pbxproj +++ b/libpthread.xcodeproj/project.pbxproj @@ -18,13 +18,23 @@ name = Tests; productName = Tests; }; + C900AEA7215AF7170011B58C /* Introspection */ = { + isa = PBXAggregateTarget; + buildConfigurationList = C900AEAA215AF7170011B58C /* Build configuration list for PBXAggregateTarget "Introspection" */; + buildPhases = ( + ); + dependencies = ( + C900AEAE215AF7290011B58C /* PBXTargetDependency */, + ); + name = Introspection; + productName = Introspection; + }; C90E7AAC15DC3D3300A06D48 /* All */ = { isa = PBXAggregateTarget; buildConfigurationList = C90E7AAD15DC3D3300A06D48 /* Build configuration list for PBXAggregateTarget "All" */; buildPhases = ( ); dependencies = ( - 6E8C16821B14F11800C8987C /* PBXTargetDependency */, C90E7AB015DC3D3D00A06D48 /* PBXTargetDependency */, C04545BC1C58510F006A53B3 /* PBXTargetDependency */, C90E7AB215DC3D3D00A06D48 /* PBXTargetDependency */, @@ -49,7 +59,6 @@ buildPhases = ( ); dependencies = ( - 6E8C16841B14F11B00C8987C /* PBXTargetDependency */, C98832C615DEB44B00B3308E /* PBXTargetDependency */, C04545BE1C585487006A53B3 /* PBXTargetDependency */, C98832C815DEB44B00B3308E /* PBXTargetDependency */, @@ -59,6 +68,17 @@ name = Embedded; productName = Embedded; }; + E4B7FCA822000AF50010A840 /* libpthread_driverkit */ = { + isa = PBXAggregateTarget; + buildConfigurationList = E4B7FCAF22000AF50010A840 /* Build configuration list for PBXAggregateTarget "libpthread_driverkit" */; + buildPhases = ( + ); + dependencies = ( + E4B7FCA922000AF50010A840 /* PBXTargetDependency */, + ); + name = libpthread_driverkit; + productName = All; + }; /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ @@ -90,8 +110,6 @@ 6E8C16601B14F08A00C8987C /* pthread_cond_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5D615C9CECA0098ECD8 /* pthread_cond_legacy.c */; }; 6E8C16611B14F08A00C8987C /* pthread_mutex_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5D815C9CEEA0098ECD8 /* pthread_mutex_legacy.c */; }; 6E8C16621B14F08A00C8987C /* pthread_rwlock_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5DA15C9CEFA0098ECD8 /* pthread_rwlock_legacy.c */; }; - 6E8C16631B14F08A00C8987C /* pthread_support.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5DC15C9D16B0098ECD8 /* pthread_support.c */; }; - 6E8C16641B14F08A00C8987C /* thread_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325FC15B7513200270056 /* thread_setup.c */; }; 6E8C16651B14F08A00C8987C /* pthread_atfork.c in Sources */ = {isa = PBXBuildFile; fileRef = C90E7AB415DC40D900A06D48 /* pthread_atfork.c */; }; 6E8C16661B14F08A00C8987C /* pthread_asm.s in Sources */ = {isa = PBXBuildFile; fileRef = C99AD87D15DF04D10009A6F8 /* pthread_asm.s */; }; 6E8C16691B14F08A00C8987C /* qos.h in Headers */ = {isa = PBXBuildFile; fileRef = C9244C1A185FCFED00075748 /* qos.h */; }; @@ -116,9 +134,7 @@ 74E594951613AAF4006C417B /* pthread_cond.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F215B7513200270056 /* pthread_cond.c */; }; 74E594961613AAF4006C417B /* pthread_mutex.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F515B7513200270056 /* pthread_mutex.c */; }; 74E594971613AAF4006C417B /* pthread_rwlock.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F615B7513200270056 /* pthread_rwlock.c */; }; - 74E594981613AAF4006C417B /* pthread_support.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5DC15C9D16B0098ECD8 /* pthread_support.c */; }; 74E594991613AAF4006C417B /* pthread_tsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F815B7513200270056 /* pthread_tsd.c */; }; - 74E5949A1613AAF4006C417B /* thread_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325FC15B7513200270056 /* thread_setup.c */; }; 74E5949C1613AAF4006C417B /* pthread_atfork.c in Sources */ = {isa = PBXBuildFile; fileRef = C90E7AB415DC40D900A06D48 /* pthread_atfork.c */; }; 74E5949E1613AAF4006C417B /* pthread_asm.s in Sources */ = {isa = PBXBuildFile; fileRef = C99AD87D15DF04D10009A6F8 /* pthread_asm.s */; }; 74E594A61613AB10006C417B /* pthread_cancelable_cancel.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A1BF5215C9A9F5006BB313 /* pthread_cancelable_cancel.c */; }; @@ -134,9 +150,7 @@ C04545A81C584F4A006A53B3 /* pthread_cond.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F215B7513200270056 /* pthread_cond.c */; }; C04545A91C584F4A006A53B3 /* pthread_mutex.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F515B7513200270056 /* pthread_mutex.c */; }; C04545AB1C584F4A006A53B3 /* pthread_rwlock.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F615B7513200270056 /* pthread_rwlock.c */; }; - C04545AC1C584F4A006A53B3 /* pthread_support.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5DC15C9D16B0098ECD8 /* pthread_support.c */; }; C04545AD1C584F4A006A53B3 /* pthread_tsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F815B7513200270056 /* pthread_tsd.c */; }; - C04545AE1C584F4A006A53B3 /* thread_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325FC15B7513200270056 /* thread_setup.c */; }; C04545AF1C584F4A006A53B3 /* qos.c in Sources */ = {isa = PBXBuildFile; fileRef = C9244C1C1860D8EF00075748 /* qos.c */; }; C04545B01C584F4A006A53B3 /* pthread_cwd.c in Sources */ = {isa = PBXBuildFile; fileRef = 924D8EDE1C11832A002AC2BC /* pthread_cwd.c */; }; C04545B11C584F4A006A53B3 /* pthread_atfork.c in Sources */ = {isa = PBXBuildFile; fileRef = C90E7AB415DC40D900A06D48 /* pthread_atfork.c */; }; @@ -146,9 +160,7 @@ C90E7AA615DC3C9D00A06D48 /* pthread_cond.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F215B7513200270056 /* pthread_cond.c */; }; C90E7AA715DC3C9D00A06D48 /* pthread_mutex.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F515B7513200270056 /* pthread_mutex.c */; }; C90E7AA815DC3C9D00A06D48 /* pthread_rwlock.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F615B7513200270056 /* pthread_rwlock.c */; }; - C90E7AA915DC3C9D00A06D48 /* pthread_support.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5DC15C9D16B0098ECD8 /* pthread_support.c */; }; C90E7AAA15DC3C9D00A06D48 /* pthread_tsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F815B7513200270056 /* pthread_tsd.c */; }; - C90E7AAB15DC3C9D00A06D48 /* thread_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325FC15B7513200270056 /* thread_setup.c */; }; C90E7AB815DC40D900A06D48 /* pthread_atfork.c in Sources */ = {isa = PBXBuildFile; fileRef = C90E7AB415DC40D900A06D48 /* pthread_atfork.c */; }; C90E7AB915DC40D900A06D48 /* pthread_atfork.c in Sources */ = {isa = PBXBuildFile; fileRef = C90E7AB415DC40D900A06D48 /* pthread_atfork.c */; }; C9153096167ACC2B006BB094 /* private.h in Headers */ = {isa = PBXBuildFile; fileRef = C9153095167ACC22006BB094 /* private.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -158,15 +170,12 @@ C9244C1D1860D8EF00075748 /* qos.c in Sources */ = {isa = PBXBuildFile; fileRef = C9244C1C1860D8EF00075748 /* qos.c */; }; C9244C1E1860D96D00075748 /* qos.c in Sources */ = {isa = PBXBuildFile; fileRef = C9244C1C1860D8EF00075748 /* qos.c */; }; C9244C1F1860D96E00075748 /* qos.c in Sources */ = {isa = PBXBuildFile; fileRef = C9244C1C1860D8EF00075748 /* qos.c */; }; - C948FCF715D1D1E100180BF5 /* thread_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325FC15B7513200270056 /* thread_setup.c */; }; C975D5D715C9CECA0098ECD8 /* pthread_cond_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5D615C9CECA0098ECD8 /* pthread_cond_legacy.c */; }; C975D5D915C9CEEA0098ECD8 /* pthread_mutex_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5D815C9CEEA0098ECD8 /* pthread_mutex_legacy.c */; }; C975D5DB15C9CEFA0098ECD8 /* pthread_rwlock_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5DA15C9CEFA0098ECD8 /* pthread_rwlock_legacy.c */; }; - C975D5DD15C9D16B0098ECD8 /* pthread_support.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5DC15C9D16B0098ECD8 /* pthread_support.c */; }; C98C95D918FF1F4E005654FB /* spawn.h in Headers */ = {isa = PBXBuildFile; fileRef = C98C95D818FF1F4E005654FB /* spawn.h */; settings = {ATTRIBUTES = (Public, ); }; }; C99AD87B15DEC4BC0009A6F8 /* posix_sched.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F015B7513200270056 /* posix_sched.h */; settings = {ATTRIBUTES = (Private, ); }; }; C99AD87C15DEC5290009A6F8 /* spinlock_private.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A325F715B7513200270056 /* spinlock_private.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C99AD87F15DF04D10009A6F8 /* pthread_asm.s in Sources */ = {isa = PBXBuildFile; fileRef = C99AD87D15DF04D10009A6F8 /* pthread_asm.s */; }; C99AD88015E2D8B50009A6F8 /* pthread_asm.s in Sources */ = {isa = PBXBuildFile; fileRef = C99AD87D15DF04D10009A6F8 /* pthread_asm.s */; }; C9A1BF4715C9A578006BB313 /* pthread.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325FA15B7513200270056 /* pthread.c */; }; C9A1BF4815C9A578006BB313 /* pthread_cancelable.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F115B7513200270056 /* pthread_cancelable.c */; }; @@ -192,9 +201,7 @@ E41505D61E818BEB00F243FB /* pthread_cond.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F215B7513200270056 /* pthread_cond.c */; }; E41505D71E818BEB00F243FB /* pthread_mutex.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F515B7513200270056 /* pthread_mutex.c */; }; E41505D91E818BEB00F243FB /* pthread_rwlock.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F615B7513200270056 /* pthread_rwlock.c */; }; - E41505DA1E818BEB00F243FB /* pthread_support.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5DC15C9D16B0098ECD8 /* pthread_support.c */; }; E41505DB1E818BEB00F243FB /* pthread_tsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F815B7513200270056 /* pthread_tsd.c */; }; - E41505DC1E818BEB00F243FB /* thread_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325FC15B7513200270056 /* thread_setup.c */; }; E41505DD1E818BEB00F243FB /* qos.c in Sources */ = {isa = PBXBuildFile; fileRef = C9244C1C1860D8EF00075748 /* qos.c */; }; E41505DE1E818BEB00F243FB /* pthread_cwd.c in Sources */ = {isa = PBXBuildFile; fileRef = 924D8EDE1C11832A002AC2BC /* pthread_cwd.c */; }; E41505DF1E818BEB00F243FB /* pthread_atfork.c in Sources */ = {isa = PBXBuildFile; fileRef = C90E7AB415DC40D900A06D48 /* pthread_atfork.c */; }; @@ -208,9 +215,7 @@ E4F449921E82C1F000A7FB9A /* pthread_cond.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F215B7513200270056 /* pthread_cond.c */; }; E4F449931E82C1F000A7FB9A /* pthread_mutex.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F515B7513200270056 /* pthread_mutex.c */; }; E4F449941E82C1F000A7FB9A /* pthread_rwlock.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F615B7513200270056 /* pthread_rwlock.c */; }; - E4F449951E82C1F000A7FB9A /* pthread_support.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5DC15C9D16B0098ECD8 /* pthread_support.c */; }; E4F449961E82C1F000A7FB9A /* pthread_tsd.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325F815B7513200270056 /* pthread_tsd.c */; }; - E4F449971E82C1F000A7FB9A /* thread_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325FC15B7513200270056 /* thread_setup.c */; }; E4F449981E82C1F000A7FB9A /* qos.c in Sources */ = {isa = PBXBuildFile; fileRef = C9244C1C1860D8EF00075748 /* qos.c */; }; E4F449991E82C1F000A7FB9A /* pthread_cwd.c in Sources */ = {isa = PBXBuildFile; fileRef = 924D8EDE1C11832A002AC2BC /* pthread_cwd.c */; }; E4F4499A1E82C1F000A7FB9A /* pthread_atfork.c in Sources */ = {isa = PBXBuildFile; fileRef = C90E7AB415DC40D900A06D48 /* pthread_atfork.c */; }; @@ -229,8 +234,6 @@ E4F449B51E82D03500A7FB9A /* pthread_cond_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5D615C9CECA0098ECD8 /* pthread_cond_legacy.c */; }; E4F449B61E82D03500A7FB9A /* pthread_mutex_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5D815C9CEEA0098ECD8 /* pthread_mutex_legacy.c */; }; E4F449B71E82D03500A7FB9A /* pthread_rwlock_legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5DA15C9CEFA0098ECD8 /* pthread_rwlock_legacy.c */; }; - E4F449B81E82D03500A7FB9A /* pthread_support.c in Sources */ = {isa = PBXBuildFile; fileRef = C975D5DC15C9D16B0098ECD8 /* pthread_support.c */; }; - E4F449B91E82D03500A7FB9A /* thread_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = C9A325FC15B7513200270056 /* thread_setup.c */; }; E4F449BA1E82D03500A7FB9A /* pthread_atfork.c in Sources */ = {isa = PBXBuildFile; fileRef = C90E7AB415DC40D900A06D48 /* pthread_atfork.c */; }; E4F449BB1E82D03500A7FB9A /* pthread_asm.s in Sources */ = {isa = PBXBuildFile; fileRef = C99AD87D15DF04D10009A6F8 /* pthread_asm.s */; }; E4F449BE1E82D03500A7FB9A /* qos.h in Headers */ = {isa = PBXBuildFile; fileRef = C9244C1A185FCFED00075748 /* qos.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -251,20 +254,6 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 6E8C16811B14F11800C8987C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C9A325D915B7347000270056 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6E8C16511B14F08A00C8987C; - remoteInfo = "libsystem_pthread.dylib introspection"; - }; - 6E8C16831B14F11B00C8987C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = C9A325D915B7347000270056 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 6E8C16511B14F08A00C8987C; - remoteInfo = "libsystem_pthread.dylib introspection"; - }; 74E594AA1613AD7F006C417B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = C9A325D915B7347000270056 /* Project object */; @@ -293,6 +282,13 @@ remoteGlobalIDString = C04545A21C584F4A006A53B3; remoteInfo = "libpthread.a generic"; }; + C900AEAD215AF7290011B58C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C9A325D915B7347000270056 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6E8C16511B14F08A00C8987C; + remoteInfo = "libsystem_pthread introspection"; + }; C90E7AAF15DC3D3D00A06D48 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = C9A325D915B7347000270056 /* Project object */; @@ -335,6 +331,13 @@ remoteGlobalIDString = C90E7A9E15DC3C3800A06D48; remoteInfo = libpthread.a; }; + E4B7FCAA22000AF50010A840 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C9A325D915B7347000270056 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C9A325E115B7347000270056; + remoteInfo = Libpthread; + }; E4F4498A1E825D2B00A7FB9A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = C9A325D915B7347000270056 /* Project object */; @@ -431,7 +434,6 @@ C975D5D615C9CECA0098ECD8 /* pthread_cond_legacy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pthread_cond_legacy.c; sourceTree = ""; }; C975D5D815C9CEEA0098ECD8 /* pthread_mutex_legacy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pthread_mutex_legacy.c; sourceTree = ""; }; C975D5DA15C9CEFA0098ECD8 /* pthread_rwlock_legacy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pthread_rwlock_legacy.c; sourceTree = ""; }; - C975D5DC15C9D16B0098ECD8 /* pthread_support.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pthread_support.c; sourceTree = ""; }; C979E9FB18A1BC2A000951E5 /* kern_trace.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = kern_trace.h; sourceTree = ""; }; C979E9FC18A2BF2C000951E5 /* install-codes.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "install-codes.sh"; sourceTree = ""; }; C98005141899BD2000368E4D /* workqueue_internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = workqueue_internal.h; sourceTree = ""; }; @@ -455,7 +457,6 @@ C9A325F815B7513200270056 /* pthread_tsd.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pthread_tsd.c; sourceTree = ""; }; C9A325F915B7513200270056 /* workqueue_private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = workqueue_private.h; sourceTree = ""; }; C9A325FA15B7513200270056 /* pthread.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pthread.c; sourceTree = ""; }; - C9A325FC15B7513200270056 /* thread_setup.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = thread_setup.c; sourceTree = ""; }; C9A325FE15B7513700270056 /* pthread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pthread.h; sourceTree = ""; }; C9A325FF15B7513700270056 /* pthread_impl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pthread_impl.h; sourceTree = ""; }; C9A3260015B7513700270056 /* pthread_spis.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pthread_spis.h; sourceTree = ""; }; @@ -692,10 +693,8 @@ C9A325F515B7513200270056 /* pthread_mutex.c */, 6E5869CA20C9043200F1CB75 /* pthread_dependency.c */, C9A325F615B7513200270056 /* pthread_rwlock.c */, - C975D5DC15C9D16B0098ECD8 /* pthread_support.c */, C9A325F815B7513200270056 /* pthread_tsd.c */, C9244C1C1860D8EF00075748 /* qos.c */, - C9A325FC15B7513200270056 /* thread_setup.c */, E4943AAA1E80BE1F00D2A961 /* resolver */, C9A1BF5115C9A8B7006BB313 /* variants */, ); @@ -1000,7 +999,6 @@ C90E7A9B15DC3C3800A06D48 /* Sources */, C90E7A9C15DC3C3800A06D48 /* Frameworks */, C90E7A9D15DC3C3800A06D48 /* Headers */, - C04545891C5844F8006A53B3 /* Symlink libpthread_dyld.a to libpthread.a */, ); buildRules = ( ); @@ -1112,7 +1110,7 @@ C9A325D915B7347000270056 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0900; + LastUpgradeCheck = 1100; ORGANIZATIONNAME = ""; TargetAttributes = { 92799B441B96A5FD00861404 = { @@ -1139,6 +1137,8 @@ C91D01B5162892FF0002E29A /* Kext */, C98832C115DEB44000B3308E /* Embedded */, 92799B441B96A5FD00861404 /* Tests */, + C900AEA7215AF7170011B58C /* Introspection */, + E4B7FCA822000AF50010A840 /* libpthread_driverkit */, C9A325E115B7347000270056 /* libsystem_pthread */, E4F449A41E82D03500A7FB9A /* libsystem_pthread noresolver */, 6E8C16511B14F08A00C8987C /* libsystem_pthread introspection */, @@ -1181,22 +1181,6 @@ shellScript = "dtrace -h -C -s \"${SCRIPT_INPUT_FILE_0}\" -o \"${SCRIPT_OUTPUT_FILE_0}\""; showEnvVarsInLog = 0; }; - C04545891C5844F8006A53B3 /* Symlink libpthread_dyld.a to libpthread.a */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 8; - files = ( - ); - inputPaths = ( - "$(SRCROOT)/xcodescripts/run-on-install.sh", - ); - name = "Symlink libpthread_dyld.a to libpthread.a"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 1; - shellPath = "/bin/bash -e -x"; - shellScript = ". \"${SCRIPT_INPUT_FILE_0}\" /bin/ln -sf libpthread_dyld.a \"${DSTROOT}${INSTALL_PATH}/libpthread.a\""; - showEnvVarsInLog = 0; - }; C04545BA1C585034006A53B3 /* Symlink libpthread.a to the loaderd path */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 8; @@ -1228,7 +1212,7 @@ ); runOnlyForDeploymentPostprocessing = 1; shellPath = "/bin/bash -e -x"; - shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-codes.sh"; + shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-codes.sh\n"; showEnvVarsInLog = 0; }; C9A960B518452C1800AE10C8 /* Install lldbmacros */ = { @@ -1243,7 +1227,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = "/bin/bash -e -x"; - shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-lldbmacros.sh"; + shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-lldbmacros.sh\n"; showEnvVarsInLog = 0; }; C9D70EBD167AC76700D52713 /* Symlink Old Header Location */ = { @@ -1259,7 +1243,7 @@ ); runOnlyForDeploymentPostprocessing = 1; shellPath = "/bin/bash -e -x"; - shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-symlinks.sh"; + shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-symlinks.sh\n"; showEnvVarsInLog = 0; }; C9DCA2A215DC4F3500D057E2 /* Install Manpages */ = { @@ -1275,7 +1259,7 @@ ); runOnlyForDeploymentPostprocessing = 1; shellPath = "/bin/bash -e -x"; - shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-manpages.sh"; + shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-manpages.sh\n"; showEnvVarsInLog = 0; }; E41505E31E818BEB00F243FB /* Symlink normal variant */ = { @@ -1386,7 +1370,7 @@ ); runOnlyForDeploymentPostprocessing = 1; shellPath = "/bin/bash -e -x"; - shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-sys-headers.sh"; + shellScript = ". \"$PROJECT_DIR\"/xcodescripts/install-sys-headers.sh\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -1411,8 +1395,6 @@ 6E8C16601B14F08A00C8987C /* pthread_cond_legacy.c in Sources */, 6E8C16611B14F08A00C8987C /* pthread_mutex_legacy.c in Sources */, 6E8C16621B14F08A00C8987C /* pthread_rwlock_legacy.c in Sources */, - 6E8C16631B14F08A00C8987C /* pthread_support.c in Sources */, - 6E8C16641B14F08A00C8987C /* thread_setup.c in Sources */, 6E8C16651B14F08A00C8987C /* pthread_atfork.c in Sources */, 6E5869CD20C9043B00F1CB75 /* pthread_dependency.c in Sources */, 6E8C16661B14F08A00C8987C /* pthread_asm.s in Sources */, @@ -1431,9 +1413,7 @@ 74E594951613AAF4006C417B /* pthread_cond.c in Sources */, 74E594961613AAF4006C417B /* pthread_mutex.c in Sources */, 74E594971613AAF4006C417B /* pthread_rwlock.c in Sources */, - 74E594981613AAF4006C417B /* pthread_support.c in Sources */, 74E594991613AAF4006C417B /* pthread_tsd.c in Sources */, - 74E5949A1613AAF4006C417B /* thread_setup.c in Sources */, C9244C1F1860D96E00075748 /* qos.c in Sources */, 924D8EDF1C11833D002AC2BC /* pthread_cwd.c in Sources */, 74E5949C1613AAF4006C417B /* pthread_atfork.c in Sources */, @@ -1453,9 +1433,7 @@ C04545A81C584F4A006A53B3 /* pthread_cond.c in Sources */, C04545A91C584F4A006A53B3 /* pthread_mutex.c in Sources */, C04545AB1C584F4A006A53B3 /* pthread_rwlock.c in Sources */, - C04545AC1C584F4A006A53B3 /* pthread_support.c in Sources */, C04545AD1C584F4A006A53B3 /* pthread_tsd.c in Sources */, - C04545AE1C584F4A006A53B3 /* thread_setup.c in Sources */, C04545AF1C584F4A006A53B3 /* qos.c in Sources */, C04545B01C584F4A006A53B3 /* pthread_cwd.c in Sources */, C04545B11C584F4A006A53B3 /* pthread_atfork.c in Sources */, @@ -1475,12 +1453,9 @@ C90E7AA715DC3C9D00A06D48 /* pthread_mutex.c in Sources */, 6E5869D120C9043D00F1CB75 /* pthread_dependency.c in Sources */, C90E7AA815DC3C9D00A06D48 /* pthread_rwlock.c in Sources */, - C90E7AA915DC3C9D00A06D48 /* pthread_support.c in Sources */, C90E7AAA15DC3C9D00A06D48 /* pthread_tsd.c in Sources */, - C90E7AAB15DC3C9D00A06D48 /* thread_setup.c in Sources */, 924D8EE01C11833D002AC2BC /* pthread_cwd.c in Sources */, C90E7AB915DC40D900A06D48 /* pthread_atfork.c in Sources */, - C99AD87F15DF04D10009A6F8 /* pthread_asm.s in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1502,8 +1477,6 @@ C975D5D715C9CECA0098ECD8 /* pthread_cond_legacy.c in Sources */, C975D5D915C9CEEA0098ECD8 /* pthread_mutex_legacy.c in Sources */, C975D5DB15C9CEFA0098ECD8 /* pthread_rwlock_legacy.c in Sources */, - C975D5DD15C9D16B0098ECD8 /* pthread_support.c in Sources */, - C948FCF715D1D1E100180BF5 /* thread_setup.c in Sources */, C90E7AB815DC40D900A06D48 /* pthread_atfork.c in Sources */, 6E5869CB20C9043200F1CB75 /* pthread_dependency.c in Sources */, C99AD88015E2D8B50009A6F8 /* pthread_asm.s in Sources */, @@ -1532,9 +1505,7 @@ E41505D61E818BEB00F243FB /* pthread_cond.c in Sources */, E41505D71E818BEB00F243FB /* pthread_mutex.c in Sources */, E41505D91E818BEB00F243FB /* pthread_rwlock.c in Sources */, - E41505DA1E818BEB00F243FB /* pthread_support.c in Sources */, E41505DB1E818BEB00F243FB /* pthread_tsd.c in Sources */, - E41505DC1E818BEB00F243FB /* thread_setup.c in Sources */, E41505DD1E818BEB00F243FB /* qos.c in Sources */, E41505DE1E818BEB00F243FB /* pthread_cwd.c in Sources */, E41505DF1E818BEB00F243FB /* pthread_atfork.c in Sources */, @@ -1554,9 +1525,7 @@ E4F449921E82C1F000A7FB9A /* pthread_cond.c in Sources */, E4F449931E82C1F000A7FB9A /* pthread_mutex.c in Sources */, E4F449941E82C1F000A7FB9A /* pthread_rwlock.c in Sources */, - E4F449951E82C1F000A7FB9A /* pthread_support.c in Sources */, E4F449961E82C1F000A7FB9A /* pthread_tsd.c in Sources */, - E4F449971E82C1F000A7FB9A /* thread_setup.c in Sources */, E4F449981E82C1F000A7FB9A /* qos.c in Sources */, E4F449991E82C1F000A7FB9A /* pthread_cwd.c in Sources */, E4F4499A1E82C1F000A7FB9A /* pthread_atfork.c in Sources */, @@ -1582,8 +1551,6 @@ E4F449B51E82D03500A7FB9A /* pthread_cond_legacy.c in Sources */, E4F449B61E82D03500A7FB9A /* pthread_mutex_legacy.c in Sources */, E4F449B71E82D03500A7FB9A /* pthread_rwlock_legacy.c in Sources */, - E4F449B81E82D03500A7FB9A /* pthread_support.c in Sources */, - E4F449B91E82D03500A7FB9A /* thread_setup.c in Sources */, E4F449BA1E82D03500A7FB9A /* pthread_atfork.c in Sources */, 6E5869CC20C9043B00F1CB75 /* pthread_dependency.c in Sources */, E4F449BB1E82D03500A7FB9A /* pthread_asm.s in Sources */, @@ -1593,16 +1560,6 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 6E8C16821B14F11800C8987C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6E8C16511B14F08A00C8987C /* libsystem_pthread introspection */; - targetProxy = 6E8C16811B14F11800C8987C /* PBXContainerItemProxy */; - }; - 6E8C16841B14F11B00C8987C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 6E8C16511B14F08A00C8987C /* libsystem_pthread introspection */; - targetProxy = 6E8C16831B14F11B00C8987C /* PBXContainerItemProxy */; - }; 74E594AB1613AD7F006C417B /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 74E594911613AAF4006C417B /* libpthread eOS */; @@ -1623,6 +1580,11 @@ target = C04545A21C584F4A006A53B3 /* libpthread generic */; targetProxy = C04545BD1C585487006A53B3 /* PBXContainerItemProxy */; }; + C900AEAE215AF7290011B58C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6E8C16511B14F08A00C8987C /* libsystem_pthread introspection */; + targetProxy = C900AEAD215AF7290011B58C /* PBXContainerItemProxy */; + }; C90E7AB015DC3D3D00A06D48 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = C9A325E115B7347000270056 /* libsystem_pthread */; @@ -1653,6 +1615,11 @@ target = C90E7A9E15DC3C3800A06D48 /* libpthread dyld */; targetProxy = C98832C715DEB44B00B3308E /* PBXContainerItemProxy */; }; + E4B7FCA922000AF50010A840 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C9A325E115B7347000270056 /* libsystem_pthread */; + targetProxy = E4B7FCAA22000AF50010A840 /* PBXContainerItemProxy */; + }; E4F4498B1E825D2B00A7FB9A /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = E41505D01E818BEB00F243FB /* libpthread mp resolved */; @@ -1791,6 +1758,18 @@ }; name = Release; }; + C900AEAB215AF7170011B58C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; + C900AEAC215AF7170011B58C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; C90E7AA015DC3C3800A06D48 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = C04545B91C584F8B006A53B3 /* static.xcconfig */; @@ -1860,6 +1839,20 @@ }; name = Debug; }; + E4B7FCB022000AF50010A840 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + E4B7FCB122000AF50010A840 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; E4F4499E1E82C1F000A7FB9A /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = E41505E81E818D4D00F243FB /* resolved.xcconfig */; @@ -1947,6 +1940,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + C900AEAA215AF7170011B58C /* Build configuration list for PBXAggregateTarget "Introspection" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C900AEAB215AF7170011B58C /* Release */, + C900AEAC215AF7170011B58C /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; C90E7AA115DC3C3800A06D48 /* Build configuration list for PBXNativeTarget "libpthread dyld" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -2019,6 +2021,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + E4B7FCAF22000AF50010A840 /* Build configuration list for PBXAggregateTarget "libpthread_driverkit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E4B7FCB022000AF50010A840 /* Release */, + E4B7FCB122000AF50010A840 /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; E4F4499D1E82C1F000A7FB9A /* Build configuration list for PBXNativeTarget "libpthread armv81 resolved" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/man/pthread_setname_np.3 b/man/pthread_setname_np.3 index 13a9108..502e936 100644 --- a/man/pthread_setname_np.3 +++ b/man/pthread_setname_np.3 @@ -36,7 +36,7 @@ .Fn pthread_setname_np "const char *name" .Sh DESCRIPTION The -.Fn pthread_set_name_np +.Fn pthread_setname_np function sets the internal name for the calling thread to string value specified by .Fa name argument. diff --git a/private/private.h b/private/private.h index b321442..33d5e25 100644 --- a/private/private.h +++ b/private/private.h @@ -63,6 +63,9 @@ struct _libpthread_functions { * If this is used on a workqueue (dispatch) thread, it MUST be unset with * pthread_fchdir_np(-1) before returning. * + * posix_spawn_file_actions_addchdir_np is a better approach if this call would + * only be used to spawn a new process with a given working directory. + * * @param path * The path of the new working directory. * @@ -70,7 +73,7 @@ struct _libpthread_functions { * 0 upon success, -1 upon error and errno is set. */ __API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0)) -int pthread_chdir_np(char *path); +int pthread_chdir_np(const char *path); /*! * @function pthread_fchdir_np @@ -83,6 +86,9 @@ int pthread_chdir_np(char *path); * directory fd. If this is used on a workqueue (dispatch) thread, it MUST be * unset with pthread_fchdir_np(-1) before returning. * + * posix_spawn_file_actions_addfchdir_np is a better approach if this call would + * only be used to spawn a new process with a given working directory. + * * @param fd * A file descriptor to the new working directory. Pass -1 to unset the * per-thread working directory. @@ -96,6 +102,9 @@ int pthread_fchdir_np(int fd); __API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) int pthread_attr_setcpupercent_np(pthread_attr_t * __restrict, int, unsigned long); +__API_AVAILABLE(macos(10.15), ios(13.0), tvos(13.0), watchos(6.0)) +int pthread_current_stack_contains_np(const void *, size_t); + #ifdef _os_tsd_get_base #ifdef __LP64__ diff --git a/private/tsd_private.h b/private/tsd_private.h index 4b48d58..e83ea66 100644 --- a/private/tsd_private.h +++ b/private/tsd_private.h @@ -225,6 +225,13 @@ #define __PTK_FRAMEWORK_SWIFT_KEY8 108 #define __PTK_FRAMEWORK_SWIFT_KEY9 109 +/* Keys 190 - 194 are for the use of PerfUtils */ +#define __PTK_PERF_UTILS_KEY0 190 +#define __PTK_PERF_UTILS_KEY1 191 +#define __PTK_PERF_UTILS_KEY2 192 +#define __PTK_PERF_UTILS_KEY3 193 +#define __PTK_PERF_UTILS_KEY4 194 + /* Keys 210 - 229 are for libSystem usage within the iOS Simulator */ /* They are offset from their corresponding libSystem keys by 200 */ #define __PTK_LIBC_SIM_LOCALE_KEY 210 diff --git a/private/workqueue_private.h b/private/workqueue_private.h index 9cd0e95..11b0e5e 100644 --- a/private/workqueue_private.h +++ b/private/workqueue_private.h @@ -74,6 +74,23 @@ typedef void (*pthread_workqueue_function_kevent_t)(void **events, int *nevents) typedef void (*pthread_workqueue_function_workloop_t)(uint64_t *workloop_id, void **events, int *nevents); +#define PTHREAD_WORKQUEUE_CONFIG_VERSION 2 +#define PTHREAD_WORKQUEUE_CONFIG_MIN_SUPPORTED_VERSION 1 +#define PTHREAD_WORKQUEUE_CONFIG_SUPPORTED_FLAGS 0 +struct pthread_workqueue_config { + uint32_t flags; + uint32_t version; + pthread_workqueue_function_kevent_t kevent_cb; + pthread_workqueue_function_workloop_t workloop_cb; + pthread_workqueue_function2_t workq_cb; + uint64_t queue_serialno_offs; + uint64_t queue_label_offs; +}; + +__API_AVAILABLE(macos(10.15), ios(13.0)) +int +pthread_workqueue_setup(struct pthread_workqueue_config *cfg, size_t cfg_size); + // Initialises the pthread workqueue subsystem, passing the new-style callback prototype, // the dispatchoffset and an unused flags field. __API_AVAILABLE(macos(10.10), ios(8.0)) diff --git a/pthread/pthread.h b/pthread/pthread.h index f5fdff6..a042c82 100644 --- a/pthread/pthread.h +++ b/pthread/pthread.h @@ -188,7 +188,7 @@ __BEGIN_DECLS #define PTHREAD_MUTEX_INITIALIZER {_PTHREAD_MUTEX_SIG_init, {0}} /* */ -#if ((__MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)) +#if ((__MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) || (__IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000)) || defined(__DRIVERKIT_VERSION_MIN_REQUIRED) # if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE) # define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER {_PTHREAD_ERRORCHECK_MUTEX_SIG_init, {0}} # define PTHREAD_RECURSIVE_MUTEX_INITIALIZER {_PTHREAD_RECURSIVE_MUTEX_SIG_init, {0}} diff --git a/src/internal.h b/src/internal.h index e8cc161..daa2179 100644 --- a/src/internal.h +++ b/src/internal.h @@ -81,6 +81,7 @@ typedef struct _pthread_attr_t pthread_attr_t; #error Unsupported target #endif + #define PTHREAD_INTERNAL_CRASH(c, x) do { \ _os_set_crash_log_cause_and_message((c), \ "BUG IN LIBPTHREAD: " x); \ @@ -160,7 +161,14 @@ PTHREAD_NOEXPORT extern uint64_t _pthread_debugstart; #define _INTERNAL_POSIX_THREAD_KEYS_END 768 #endif +#if defined(__arm64__) +/* Pull the pthread_t into the same page as the top of the stack so we dirty one less page. + * The _pthread struct at the top of the stack shouldn't be page-aligned + */ +#define PTHREAD_T_OFFSET (12*1024) +#else #define PTHREAD_T_OFFSET 0 +#endif #define MAXTHREADNAMESIZE 64 #define _PTHREAD_T @@ -192,6 +200,7 @@ typedef struct _pthread { // MACH_PORT_DEAD if the thread exited uint32_t tl_exit_gate; struct sched_param tl_param; + void *__unused_padding; // // Fields protected by pthread_t::lock @@ -204,18 +213,16 @@ typedef struct _pthread { schedset:1, wqthread:1, wqkillset:1, - wqoutsideqos:1, - __flags_pad:3; + __flags_pad:4; char pthread_name[MAXTHREADNAMESIZE]; // includes NUL [aligned] void *(*fun)(void *); // thread start routine - void *wq_kqid_ptr; // wqthreads (workloop) void *arg; // thread start routine argument int wq_nevents; // wqthreads (workloop / kevent) - uint16_t wq_retop; // wqthreads - uint8_t cancel_state; // whether the thread can be canceled [atomic] + bool wq_outsideqos; uint8_t canceled; // 4597450 set if conformant cancelation happened + uint16_t cancel_state; // whether the thread can be canceled [atomic] errno_t cancel_error; errno_t err_no; // thread-local errno @@ -467,7 +474,6 @@ _pthread_selfid_direct(void) #define _PTHREAD_CANCEL_STATE_MASK 0x01 #define _PTHREAD_CANCEL_TYPE_MASK 0x02 #define _PTHREAD_CANCEL_PENDING 0x10 /* pthread_cancel() has been called for this thread */ -#define _PTHREAD_CANCEL_INITIALIZED 0x20 /* the thread in the list is properly initialized */ extern boolean_t swtch_pri(int); @@ -510,14 +516,6 @@ PTHREAD_NOEXPORT void _pthread_deallocate(pthread_t t, bool from_mach_thread); -PTHREAD_NORETURN PTHREAD_NOEXPORT -void -__pthread_abort(void); - -PTHREAD_NORETURN PTHREAD_NOEXPORT -void -__pthread_abort_reason(const char *fmt, ...) __printflike(1,2); - PTHREAD_NOEXPORT thread_qos_t _pthread_qos_class_to_thread_qos(qos_class_t qos); @@ -538,7 +536,7 @@ PTHREAD_EXPORT void _pthread_start(pthread_t self, mach_port_t kport, void *(*fun)(void *), void * funarg, size_t stacksize, unsigned int flags); -PTHREAD_NORETURN PTHREAD_EXPORT +PTHREAD_EXPORT void _pthread_wqthread(pthread_t self, mach_port_t kport, void *stackaddr, void *keventlist, int flags, int nkevents); @@ -596,11 +594,16 @@ _pthread_set_kernel_thread(pthread_t t, mach_port_t p) t->tsd[_PTHREAD_TSD_SLOT_MACH_THREAD_SELF] = p; } -#define PTHREAD_ABORT(f,...) __pthread_abort_reason( \ - "%s:%s:%u: " f, __FILE__, __func__, __LINE__, ## __VA_ARGS__) - -#define PTHREAD_ASSERT(b) \ - do { if (!(b)) PTHREAD_ABORT("failed assertion `%s'", #b); } while (0) +#ifdef DEBUG +#define PTHREAD_DEBUG_ASSERT(b) \ + do { \ + if (os_unlikely(!(b))) { \ + PTHREAD_INTERNAL_CRASH(0, "Assertion failed: " #b); \ + } \ + } while (0) +#else +#define PTHREAD_DEBUG_ASSERT(b) ((void)0) +#endif #include #include @@ -690,21 +693,13 @@ _pthread_validate_thread_and_list_lock(pthread_t thread) { pthread_t p; if (thread == NULL) return false; -loop: _PTHREAD_LOCK(_pthread_list_lock); TAILQ_FOREACH(p, &__pthread_head, tl_plist) { if (p != thread) continue; - int state = os_atomic_load(&p->cancel_state, relaxed); - if (os_likely(state & _PTHREAD_CANCEL_INITIALIZED)) { - if (os_unlikely(p->sig != _PTHREAD_SIG)) { - PTHREAD_CLIENT_CRASH(0, "pthread_t was corrupted"); - } - return true; + if (os_unlikely(p->sig != _PTHREAD_SIG)) { + PTHREAD_CLIENT_CRASH(0, "pthread_t was corrupted"); } - _PTHREAD_UNLOCK(_pthread_list_lock); - thread_switch(_pthread_kernel_thread(p), - SWITCH_OPTION_OSLOCK_DEPRESS, 1); - goto loop; + return true; } _PTHREAD_UNLOCK(_pthread_list_lock); diff --git a/src/pthread.c b/src/pthread.c index 3c3ea6a..8eca496 100644 --- a/src/pthread.c +++ b/src/pthread.c @@ -75,11 +75,19 @@ #include #define __APPLE_API_PRIVATE #include +#if __has_include() +#include +#endif // __has_include() #include <_simple.h> #include #include +#include + +// Defined in libsyscall; initialized in libmalloc +extern malloc_logger_t *__syscall_logger; + extern int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen); extern void __exit(int) __attribute__((noreturn)); @@ -203,11 +211,12 @@ __pthread_invalid_workloopfunction(uint64_t *workloop_id, void **events, int *ne static pthread_workqueue_function2_t __libdispatch_workerfunction; static pthread_workqueue_function_kevent_t __libdispatch_keventfunction = &__pthread_invalid_keventfunction; static pthread_workqueue_function_workloop_t __libdispatch_workloopfunction = &__pthread_invalid_workloopfunction; -static int __libdispatch_offset; static int __pthread_supported_features; // supported feature set #if defined(__i386__) || defined(__x86_64__) static mach_vm_address_t __pthread_stack_hint = 0xB0000000; +#elif defined(__arm__) || defined(__arm64__) +static mach_vm_address_t __pthread_stack_hint = 0x30000000; #else #error no __pthread_stack_hint for this architecture #endif @@ -223,7 +232,7 @@ static inline void _pthread_struct_init(pthread_t t, const pthread_attr_t *attrs #if VARIANT_DYLD static void _pthread_set_self_dyld(void); #endif // VARIANT_DYLD -static inline void _pthread_set_self_internal(pthread_t, bool needs_tsd_base_set); +static inline void _pthread_set_self_internal(pthread_t); static void _pthread_dealloc_reply_port(pthread_t t); static void _pthread_dealloc_special_reply_port(pthread_t t); @@ -259,11 +268,6 @@ extern void thread_start(pthread_t self, mach_port_t kport, void *(*fun)(void *) #define PTHREAD_START_POLICY_MASK 0xff #define PTHREAD_START_IMPORTANCE_MASK 0xffff -#if (!defined(__OPEN_SOURCE__) && TARGET_OS_OSX) || OS_VARIANT_RESOLVED // 40703288 -static int pthread_setschedparam_internal(pthread_t, mach_port_t, int, - const struct sched_param *); -#endif - extern pthread_t __bsdthread_create(void *(*func)(void *), void * func_arg, void * stack, pthread_t thread, unsigned int flags); extern int __bsdthread_register(void (*)(pthread_t, mach_port_t, void *(*)(void *), void *, size_t, unsigned int), void (*)(pthread_t, mach_port_t, void *, void *, int), int,void (*)(pthread_t, mach_port_t, void *(*)(void *), void *, size_t, unsigned int), int32_t *,__uint64_t); extern int __bsdthread_terminate(void * freeaddr, size_t freesize, mach_port_t kport, mach_port_t joinsem); @@ -584,20 +588,26 @@ pthread_attr_setcpupercent_np(pthread_attr_t *attr, int percent, // it should be freed. static pthread_t -_pthread_allocate(const pthread_attr_t *attrs, void **stack) +_pthread_allocate(const pthread_attr_t *attrs, void **stack, + bool from_mach_thread) { mach_vm_address_t allocaddr = __pthread_stack_hint; size_t allocsize, guardsize, stacksize, pthreadoff; kern_return_t kr; pthread_t t; - PTHREAD_ASSERT(attrs->stacksize == 0 || - attrs->stacksize >= PTHREAD_STACK_MIN); + if (os_unlikely(attrs->stacksize != 0 && + attrs->stacksize < PTHREAD_STACK_MIN)) { + PTHREAD_CLIENT_CRASH(attrs->stacksize, "Stack size in attrs is too small"); + } + + if (os_unlikely(((uintptr_t)attrs->stackaddr % vm_page_size) != 0)) { + PTHREAD_CLIENT_CRASH(attrs->stacksize, "Unaligned stack addr in attrs"); + } // Allocate a pthread structure if necessary if (attrs->stackaddr != NULL) { - PTHREAD_ASSERT(((uintptr_t)attrs->stackaddr % vm_page_size) == 0); allocsize = PTHREAD_SIZE; guardsize = 0; pthreadoff = 0; @@ -621,10 +631,32 @@ _pthread_allocate(const pthread_attr_t *attrs, void **stack) if (kr != KERN_SUCCESS) { kr = mach_vm_allocate(mach_task_self(), &allocaddr, allocsize, VM_MAKE_TAG(VM_MEMORY_STACK)| VM_FLAGS_ANYWHERE); + } else if (__syscall_logger && !from_mach_thread) { + // libsyscall will not output malloc stack logging events when + // VM_MEMORY_STACK is passed in to facilitate mach thread promotion. + // To avoid losing the stack traces for normal p-thread create + // operations, libpthread must pretend to be the vm syscall and log + // the allocations. + int eventTypeFlags = stack_logging_type_vm_allocate | + stack_logging_type_mapped_file_or_shared_mem; + __syscall_logger(eventTypeFlags | VM_MAKE_TAG(VM_MEMORY_STACK), + (uintptr_t)mach_task_self(), (uintptr_t)allocsize, 0, + (uintptr_t)allocaddr, 0); } + if (kr != KERN_SUCCESS) { *stack = NULL; return NULL; + } else if (__syscall_logger && !from_mach_thread) { + // libsyscall will not output malloc stack logging events when + // VM_MEMORY_STACK is passed in to facilitate mach thread promotion. + // To avoid losing the stack traces for normal p-thread create + // operations, libpthread must pretend to be the vm syscall and log + // the allocations. + int eventTypeFlags = stack_logging_type_vm_allocate; + __syscall_logger(eventTypeFlags | VM_MAKE_TAG(VM_MEMORY_STACK), + (uintptr_t)mach_task_self(), (uintptr_t)allocsize, 0, + (uintptr_t)allocaddr, 0); } // The stack grows down. @@ -662,7 +694,9 @@ _pthread_deallocate(pthread_t t, bool from_mach_thread) _pthread_introspection_thread_destroy(t); } ret = mach_vm_deallocate(mach_task_self(), t->freeaddr, t->freesize); - PTHREAD_ASSERT(ret == KERN_SUCCESS); + if (ret != KERN_SUCCESS) { + PTHREAD_INTERNAL_CRASH(ret, "Unable to deallocate stack"); + } } } @@ -700,8 +734,6 @@ PTHREAD_NORETURN PTHREAD_NOINLINE PTHREAD_NOT_TAIL_CALLED static void _pthread_terminate(pthread_t t, void *exit_value) { - PTHREAD_ASSERT(t == pthread_self()); - _pthread_introspection_thread_terminate(t); uintptr_t freeaddr = (uintptr_t)t->freeaddr; @@ -839,38 +871,27 @@ _pthread_terminate_invoke(pthread_t t, void *exit_value) #pragma mark pthread start / body -/* - * Create and start execution of a new thread. - */ -PTHREAD_NOINLINE PTHREAD_NORETURN -static void -_pthread_body(pthread_t self, bool needs_tsd_base_set) -{ - _pthread_set_self_internal(self, needs_tsd_base_set); - __pthread_started_thread(self); - _pthread_exit(self, (self->fun)(self->arg)); -} - PTHREAD_NORETURN void _pthread_start(pthread_t self, mach_port_t kport, __unused void *(*fun)(void *), __unused void *arg, __unused size_t stacksize, unsigned int pflags) { - bool thread_tsd_bsd_set = (bool)(pflags & PTHREAD_START_TSD_BASE_SET); - if (os_unlikely(pflags & PTHREAD_START_SUSPENDED)) { - PTHREAD_INTERNAL_CRASH(0, + PTHREAD_INTERNAL_CRASH(pflags, "kernel without PTHREAD_START_SUSPENDED support"); } -#if DEBUG - PTHREAD_ASSERT(MACH_PORT_VALID(kport)); - PTHREAD_ASSERT(_pthread_kernel_thread(self) == kport); -#endif - // will mark the thread initialized + if (os_unlikely((pflags & PTHREAD_START_TSD_BASE_SET) == 0)) { + PTHREAD_INTERNAL_CRASH(pflags, + "thread_set_tsd_base() wasn't called by the kernel"); + } + PTHREAD_DEBUG_ASSERT(MACH_PORT_VALID(kport)); + PTHREAD_DEBUG_ASSERT(_pthread_kernel_thread(self) == kport); _pthread_markcancel_if_canceled(self, kport); - _pthread_body(self, !thread_tsd_bsd_set); + _pthread_set_self_internal(self); + __pthread_started_thread(self); + _pthread_exit(self, (self->fun)(self->arg)); } PTHREAD_ALWAYS_INLINE @@ -878,9 +899,7 @@ static inline void _pthread_struct_init(pthread_t t, const pthread_attr_t *attrs, void *stackaddr, size_t stacksize, void *freeaddr, size_t freesize) { -#if DEBUG - PTHREAD_ASSERT(t->sig != _PTHREAD_SIG); -#endif + PTHREAD_DEBUG_ASSERT(t->sig != _PTHREAD_SIG); t->sig = _PTHREAD_SIG; t->tsd[_PTHREAD_TSD_SLOT_PTHREAD_SELF] = t; @@ -965,13 +984,12 @@ size_t pthread_get_stacksize_np(pthread_t t) { size_t size = 0; - size_t stacksize = t->stackaddr - t->stackbottom; if (t == NULL) { return ESRCH; // XXX bug? } -#if !defined(__arm__) && !defined(__arm64__) +#if TARGET_OS_OSX // The default rlimit based allocations will be provided with a stacksize // of the current limit and a freesize of the max. However, custom // allocations will just have the guard page to free. If we aren't in the @@ -982,37 +1000,40 @@ pthread_get_stacksize_np(pthread_t t) // // Of course, on arm rlim_cur == rlim_max and there's only the one guard // page. So, we can skip all this there. - if (t == main_thread() && stacksize + vm_page_size != t->freesize) { - // We want to call getrlimit() just once, as it's relatively expensive - static size_t rlimit_stack; + if (t == main_thread()) { + size_t stacksize = t->stackaddr - t->stackbottom; + + if (stacksize + vm_page_size != t->freesize) { + // We want to call getrlimit() just once, as it's relatively + // expensive + static size_t rlimit_stack; - if (rlimit_stack == 0) { - struct rlimit limit; - int ret = getrlimit(RLIMIT_STACK, &limit); + if (rlimit_stack == 0) { + struct rlimit limit; + int ret = getrlimit(RLIMIT_STACK, &limit); - if (ret == 0) { - rlimit_stack = (size_t) limit.rlim_cur; + if (ret == 0) { + rlimit_stack = (size_t) limit.rlim_cur; + } } - } - if (rlimit_stack == 0 || rlimit_stack > t->freesize) { - return stacksize; - } else { - return rlimit_stack; + if (rlimit_stack == 0 || rlimit_stack > t->freesize) { + return stacksize; + } else { + return round_page(rlimit_stack); + } } } -#endif /* !defined(__arm__) && !defined(__arm64__) */ +#endif /* TARGET_OS_OSX */ if (t == pthread_self() || t == main_thread()) { - size = stacksize; + size = t->stackaddr - t->stackbottom;; goto out; } if (_pthread_validate_thread_and_list_lock(t)) { - size = stacksize; + size = t->stackaddr - t->stackbottom;; _PTHREAD_UNLOCK(_pthread_list_lock); - } else { - size = ESRCH; // XXX bug? } out: @@ -1108,6 +1129,24 @@ pthread_main_np(void) } +static int +_pthread_threadid_slow(pthread_t thread, uint64_t *thread_id) +{ + unsigned int info_count = THREAD_IDENTIFIER_INFO_COUNT; + mach_port_t thport = _pthread_kernel_thread(thread); + struct thread_identifier_info info; + kern_return_t kr; + + kr = thread_info(thport, THREAD_IDENTIFIER_INFO, + (thread_info_t)&info, &info_count); + if (kr == KERN_SUCCESS && info.thread_id) { + *thread_id = info.thread_id; + os_atomic_store(&thread->thread_id, info.thread_id, relaxed); + return 0; + } + return EINVAL; +} + /* * if we are passed in a pthread_t that is NULL, then we return the current * thread's thread_id. So folks don't have to call pthread_self, in addition to @@ -1129,10 +1168,11 @@ pthread_threadid_np(pthread_t thread, uint64_t *thread_id) } else if (!_pthread_validate_thread_and_list_lock(thread)) { res = ESRCH; } else { - if (thread->thread_id == 0) { - res = EINVAL; - } else { - *thread_id = thread->thread_id; + *thread_id = os_atomic_load(&thread->thread_id, relaxed); + if (os_unlikely(*thread_id == 0)) { + // there is a race at init because the thread sets its own TID. + // correct this by asking mach + res = _pthread_threadid_slow(thread, thread_id); } _PTHREAD_UNLOCK(_pthread_list_lock); } @@ -1235,7 +1275,7 @@ static inline void __pthread_started_thread(pthread_t t) { mach_port_t kport = _pthread_kernel_thread(t); - if (os_slowpath(!MACH_PORT_VALID(kport))) { + if (os_unlikely(!MACH_PORT_VALID(kport))) { PTHREAD_CLIENT_CRASH(kport, "Unable to allocate thread port, possible port leak"); } @@ -1277,7 +1317,7 @@ _pthread_create(pthread_t *thread, const pthread_attr_t *attrs, __is_threaded = 1; - t =_pthread_allocate(attrs, &stack); + t =_pthread_allocate(attrs, &stack, from_mach_thread); if (t == NULL) { return EAGAIN; } @@ -1297,10 +1337,6 @@ _pthread_create(pthread_t *thread, const pthread_attr_t *attrs, return EAGAIN; } - if (create_flags & _PTHREAD_CREATE_SUSPENDED) { - _pthread_markcancel_if_canceled(t, _pthread_kernel_thread(t)); - } - // n.b. if a thread is created detached and exits, t will be invalid *thread = t; return 0; @@ -1322,70 +1358,10 @@ pthread_create_from_mach_thread(pthread_t *thread, const pthread_attr_t *attr, return _pthread_create(thread, attr, start_routine, arg, flags); } -#if !defined(__OPEN_SOURCE__) && TARGET_OS_OSX // 40703288 -/* Functions defined in machine-dependent files. */ -PTHREAD_NOEXPORT void _pthread_setup_suspended(pthread_t th, void (*f)(pthread_t), void *sp); - -PTHREAD_NORETURN -static void -_pthread_suspended_body(pthread_t self) -{ - _pthread_set_self(self); - __pthread_started_thread(self); - _pthread_exit(self, (self->fun)(self->arg)); -} - -static int -_pthread_create_suspended_np(pthread_t *thread, const pthread_attr_t *attrs, - void *(*start_routine)(void *), void *arg) -{ - pthread_t t; - void *stack; - mach_port_t kernel_thread = MACH_PORT_NULL; - - if (attrs == NULL) { - attrs = &_pthread_attr_default; - } else if (attrs->sig != _PTHREAD_ATTR_SIG) { - return EINVAL; - } - - t = _pthread_allocate(attrs, &stack); - if (t == NULL) { - return EAGAIN; - } - - if (thread_create(mach_task_self(), &kernel_thread) != KERN_SUCCESS) { - _pthread_deallocate(t, false); - return EAGAIN; - } - - _pthread_set_kernel_thread(t, kernel_thread); - (void)pthread_setschedparam_internal(t, kernel_thread, - t->tl_policy, &t->tl_param); - - __is_threaded = 1; - - t->arg = arg; - t->fun = start_routine; - t->cancel_state |= _PTHREAD_CANCEL_INITIALIZED; - __pthread_add_thread(t, false); - - // Set up a suspended thread. - _pthread_setup_suspended(t, _pthread_suspended_body, stack); - *thread = t; - return 0; -} -#endif // !defined(__OPEN_SOURCE__) && TARGET_OS_OSX - int pthread_create_suspended_np(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) { -#if !defined(__OPEN_SOURCE__) && TARGET_OS_OSX // 40703288 - if (_os_xbs_chrooted) { - return _pthread_create_suspended_np(thread, attr, start_routine, arg); - } -#endif unsigned int flags = _PTHREAD_CREATE_SUSPENDED; return _pthread_create(thread, attr, start_routine, arg, flags); } @@ -1433,13 +1409,10 @@ pthread_kill(pthread_t th, int sig) } mach_port_t kport = MACH_PORT_NULL; - if (!_pthread_is_valid(th, &kport)) { - return ESRCH; // Not a valid thread. - } - - // Don't signal workqueue threads. - if (th->wqthread != 0 && th->wqkillset == 0) { - return ENOTSUP; + { + if (!_pthread_is_valid(th, &kport)) { + return ESRCH; + } } int ret = __pthread_kill(kport, sig); @@ -1454,13 +1427,9 @@ PTHREAD_NOEXPORT_VARIANT int __pthread_workqueue_setkill(int enable) { - pthread_t self = pthread_self(); - - _PTHREAD_LOCK(self->lock); - self->wqkillset = enable ? 1 : 0; - _PTHREAD_UNLOCK(self->lock); - - return 0; + { + return __bsdthread_ctl(BSDTHREAD_CTL_WORKQ_ALLOW_KILL, enable, 0, 0); + } } @@ -1629,7 +1598,8 @@ _pthread_set_self(pthread_t p) return _pthread_set_self_dyld(); } #endif // VARIANT_DYLD - _pthread_set_self_internal(p, true); + _pthread_set_self_internal(p); + _thread_set_tsd_base(&p->tsd[0]); } #if VARIANT_DYLD @@ -1660,17 +1630,13 @@ _pthread_set_self_dyld(void) PTHREAD_ALWAYS_INLINE static inline void -_pthread_set_self_internal(pthread_t p, bool needs_tsd_base_set) +_pthread_set_self_internal(pthread_t p) { - p->thread_id = __thread_selfid(); + os_atomic_store(&p->thread_id, __thread_selfid(), relaxed); if (os_unlikely(p->thread_id == -1ull)) { PTHREAD_INTERNAL_CRASH(0, "failed to set thread_id"); } - - if (needs_tsd_base_set) { - _thread_set_tsd_base(&p->tsd[0]); - } } @@ -1899,10 +1865,12 @@ __pthread_init(const struct _libpthread_functions *pthread_funcs, // and make it our main thread point. pthread_t thread = (pthread_t)_pthread_getspecific_direct( _PTHREAD_TSD_SLOT_PTHREAD_SELF); - PTHREAD_ASSERT(thread); + if (os_unlikely(thread == NULL)) { + PTHREAD_INTERNAL_CRASH(0, "PTHREAD_SELF TSD not initialized"); + } _main_thread_ptr = thread; - PTHREAD_ASSERT(_pthread_attr_default.qosclass == + PTHREAD_DEBUG_ASSERT(_pthread_attr_default.qosclass == _pthread_default_priority(0)); _pthread_struct_init(thread, &_pthread_attr_default, stackaddr, stacksize, allocaddr, allocsize); @@ -1950,7 +1918,6 @@ _pthread_main_thread_init(pthread_t p) p->tl_exit_gate = MACH_PORT_NULL; p->tsd[__TSD_SEMAPHORE_CACHE] = (void*)(uintptr_t)SEMAPHORE_NULL; p->tsd[__TSD_MACH_SPECIAL_REPLY] = 0; - p->cancel_state |= _PTHREAD_CANCEL_INITIALIZED; // Initialize the list of threads with the new main thread. TAILQ_INSERT_HEAD(&__pthread_head, p, tl_plist); @@ -1964,7 +1931,7 @@ void _pthread_main_thread_postfork_init(pthread_t p) { _pthread_main_thread_init(p); - _pthread_set_self_internal(p, false); + _pthread_set_self_internal(p); } int @@ -1987,6 +1954,25 @@ pthread_yield_np(void) sched_yield(); } +// Libsystem knows about this symbol and exports it to libsyscall +int +pthread_current_stack_contains_np(const void *addr, size_t length) +{ + uintptr_t begin = (uintptr_t) addr, end; + uintptr_t stack_base = (uintptr_t) _pthread_self_direct()->stackbottom; + uintptr_t stack_top = (uintptr_t) _pthread_self_direct()->stackaddr; + + if (stack_base == stack_top) { + return -ENOTSUP; + } + + if (__builtin_add_overflow(begin, length, &end)) { + return -EINVAL; + } + + return stack_base <= begin && end <= stack_top; +} + // Libsystem knows about this symbol and exports it to libsyscall @@ -2021,7 +2007,15 @@ _pthread_clear_qos_tsd(mach_port_t thread_port) #if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__arm64__) +#if __ARM64_ARCH_8_32__ +/* + * arm64_32 uses 64-bit sizes for the frame pointer and + * return address of a stack frame. + */ +typedef uint64_t frame_data_addr_t; +#else typedef uintptr_t frame_data_addr_t; +#endif struct frame_data { frame_data_addr_t frame_addr_next; @@ -2037,9 +2031,18 @@ pthread_stack_frame_decode_np(uintptr_t frame_addr, uintptr_t *return_addr) struct frame_data *frame = (struct frame_data *)frame_addr; if (return_addr) { +#if __has_feature(ptrauth_calls) + *return_addr = (uintptr_t)ptrauth_strip((void *)frame->ret_addr, + ptrauth_key_return_address); +#else *return_addr = (uintptr_t)frame->ret_addr; +#endif /* __has_feature(ptrauth_calls) */ } +#if __has_feature(ptrauth_calls) + return (uintptr_t)ptrauth_strip((void *)frame->frame_addr_next, + ptrauth_key_frame_pointer); +#endif /* __has_feature(ptrauth_calls) */ return (uintptr_t)frame->frame_addr_next; } @@ -2175,11 +2178,13 @@ _pthread_wqthread_setup(pthread_t self, mach_port_t kport, void *stacklowaddr, self->wqthread = 1; self->wqkillset = 0; self->tl_joinable = false; - self->cancel_state |= _PTHREAD_CANCEL_INITIALIZED; // Update the running thread count and set childrun bit. - bool thread_tsd_base_set = (bool)(flags & WQ_FLAG_THREAD_TSD_BASE_SET); - _pthread_set_self_internal(self, !thread_tsd_base_set); + if (os_unlikely((flags & WQ_FLAG_THREAD_TSD_BASE_SET) == 0)) { + PTHREAD_INTERNAL_CRASH(flags, + "thread_set_tsd_base() wasn't called by the kernel"); + } + _pthread_set_self_internal(self); __pthread_add_thread(self, false); __pthread_started_thread(self); } @@ -2212,36 +2217,36 @@ _pthread_wqthread(pthread_t self, mach_port_t kport, void *stacklowaddr, } pthread_priority_t pp; + if (flags & WQ_FLAG_THREAD_OUTSIDEQOS) { - self->wqoutsideqos = 1; + self->wq_outsideqos = 1; pp = _pthread_priority_make_from_thread_qos(THREAD_QOS_LEGACY, 0, _PTHREAD_PRIORITY_FALLBACK_FLAG); } else { - self->wqoutsideqos = 0; + self->wq_outsideqos = 0; pp = _pthread_wqthread_priority(flags); } self->tsd[_PTHREAD_TSD_SLOT_PTHREAD_QOS_CLASS] = (void *)pp; // avoid spills on the stack hard to keep used stack space minimal - if (nkevents == WORKQ_EXIT_THREAD_NKEVENT) { - goto exit; + if (os_unlikely(nkevents == WORKQ_EXIT_THREAD_NKEVENT)) { + _pthread_wqthread_exit(self); } else if (flags & WQ_FLAG_THREAD_WORKLOOP) { + kqueue_id_t *kqidptr = (kqueue_id_t *)keventlist - 1; self->fun = (void *(*)(void*))__libdispatch_workloopfunction; - self->wq_retop = WQOPS_THREAD_WORKLOOP_RETURN; - self->wq_kqid_ptr = ((kqueue_id_t *)keventlist - 1); self->arg = keventlist; self->wq_nevents = nkevents; + (*__libdispatch_workloopfunction)(kqidptr, &self->arg, &self->wq_nevents); + __workq_kernreturn(WQOPS_THREAD_WORKLOOP_RETURN, self->arg, self->wq_nevents, 0); } else if (flags & WQ_FLAG_THREAD_KEVENT) { self->fun = (void *(*)(void*))__libdispatch_keventfunction; - self->wq_retop = WQOPS_THREAD_KEVENT_RETURN; - self->wq_kqid_ptr = NULL; self->arg = keventlist; self->wq_nevents = nkevents; + (*__libdispatch_keventfunction)(&self->arg, &self->wq_nevents); + __workq_kernreturn(WQOPS_THREAD_KEVENT_RETURN, self->arg, self->wq_nevents, 0); } else { self->fun = (void *(*)(void*))__libdispatch_workerfunction; - self->wq_retop = WQOPS_THREAD_RETURN; - self->wq_kqid_ptr = NULL; self->arg = (void *)(uintptr_t)pp; self->wq_nevents = 0; if (os_likely(__workq_newapi)) { @@ -2249,33 +2254,15 @@ _pthread_wqthread(pthread_t self, mach_port_t kport, void *stacklowaddr, } else { _pthread_wqthread_legacy_worker_wrap(pp); } - goto just_return; - } - - if (nkevents > 0) { -kevent_errors_retry: - if (self->wq_retop == WQOPS_THREAD_WORKLOOP_RETURN) { - ((pthread_workqueue_function_workloop_t)self->fun) - (self->wq_kqid_ptr, &self->arg, &self->wq_nevents); - } else { - ((pthread_workqueue_function_kevent_t)self->fun) - (&self->arg, &self->wq_nevents); - } - int rc = __workq_kernreturn(self->wq_retop, self->arg, self->wq_nevents, 0); - if (os_unlikely(rc > 0)) { - self->wq_nevents = rc; - goto kevent_errors_retry; - } - if (os_unlikely(rc < 0)) { - PTHREAD_INTERNAL_CRASH(self->err_no, "kevent (workloop) failed"); - } - } else { -just_return: - __workq_kernreturn(self->wq_retop, NULL, 0, 0); + __workq_kernreturn(WQOPS_THREAD_RETURN, NULL, 0, 0); } -exit: - _pthread_wqthread_exit(self); + _os_set_crash_log_cause_and_message(self->err_no, + "BUG IN LIBPTHREAD: __workq_kernreturn returned"); + /* + * 52858993: we should never return but the compiler insists on outlining, + * so the __builtin_trap() is in _start_wqthread in pthread_asm.s + */ } @@ -2288,33 +2275,70 @@ _Static_assert(WORKQ_KEVENT_EVENT_BUFFER_LEN == WQ_KEVENT_LIST_LEN, void pthread_workqueue_setdispatchoffset_np(int offset) { - __libdispatch_offset = offset; + __workq_kernreturn(WQOPS_QUEUE_NEWSPISUPP, NULL, offset, 0x00); } -static int -pthread_workqueue_setdispatch_with_workloop_np(pthread_workqueue_function2_t queue_func, - pthread_workqueue_function_kevent_t kevent_func, - pthread_workqueue_function_workloop_t workloop_func) +int +pthread_workqueue_setup(struct pthread_workqueue_config *cfg, size_t cfg_size) { - int res = EBUSY; + int rv = EBUSY; + struct workq_dispatch_config wdc_cfg; + size_t min_size = 0; + + if (cfg_size < sizeof(uint32_t)) { + return EINVAL; + } + + switch (cfg->version) { + case 1: + min_size = offsetof(struct pthread_workqueue_config, queue_label_offs); + break; + case 2: + min_size = sizeof(struct pthread_workqueue_config); + break; + default: + return EINVAL; + } + + if (!cfg || cfg_size < min_size) { + return EINVAL; + } + + if (cfg->flags & ~PTHREAD_WORKQUEUE_CONFIG_SUPPORTED_FLAGS || + cfg->version < PTHREAD_WORKQUEUE_CONFIG_MIN_SUPPORTED_VERSION) { + return ENOTSUP; + } + if (__libdispatch_workerfunction == NULL) { - // Check whether the kernel supports new SPIs - res = __workq_kernreturn(WQOPS_QUEUE_NEWSPISUPP, NULL, __libdispatch_offset, kevent_func != NULL ? 0x01 : 0x00); - if (res == -1){ - res = ENOTSUP; + __workq_newapi = true; + + wdc_cfg.wdc_version = WORKQ_DISPATCH_CONFIG_VERSION; + wdc_cfg.wdc_flags = 0; + wdc_cfg.wdc_queue_serialno_offs = cfg->queue_serialno_offs; +#if WORKQ_DISPATCH_CONFIG_VERSION >= 2 + wdc_cfg.wdc_queue_label_offs = cfg->queue_label_offs; +#endif + + // Tell the kernel about dispatch internals + rv = (int) __workq_kernreturn(WQOPS_SETUP_DISPATCH, &wdc_cfg, sizeof(wdc_cfg), 0); + if (rv == -1) { + return errno; } else { - __libdispatch_workerfunction = queue_func; - __libdispatch_keventfunction = kevent_func; - __libdispatch_workloopfunction = workloop_func; + __libdispatch_keventfunction = cfg->kevent_cb; + __libdispatch_workloopfunction = cfg->workloop_cb; + __libdispatch_workerfunction = cfg->workq_cb; // Prepare the kernel for workq action (void)__workq_open(); if (__is_threaded == 0) { __is_threaded = 1; } + + return 0; } } - return res; + + return rv; } int @@ -2323,15 +2347,17 @@ _pthread_workqueue_init_with_workloop(pthread_workqueue_function2_t queue_func, pthread_workqueue_function_workloop_t workloop_func, int offset, int flags) { - if (flags != 0) { - return ENOTSUP; - } - - __workq_newapi = true; - __libdispatch_offset = offset; + struct pthread_workqueue_config cfg = { + .version = PTHREAD_WORKQUEUE_CONFIG_VERSION, + .flags = 0, + .workq_cb = queue_func, + .kevent_cb = kevent_func, + .workloop_cb = workloop_func, + .queue_serialno_offs = offset, + .queue_label_offs = 0, + }; - int rv = pthread_workqueue_setdispatch_with_workloop_np(queue_func, kevent_func, workloop_func); - return rv; + return pthread_workqueue_setup(&cfg, sizeof(cfg)); } int @@ -2351,7 +2377,17 @@ _pthread_workqueue_init(pthread_workqueue_function2_t func, int offset, int flag int pthread_workqueue_setdispatch_np(pthread_workqueue_function_t worker_func) { - return pthread_workqueue_setdispatch_with_workloop_np((pthread_workqueue_function2_t)worker_func, NULL, NULL); + struct pthread_workqueue_config cfg = { + .version = PTHREAD_WORKQUEUE_CONFIG_VERSION, + .flags = 0, + .workq_cb = (uint64_t)(pthread_workqueue_function2_t)worker_func, + .kevent_cb = 0, + .workloop_cb = 0, + .queue_serialno_offs = 0, + .queue_label_offs = 0, + }; + + return pthread_workqueue_setup(&cfg, sizeof(cfg)); } int @@ -2589,6 +2625,8 @@ _pthread_introspection_thread_destroy(pthread_t t) _pthread_introspection_hook_callout_thread_destroy(t); } + +#if !VARIANT_DYLD #pragma mark libplatform shims #include @@ -2623,3 +2661,4 @@ memcpy(void* a, const void* b, unsigned long s) return _platform_memmove(a, b, s); } +#endif // !VARIANT_DYLD diff --git a/src/pthread_asm.s b/src/pthread_asm.s index 90afe46..244957a 100644 --- a/src/pthread_asm.s +++ b/src/pthread_asm.s @@ -33,20 +33,23 @@ .globl _start_wqthread _start_wqthread: // This routine is never called directly by user code, jumped from kernel + // Push a sentinel frame, so backtracers know when to stop. + push $0 push %rbp mov %rsp,%rbp - sub $24,%rsp // align the stack + sub $16,%rsp // align the stack call __pthread_wqthread - leave - ret + ud2 // never returns .align 2, 0x90 .globl _thread_start _thread_start: // This routine is never called directly by user code, jumped from kernel + // Push a sentinel frame, so backtracers know when to stop. + push $0 push %rbp mov %rsp,%rbp - sub $24,%rsp // align the stack + sub $16,%rsp // align the stack call __pthread_start leave ret @@ -74,6 +77,14 @@ ____chkstk_darwin: // %rax == alloca size popq %rcx retq +Lcrash: + // POSIX mandates that stack overflow crashes with SIGSEGV + // so load an address in the guard page and dereference it + movq %gs:_PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET, %rcx + testq %rcx, -8(%rcx) + // if main_thread caused stack growth with setrlimit() + // fall into Lprobe and eventually cause SIGSEGV. + Lprobe: // probe the stack when it's not ours (altstack or some shenanigan) cmpq $0x1000, %rax @@ -93,9 +104,6 @@ Lend: popq %rcx retq -Lcrash: - ud2 - #endif #elif defined(__i386__) @@ -108,9 +116,11 @@ Lcrash: .globl _start_wqthread _start_wqthread: // This routine is never called directly by user code, jumped from kernel + // Push a sentinel frame, so backtracers know when to stop. + push $0 push %ebp mov %esp,%ebp - sub $28,%esp // align the stack + sub $24,%esp // align the stack mov %esi,20(%esp) //arg5 mov %edi,16(%esp) //arg5 mov %edx,12(%esp) //arg4 @@ -118,16 +128,17 @@ _start_wqthread: mov %ebx,4(%esp) //arg2 mov %eax,(%esp) //arg1 call __pthread_wqthread - leave - ret + ud2 // never returns .align 2, 0x90 .globl _thread_start _thread_start: // This routine is never called directly by user code, jumped from kernel + // Push a sentinel frame, so backtracers know when to stop. + push $0 push %ebp mov %esp,%ebp - sub $28,%esp // align the stack + sub $24,%esp // align the stack mov %esi,20(%esp) //arg6 mov %edi,16(%esp) //arg5 mov %edx,12(%esp) //arg4 @@ -165,6 +176,15 @@ ____chkstk_darwin: // %eax == alloca size popl %ecx retl +Lcrash: + // POSIX mandates that stack overflow crashes with SIGSEGV + // so load an address in the guard page and dereference it + movl %gs:0x0, %ecx // pthread_self() + movl _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET(%ecx), %ecx + testl %ecx, -4(%ecx) + // if main_thread caused stack growth with setrlimit() + // fall into Lprobe and eventually cause SIGSEGV. + Lprobe: // probe the stack when it's not ours (altstack or some shenanigan) cmpl $0x1000, %eax @@ -185,9 +205,6 @@ Lend: popl %ecx retl -Lcrash: - ud2 - #endif #elif defined(__arm__) @@ -206,30 +223,122 @@ Lcrash: .align 2 .globl _start_wqthread _start_wqthread: -#if __ARM_ARCH_7K__ - /* align stack to 16 bytes before calling C */ - sub sp, sp, #8 -#endif +// Push a sentinel frame, so backtracers know when to stop. + mov ip, #0 + str ip, [sp, #-4]! + str ip, [sp, #-4]! stmfd sp!, {r4, r5} bl __pthread_wqthread + trap // never returns + + .text + .align 2 + .globl _thread_start +_thread_start: +// Push a sentinel frame, so backtracers know when to stop. + mov ip, #0 + str ip, [sp, #-4]! + str ip, [sp, #-4]! + stmfd sp!, {r4, r5} + bl __pthread_start // Stackshots will show the routine that happens to link immediately following // _start_wqthread. So we add an extra instruction (nop) to make stackshots // more readable. nop +#endif + +#elif defined(__arm64__) + +#include + +#ifndef VARIANT_DYLD + +// This routine is never called directly by user code, jumped from kernel +// args 0 to 5 in registers. + .text + .align 2 + .globl _start_wqthread +_start_wqthread: +// Push a sentinel frame, so backtracers know when to stop. + stp xzr, xzr, [sp, #-16]! + bl __pthread_wqthread + brk #1 // never returns + .text .align 2 .globl _thread_start _thread_start: -#if __ARM_ARCH_7K__ - /* align stack to 16 bytes before calling C */ - sub sp, sp, #8 -#endif - stmfd sp!, {r4, r5} +// Push a sentinel frame, so backtracers know when to stop. + stp xzr, xzr, [sp, #-16]! bl __pthread_start -// See above nop + .text + .align 2 + .globl _thread_chkstk_darwin +_thread_chkstk_darwin: + .globl ____chkstk_darwin +____chkstk_darwin: // %w9 == alloca size + stp x10, x11, [sp, #-16] + + // validate that the frame pointer is on our stack (no alt stack) + mrs x10, TPIDRRO_EL0 + and x10, x10, #0xfffffffffffffff8 + + // (%sp - pthread_self()->stackaddr) > 0 ? +#if defined(__ARM64_ARCH_8_32__) + ldur w11, [x10, _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET] +#else + ldur x11, [x10, _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET] +#endif + subs x11, sp, x11 + b.hs Lprobe + + // %sp <= pthread_self()->stackbottom ? +#if defined(__ARM64_ARCH_8_32__) + ldur w11, [x10, _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET] +#else + ldur x11, [x10, _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET] +#endif + mov x10, sp + cmp x10, x11 + b.ls Lprobe + + // %sp - (uintptr_t)%w9 < pthread_self()->stackbottom ? + subs x10, x10, w9, uxtw + b.lo Lcrash + cmp x10, x11 + b.lo Lcrash + +Lexit: + ldp x10, x11, [sp, #-16] + ret + +Lcrash: + // POSIX mandates that stack overflow crashes with SIGSEGV + // so load an address in the guard page and dereference it + // + // x11 contains pthread_self()->stackbottom already + ldr x11, [x11, #-8] + // if main_thread caused stack growth with setrlimit() + // fall into Lprobe and eventually cause SIGSEGV. + +Lprobe: + mov x10, sp + cmp w9, #0x1000 + b.lo Lend +Lloop: + sub x10, x10, #0x1000 + ldr x11, [x10] + sub w9, w9, #0x1000 + cmp w9, #0x1000 + b.hi Lloop +Lend: + sub x10, x10, x9 + ldr x11, [x10] + b Lexit + #endif #else diff --git a/src/pthread_cancelable.c b/src/pthread_cancelable.c index 8bb9c08..3df57a7 100644 --- a/src/pthread_cancelable.c +++ b/src/pthread_cancelable.c @@ -191,8 +191,7 @@ void _pthread_markcancel_if_canceled(pthread_t thread, mach_port_t kport) { const int flags = (PTHREAD_CANCEL_ENABLE|_PTHREAD_CANCEL_PENDING); - int state = os_atomic_or2o(thread, cancel_state, - _PTHREAD_CANCEL_INITIALIZED, relaxed); + int state = os_atomic_load2o(thread, cancel_state, relaxed); if ((state & flags) == flags && __unix_conforming) { __pthread_markcancel(kport); } @@ -353,9 +352,7 @@ _pthread_joiner_abort_wait(pthread_t thread, pthread_join_context_t ctx) * _pthread_joiner_prepost_wake() didn't happen * allow another thread to join */ -#if DEBUG - PTHREAD_ASSERT(thread->tl_join_ctx == ctx); -#endif + PTHREAD_DEBUG_ASSERT(thread->tl_join_ctx == ctx); thread->tl_join_ctx = NULL; thread->tl_exit_gate = MACH_PORT_NULL; aborted = true; @@ -422,9 +419,7 @@ _pthread_joiner_wait(pthread_t thread, pthread_join_context_t ctx, int conformin // If pthread_detach() was called, we can't safely dereference the thread, // else, decide who gets to deallocate the thread (see _pthread_terminate). if (!ctx->detached) { -#if DEBUG - PTHREAD_ASSERT(thread->tl_join_ctx == ctx); -#endif + PTHREAD_DEBUG_ASSERT(thread->tl_join_ctx == ctx); thread->tl_join_ctx = NULL; cleanup = thread->tl_joiner_cleans_up; } @@ -461,9 +456,7 @@ _pthread_join(pthread_t thread, void **value_ptr, int conforming) res = EDEADLK; } else if (thread->tl_exit_gate == MACH_PORT_DEAD) { TAILQ_REMOVE(&__pthread_head, thread, tl_plist); -#if DEBUG - PTHREAD_ASSERT(thread->tl_joiner_cleans_up); -#endif + PTHREAD_DEBUG_ASSERT(thread->tl_joiner_cleans_up); thread->tl_joinable = false; if (value_ptr) *value_ptr = _pthread_get_exit_value(thread); } else { diff --git a/src/pthread_cond.c b/src/pthread_cond.c index 79e38ba..725134f 100644 --- a/src/pthread_cond.c +++ b/src/pthread_cond.c @@ -470,6 +470,7 @@ _pthread_cond_wait(pthread_cond_t *ocond, volatile uint32_t *c_lseqcnt, *c_useqcnt, *c_sseqcnt; uint64_t oldval64, newval64, mugen, cvlsgen; uint32_t *npmtx = NULL; + int timeout_elapsed = 0; res = _pthread_cond_check_init(cond, NULL); if (res != 0) { @@ -488,47 +489,59 @@ _pthread_cond_wait(pthread_cond_t *ocond, /* send relative time to kernel */ if (abstime) { + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= NSEC_PER_SEC) { + return EINVAL; + } + if (isRelative == 0) { struct timespec now; struct timeval tv; __gettimeofday(&tv, NULL); TIMEVAL_TO_TIMESPEC(&tv, &now); - /* Compute relative time to sleep */ - then.tv_nsec = abstime->tv_nsec - now.tv_nsec; - then.tv_sec = abstime->tv_sec - now.tv_sec; - if (then.tv_nsec < 0) { - then.tv_nsec += NSEC_PER_SEC; - then.tv_sec--; - } - if (then.tv_sec < 0 || (then.tv_sec == 0 && then.tv_nsec == 0)) { - return ETIMEDOUT; - } - if (conforming && - (abstime->tv_sec < 0 || - abstime->tv_nsec < 0 || - abstime->tv_nsec >= NSEC_PER_SEC)) { - return EINVAL; + if ((abstime->tv_sec == now.tv_sec) ? + (abstime->tv_nsec <= now.tv_nsec) : + (abstime->tv_sec < now.tv_sec)) { + timeout_elapsed = 1; + } else { + /* Compute relative time to sleep */ + then.tv_nsec = abstime->tv_nsec - now.tv_nsec; + then.tv_sec = abstime->tv_sec - now.tv_sec; + if (then.tv_nsec < 0) { + then.tv_nsec += NSEC_PER_SEC; + then.tv_sec--; + } } } else { then.tv_sec = abstime->tv_sec; then.tv_nsec = abstime->tv_nsec; if ((then.tv_sec == 0) && (then.tv_nsec == 0)) { - return ETIMEDOUT; + timeout_elapsed = 1; } } - if (conforming && (then.tv_sec < 0 || then.tv_nsec < 0)) { - return EINVAL; - } - if (then.tv_nsec >= NSEC_PER_SEC) { - return EINVAL; - } } if (cond->busy != NULL && cond->busy != mutex) { return EINVAL; } + /* + * If timeout is known to have elapsed, we still need to unlock and + * relock the mutex to allow other waiters to get in line and + * modify the condition state. + */ + if (timeout_elapsed) { + res = pthread_mutex_unlock(omutex); + if (res != 0) { + return res; + } + res = pthread_mutex_lock(omutex); + if (res != 0) { + return res; + } + return ETIMEDOUT; + } + COND_GETSEQ_ADDR(cond, &c_lsseqaddr, &c_lseqcnt, &c_useqcnt, &c_sseqcnt); do { diff --git a/src/pthread_cwd.c b/src/pthread_cwd.c index 7a8d500..3126c3b 100644 --- a/src/pthread_cwd.c +++ b/src/pthread_cwd.c @@ -2,9 +2,9 @@ #include #include -extern int __pthread_chdir(char *path); +extern int __pthread_chdir(const char *path); int -pthread_chdir_np(char *path) +pthread_chdir_np(const char *path) { return __pthread_chdir(path); } diff --git a/src/pthread_dependency.c b/src/pthread_dependency.c index 282dfc3..3836f15 100644 --- a/src/pthread_dependency.c +++ b/src/pthread_dependency.c @@ -91,8 +91,9 @@ pthread_dependency_wait_np(pthread_dependency_t *pr) pr->__pdep_owner, 0); switch (-ret) { case EFAULT: - if (pr->__pdep_opaque1 == pr->__pdep_owner) goto again; + case EINTR: case 0: + if (pr->__pdep_opaque1 == pr->__pdep_owner) goto again; break; case EOWNERDEAD: PTHREAD_CLIENT_CRASH(pr->__pdep_owner, "Waiting on orphaned dependency"); diff --git a/src/pthread_mutex.c b/src/pthread_mutex.c index edc97ee..e1e5c2e 100644 --- a/src/pthread_mutex.c +++ b/src/pthread_mutex.c @@ -131,7 +131,6 @@ void _pthread_mutex_global_init(const char *envp[], struct _pthread_registration_data *registration_data) { - int opt = _PTHREAD_MTX_OPT_POLICY_DEFAULT; if (registration_data->mutex_default_policy) { int policy = registration_data->mutex_default_policy; @@ -461,8 +460,8 @@ PTHREAD_NOEXPORT PTHREAD_NOINLINE PTHREAD_NORETURN int _pthread_mutex_corruption_abort(_pthread_mutex *mutex) { - PTHREAD_ABORT("pthread_mutex corruption: mutex owner changed in the " - "middle of lock/unlock"); + PTHREAD_CLIENT_CRASH(0, "pthread_mutex corruption: mutex owner changed " + "in the middle of lock/unlock"); } @@ -941,7 +940,7 @@ _pthread_mutex_fairshare_unlock_drop(_pthread_mutex *mutex, mutex_seq newseq, res = 0; } if (res != 0) { - PTHREAD_ABORT("__psynch_mutexdrop failed with error %d", res); + PTHREAD_INTERNAL_CRASH(res, "__psynch_mutexdrop failed"); } return res; } @@ -1122,7 +1121,7 @@ _pthread_mutex_firstfit_wake(_pthread_mutex *mutex, mutex_seq newseq, res = 0; } if (res != 0) { - PTHREAD_ABORT("__psynch_mutexdrop failed with error %d", res); + PTHREAD_INTERNAL_CRASH(res, "__psynch_mutexdrop failed"); } return res; } diff --git a/src/pthread_rwlock.c b/src/pthread_rwlock.c index 5b0bc9a..dac212a 100644 --- a/src/pthread_rwlock.c +++ b/src/pthread_rwlock.c @@ -199,7 +199,16 @@ rwlock_seq_atomic_load_relaxed(rwlock_seq *seqaddr, rwlock_seq *oldseqval, switch (seqfields) { case RWLOCK_SEQ_LSU: #if RWLOCK_USE_INT128 +#if defined(__arm64__) && defined(__ARM_ARCH_8_2__) + // Workaround clang armv81 codegen bug for 128bit os_atomic_load + // rdar://problem/31213932 + oldseqval->seq_LSU = seqaddr->seq_LSU; + while (!os_atomic_cmpxchgvw(&seqaddr->atomic_seq_LSU, + oldseqval->seq_LSU, oldseqval->seq_LSU, &oldseqval->seq_LSU, + relaxed)); +#else oldseqval->seq_LSU = os_atomic_load(&seqaddr->atomic_seq_LSU, relaxed); +#endif #else oldseqval->seq_LS = os_atomic_load(&seqaddr->atomic_seq_LS, relaxed); oldseqval->seq_U = os_atomic_load(&seqaddr->atomic_seq_U, relaxed); @@ -673,8 +682,7 @@ _pthread_rwlock_lock_wait(pthread_rwlock_t *orwlock, bool readlock, PLOCKSTAT_RW_BLOCKED(orwlock, plockstat, BLOCK_SUCCESS_PLOCKSTAT); } else { PLOCKSTAT_RW_BLOCKED(orwlock, plockstat, BLOCK_FAIL_PLOCKSTAT); - PTHREAD_ABORT("kernel rwlock returned unknown error %x: " - "tid %llx\n", res, _pthread_selfid_direct()); + PTHREAD_INTERNAL_CRASH(res, "kernel rwlock returned unknown error"); } return res; @@ -930,8 +938,7 @@ _pthread_rwlock_unlock_drop(pthread_rwlock_t *orwlock, rwlock_seq oldseq, } while (res == EINTR); if (res != 0) { - PTHREAD_ABORT("kernel rwunlock returned unknown error %x: " - "tid %llx\n", res, _pthread_selfid_direct()); + PTHREAD_INTERNAL_CRASH(res, "kernel rwunlock returned unknown error"); } return res; diff --git a/src/pthread_support.c b/src/pthread_support.c deleted file mode 100644 index f8c529f..0000000 --- a/src/pthread_support.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2012 Apple Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include "internal.h" -#include -#include <_simple.h> - - -#define __SIGABRT 6 - -/* We should move abort() into Libsyscall, if possible. */ -int __getpid(void); - -int -__kill(int pid, int signum, int posix); - -void -__pthread_abort(void) -{ - PTHREAD_NORETURN void (*_libc_abort)(void); - _libc_abort = dlsym(RTLD_DEFAULT, "abort"); - - if (_libc_abort) { - _libc_abort(); - } else { - __kill(__getpid(), __SIGABRT, 0); - } - __builtin_trap(); -} - -void -__pthread_abort_reason(const char *fmt, ...) -{ - __pthread_abort(); -} diff --git a/src/pthread_tsd.c b/src/pthread_tsd.c index 54b1bb0..b8e5d1a 100644 --- a/src/pthread_tsd.c +++ b/src/pthread_tsd.c @@ -54,6 +54,14 @@ #include "internal.h" #include +#ifndef PTHREAD_KEY_LEGACY_SUPPORT +#if TARGET_OS_DRIVERKIT +#define PTHREAD_KEY_LEGACY_SUPPORT 0 +#else +#define PTHREAD_KEY_LEGACY_SUPPORT 1 +#endif // TARGET_OS_DRIVERKIT +#endif // PTHREAD_KEY_LEGACY_SUPPORT + #if !VARIANT_DYLD // __pthread_tsd_first is first static key managed by libpthread. // __pthread_tsd_max is the (observed) end of static key destructors. @@ -66,8 +74,13 @@ static const int __pthread_tsd_end = _INTERNAL_POSIX_THREAD_KEYS_END; static int __pthread_tsd_max = __pthread_tsd_first; static _pthread_lock __pthread_tsd_lock = _PTHREAD_LOCK_INITIALIZER; +#if PTHREAD_KEY_LEGACY_SUPPORT static bool __pthread_key_legacy_behaviour = 0; static bool __pthread_key_legacy_behaviour_log = 0; +#else +#define __pthread_key_legacy_behaviour 0 +#define _pthread_tsd_cleanup_legacy(...) +#endif // PTHREAD_KEY_LEGACY_SUPPORT // Omit support for pthread key destructors in the static archive for dyld. // dyld does not create and destroy threads so these are not necessary. @@ -86,12 +99,14 @@ static struct { void _pthread_key_global_init(const char *envp[]) { +#if PTHREAD_KEY_LEGACY_SUPPORT if (_simple_getenv(envp, "PTHREAD_KEY_LEGACY_DESTRUCTOR_ORDER")) { __pthread_key_legacy_behaviour = true; } if (_simple_getenv(envp, "PTHREAD_KEY_LEGACY_DESTRUCTOR_ORDER_LOG")) { __pthread_key_legacy_behaviour_log = true; } +#endif // PTHREAD_KEY_LEGACY_SUPPORT } // Returns true if successful, false if destructor was already set. @@ -239,9 +254,6 @@ _pthread_tsd_cleanup_key(pthread_t self, pthread_key_t key) } #endif // !VARIANT_DYLD -#import <_simple.h> -#import - #if !VARIANT_DYLD static void _pthread_tsd_cleanup_new(pthread_t self) @@ -263,6 +275,9 @@ _pthread_tsd_cleanup_new(pthread_t self) self->max_tsd_key = 0; } +#if PTHREAD_KEY_LEGACY_SUPPORT +#import <_simple.h> +#import static void _pthread_tsd_behaviour_check(pthread_t self) { @@ -320,6 +335,7 @@ _pthread_tsd_cleanup_legacy(pthread_t self) } } } +#endif // PTHREAD_KEY_LEGACY_SUPPORT #endif // !VARIANT_DYLD void diff --git a/src/qos.c b/src/qos.c index ef36089..8aef21b 100644 --- a/src/qos.c +++ b/src/qos.c @@ -201,7 +201,7 @@ _pthread_qos_class_encode_workqueue(int queue_priority, unsigned long flags) case WORKQ_LOW_PRIOQUEUE: qos = THREAD_QOS_UTILITY; break; case WORKQ_BG_PRIOQUEUE: qos = THREAD_QOS_BACKGROUND; break; default: - __pthread_abort(); + PTHREAD_CLIENT_CRASH(queue_priority, "Invalid priority"); } return _pthread_priority_make_from_thread_qos(qos, 0, flags); } @@ -218,7 +218,7 @@ _pthread_set_properties_self(_pthread_set_flags_t flags, _pthread_set_flags_t kflags = flags; int rv = 0; - if (self->wqoutsideqos && (flags & _PTHREAD_SET_SELF_OUTSIDE_QOS_SKIP)) { + if (self->wq_outsideqos && (flags & _PTHREAD_SET_SELF_OUTSIDE_QOS_SKIP)) { // A number of properties cannot be altered if we are a workloop // thread that has outside of QoS properties applied to it. kflags &= ~_PTHREAD_SET_SELF_OUTSIDE_QOS_SKIP; diff --git a/src/thread_setup.c b/src/thread_setup.c deleted file mode 100644 index 22cc689..0000000 --- a/src/thread_setup.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2000-2003, 2008, 2012 Apple Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991 - * All Rights Reserved - * - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby granted, - * provided that the above copyright notice appears in all copies and - * that both the copyright notice and this permission notice appear in - * supporting documentation. - * - * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE. - * - * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, - * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ -/* - * MkLinux - */ - -#include "internal.h" - -#if !defined(__OPEN_SOURCE__) && TARGET_OS_OSX // 40703288 -/* - * Machine specific support for thread initialization - */ - -// NOTE: no resolvers, so this file must not contain any atomic operations - -PTHREAD_NOEXPORT void _pthread_setup_suspended(pthread_t th, void (*f)(pthread_t), void *sp); - -/* - * Set up the initial state of a MACH thread - */ -void -_pthread_setup_suspended(pthread_t thread, - void (*routine)(pthread_t), - void *vsp) -{ -#if defined(__i386__) - i386_thread_state_t state = { }; - thread_state_flavor_t flavor = x86_THREAD_STATE32; - mach_msg_type_number_t count = i386_THREAD_STATE_COUNT; -#elif defined(__x86_64__) - x86_thread_state64_t state = { }; - thread_state_flavor_t flavor = x86_THREAD_STATE64; - mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; -#else -#error _pthread_setup not defined for this architecture -#endif - - (void)thread_get_state(_pthread_kernel_thread(thread), - flavor, (thread_state_t)&state, &count); - -#if defined(__i386__) - uintptr_t *sp = vsp; - - state.__eip = (uintptr_t)routine; - - // We need to simulate a 16-byte aligned stack frame as if we had - // executed a call instruction. Since we're "pushing" one argument, - // we need to adjust the pointer by 12 bytes (3 * sizeof (int *)) - sp -= 3; // make sure stack is aligned - *--sp = (uintptr_t)thread; // argument to function - *--sp = 0; // fake return address - state.__esp = (uintptr_t)sp; // set stack pointer -#elif defined(__x86_64__) - uintptr_t *sp = vsp; - - state.__rip = (uintptr_t)routine; - - // We need to simulate a 16-byte aligned stack frame as if we had - // executed a call instruction. The stack should already be aligned - // before it comes to us and we don't need to push any arguments, - // so we shouldn't need to change it. - state.__rdi = (uintptr_t)thread; // argument to function - *--sp = 0; // fake return address - state.__rsp = (uintptr_t)sp; // set stack pointer -#else -#error _pthread_setup_suspended not defined for this architecture -#endif - - (void)thread_set_state(_pthread_kernel_thread(thread), flavor, (thread_state_t)&state, count); -} -#endif // !defined(__OPEN_SOURCE__) && TARGET_OS_OSX diff --git a/sys/qos.h b/sys/qos.h index d33af6b..2aa7dcd 100644 --- a/sys/qos.h +++ b/sys/qos.h @@ -114,11 +114,13 @@ #define __QOS_ENUM(name, type, ...) enum { __VA_ARGS__ }; typedef type name##_t #define __QOS_CLASS_AVAILABLE(...) +#if defined(__cplusplus) || defined(__OBJC__) || __LP64__ #if defined(__has_feature) && defined(__has_extension) #if __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums) #undef __QOS_ENUM #define __QOS_ENUM(name, type, ...) typedef enum : type { __VA_ARGS__ } name##_t #endif +#endif #if __has_feature(enumerator_attributes) #undef __QOS_CLASS_AVAILABLE #define __QOS_CLASS_AVAILABLE __API_AVAILABLE diff --git a/sys/qos_private.h b/sys/qos_private.h index 0a38926..b968f87 100644 --- a/sys/qos_private.h +++ b/sys/qos_private.h @@ -35,6 +35,6 @@ * system responsiveness for the user. * This is SPI for use by Spotlight and Time Machine only. */ -#define QOS_CLASS_MAINTENANCE 0x05 +#define QOS_CLASS_MAINTENANCE ((qos_class_t)0x05) #endif //_QOS_SYS_PRIVATE_H diff --git a/tests/Makefile b/tests/Makefile index 84e2717..f41b873 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -33,6 +33,7 @@ TARGETS += once_cancel TARGETS += pthread_attr_setstacksize TARGETS += pthread_bulk_create TARGETS += pthread_cancel +TARGETS += pthread_create_from_mach_thread TARGETS += pthread_cwd TARGETS += pthread_exit TARGETS += pthread_introspection @@ -46,6 +47,7 @@ TARGETS += rdar_32848402 #TARGETS += rwlock-signal #TARGETS += rwlock TARGETS += tsd +TARGETS += setrlimit_sigsegv #TARGETS += wq_block_handoff #TARGETS += wq_event_manager #TARGETS += wq_kevent @@ -54,6 +56,9 @@ TARGETS += wq_limits TARGETS += add_timer_termination TARGETS += perf_contended_mutex_rwlock +# this should be CUSTOM_TARGETS, see "Compatibility defines" in Makefile.targets +OTHER_TARGETS := stackoverflow_crash + OTHER_LTE_INCLUDE_FILES += \ /usr/local/lib/libdarwintest_utils.dylib @@ -75,3 +80,12 @@ main_stack_custom: OTHER_CFLAGS += -DSTACKSIZE=0x124000 bsdthread_set_self: OTHER_CFLAGS += -D_DARWIN_FEATURE_CLOCK_GETTIME include $(DEVELOPER_DIR)/AppleInternal/Makefiles/darwintest/Makefile.targets + +stackoverflow_crash: helpers/stackoverflow_crash.c + mkdir -p $(SYMROOT)/assets/ + $(CC) -o $(SYMROOT)/assets/$@ $(CFLAGS) -D_POSIX_C_SOURCE=1 $(OTHER_CFLAGS) $(LDFLAGS) $(OTHER_LDFLAGS) $< + env CODESIGN_ALLOCATE=$(CODESIGN_ALLOCATE) $(CODESIGN) --force --sign - --timestamp=none $(SYMROOT)/assets/$@ + +install-stackoverflow_crash: stackoverflow_crash + mkdir -p $(INSTALLDIR)/assets + @cp $(SYMROOT)/assets/stackoverflow_crash $(INSTALLDIR)/assets diff --git a/tests/cond_timed.c b/tests/cond_timed.c index 3f3c4e7..89734e9 100644 --- a/tests/cond_timed.c +++ b/tests/cond_timed.c @@ -13,6 +13,7 @@ #include "darwintest_defaults.h" #define NUM_THREADS 8 +#define RDAR_38144536 1 struct context { pthread_cond_t cond; @@ -162,17 +163,29 @@ T_DECL(cond_timedwait_nulltimeout, "pthread_cond_timedwait() with NULL timeout, T_DECL(cond_timedwait_zerotimeout, "pthread_cond_timedwait() with zero timeout, ensure mutex is unlocked") { +#if RDAR_38144536 + T_SKIP("skipped "); +#else // RDAR_38144536 cond_timedwait_timeouts_internal(eZeroTimeout, false); +#endif // RDAR_38144536 } T_DECL(cond_timedwait_beforeepochtimeout, "pthread_cond_timedwait() with timeout before the epoch, ensure mutex is unlocked") { +#if RDAR_38144536 + T_SKIP("skipped "); +#else // RDAR_38144536 cond_timedwait_timeouts_internal(eBeforeEpochTimeout, false); +#endif // RDAR_38144536 } T_DECL(cond_timedwait_pasttimeout, "pthread_cond_timedwait() with timeout in the past, ensure mutex is unlocked") { +#if RDAR_38144536 + T_SKIP("skipped "); +#else // RDAR_38144536 cond_timedwait_timeouts_internal(eRecentPastTimeout, false); +#endif // RDAR_38144536 } T_DECL(cond_timedwait_relative_nulltimeout, "pthread_cond_timedwait_relative_np() with relative NULL timeout, ensure mutex is unlocked") diff --git a/tests/helpers/stackoverflow_crash.c b/tests/helpers/stackoverflow_crash.c new file mode 100644 index 0000000..2858033 --- /dev/null +++ b/tests/helpers/stackoverflow_crash.c @@ -0,0 +1,56 @@ +#include +#include + +static volatile int * array1_ref = NULL; +static long last_stack_addr = 0; + +static void +recursive_fn(void) +{ + volatile int array1[1024]; /* leave this as it is */ + int addr; + last_stack_addr = (long)&addr; + array1_ref = array1; /* make sure compiler cannot discard storage */ + array1[0] = 0; + if (array1_ref == 0) { + /* fool clang -Winfinite-recursion */ + return; + } + recursive_fn(); + return; +} + +int +main(__unused int argc, __unused const char *argv[]) +{ + struct rlimit save; + + if (getrlimit(RLIMIT_STACK, &save) == -1) { + printf("child: ERROR - getrlimit"); + return 2; + } + printf("child: LOG - current stack limits cur=0x%llx, max=0x%llx, inf=0x%llx\n", save.rlim_cur, save.rlim_max, RLIM_INFINITY); + + if(save.rlim_cur >= save.rlim_max) { + printf("child: ERROR - invalid limits"); + return 2; + } + + if(save.rlim_max == RLIM_INFINITY) { + printf("child: ERROR - rlim_max = RLIM_INFINITY"); + return 2; + } + + save.rlim_cur += 4; + + printf("child: LOG - Raising setrlimit rlim_cur=0x%llx, rlim_max=0x%llx\n", save.rlim_cur, save.rlim_max); + + if (setrlimit(RLIMIT_STACK, &save) == -1) { + printf("child: ERROR - Raising the limits failed."); + return 2; + } + + printf("child: LOG - Make the stack grow such that a SIGSEGV is generated.\n"); + recursive_fn(); + return 0; +} diff --git a/tests/pthread_create_from_mach_thread.c b/tests/pthread_create_from_mach_thread.c new file mode 100644 index 0000000..0f4fc91 --- /dev/null +++ b/tests/pthread_create_from_mach_thread.c @@ -0,0 +1,93 @@ + +#include +#include +#include +#include +#include +#include + +#include "darwintest_defaults.h" + +#define CHILD_STACK_COUNT 1024 +static uint64_t child_stack[CHILD_STACK_COUNT]; + +static void* +pthread_runner(void* __unused arg) +{ + T_PASS("mach -> pthread conversion successful"); + T_END; +} + +static void * +mach_bootstrap(void * __unused arg) +{ + pthread_t thread; + pthread_create_from_mach_thread(&thread, NULL, pthread_runner, NULL); + while (1) { + swtch_pri(0); // mach_yield + } +} + +T_DECL(pthread_create_from_mach_thread, "pthread_create_from_mach_thread", + T_META_ALL_VALID_ARCHS(YES), + // Having leaks running will suppress the behavior we are testing + T_META_CHECK_LEAKS(false), + T_META_ENVVAR("MallocStackLogging=1") + ) +{ + T_PASS("MallocStackLogging: %s", getenv("MallocStackLogging")); + + // Create a mach_thread to start with + mach_port_t task = mach_task_self(); + + thread_state_flavor_t flavor; + mach_msg_type_number_t count; + + uintptr_t start_addr = (uintptr_t)&mach_bootstrap; + // Force alignment to 16-bytes + uintptr_t stack_top = ((uintptr_t)&child_stack[CHILD_STACK_COUNT]) & ~0xf; + +#if defined(__x86_64__) + T_PASS("x86_64"); + flavor = x86_THREAD_STATE64; + count = x86_THREAD_STATE64_COUNT; + x86_thread_state64_t state = { + .__rip = start_addr, + // Must be 16-byte-off-by-8 aligned + .__rsp = stack_top - 8, + }; +#elif defined(__arm64__) + T_PASS("arm64"); + flavor = ARM_THREAD_STATE64; + count = ARM_THREAD_STATE64_COUNT; + arm_thread_state64_t state = { }; + arm_thread_state64_set_pc_fptr(state, &mach_bootstrap); + arm_thread_state64_set_sp(state, stack_top); + (void)start_addr; +#elif defined(__arm__) + T_PASS("arm (32)"); + flavor = ARM_THREAD_STATE; + count = ARM_THREAD_STATE_COUNT; + arm_thread_state_t state = { + .__pc = start_addr, + .__sp = stack_top, + .__cpsr = 0x20, + }; +#else +#error Unknown architecture +#endif + + thread_state_t state_ptr = (thread_state_t)&state; + thread_t task_thread; + T_PASS("Launching Thread"); + + kern_return_t ret = thread_create_running(task, flavor, state_ptr, count, &task_thread); + T_ASSERT_MACH_SUCCESS(ret, "mach thread created"); + // Wait forever + sigset_t empty; + T_QUIET; T_ASSERT_POSIX_ZERO(sigemptyset(&empty), NULL); + while (sigsuspend(&empty)) { + continue; + } + T_FAIL("Didn't wait forever?"); +} diff --git a/tests/pthread_threadid_np.c b/tests/pthread_threadid_np.c index 46eb527..9529f26 100644 --- a/tests/pthread_threadid_np.c +++ b/tests/pthread_threadid_np.c @@ -8,7 +8,7 @@ extern __uint64_t __thread_selfid( void ); -static void *do_test(void * __unused arg) +static void *do_test(void * arg) { uint64_t threadid = __thread_selfid(); T_ASSERT_NE(threadid, (uint64_t)0, "__thread_selfid()"); @@ -21,6 +21,9 @@ static void *do_test(void * __unused arg) pth_threadid = _pthread_threadid_self_np_direct(); T_EXPECT_EQ(threadid, pth_threadid, "pthread_threadid_np_direct()"); + if (arg) { + *(uint64_t *)arg = pth_threadid; + } return NULL; } @@ -31,9 +34,14 @@ T_DECL(pthread_threadid_np, "pthread_threadid_np", do_test(NULL); T_LOG("Pthread"); - pthread_t pth; - T_ASSERT_POSIX_ZERO(pthread_create(&pth, NULL, do_test, NULL), NULL); - T_ASSERT_POSIX_ZERO(pthread_join(pth, NULL), NULL); + for (int i = 0; i < 100; i++) { + uint64_t tid1 = 0, tid2 = 0; + pthread_t pth; + T_ASSERT_POSIX_ZERO(pthread_create(&pth, NULL, do_test, &tid1), NULL); + T_EXPECT_POSIX_ZERO(pthread_threadid_np(pth, &tid2), NULL); + T_ASSERT_POSIX_ZERO(pthread_join(pth, NULL), NULL); + T_EXPECT_EQ(tid1, tid2, "parent and child agree"); + } T_LOG("Workqueue Thread"); dispatch_queue_t dq = dispatch_queue_create("myqueue", NULL); diff --git a/tests/setrlimit_sigsegv.c b/tests/setrlimit_sigsegv.c new file mode 100644 index 0000000..8f578d5 --- /dev/null +++ b/tests/setrlimit_sigsegv.c @@ -0,0 +1,52 @@ +#include "darwintest_defaults.h" +#include +#include +#include +#include + + +extern char **environ; + +T_DECL(setrlimit_overflow_segfault, + "sigsegv is sent when stack(limit set with setrlimit) is fully used.", + T_META_IGNORECRASHES(".*stackoverflow_crash.*"), + T_META_CHECK_LEAKS(NO), + T_META_ALL_VALID_ARCHS(YES), + T_META_ASROOT(YES)) +{ + pid_t child_pid = 0; + int rv = 0; + + struct rlimit lim, save; + T_ASSERT_POSIX_SUCCESS(getrlimit(RLIMIT_STACK, &save), NULL); + T_ASSERT_POSIX_SUCCESS(getrlimit(RLIMIT_STACK, &lim), NULL); + T_LOG("parent: stack limits cur=%llx max=%llx", lim.rlim_cur, lim.rlim_max); + lim.rlim_cur = lim.rlim_cur/8; + T_ASSERT_POSIX_SUCCESS(setrlimit(RLIMIT_STACK, &lim), NULL); + int status = 0; + int exit_signal = 0; + + char *crash_cmd[] = { "./assets/stackoverflow_crash", NULL }; + posix_spawn_file_actions_t fact; + posix_spawn_file_actions_init(&fact); + T_ASSERT_POSIX_SUCCESS(posix_spawn_file_actions_addinherit_np(&fact, STDIN_FILENO), NULL); + T_ASSERT_POSIX_SUCCESS(posix_spawn_file_actions_addinherit_np(&fact, STDOUT_FILENO), NULL); + T_ASSERT_POSIX_SUCCESS(posix_spawn_file_actions_addinherit_np(&fact, STDERR_FILENO), NULL); + T_LOG("spawning %s", crash_cmd[0]); + rv = posix_spawn(&child_pid, crash_cmd[0], &fact, NULL, crash_cmd, environ); + T_ASSERT_POSIX_SUCCESS(rv, "spawning the stackoverflow program"); + + T_LOG("parent: waiting for child process with pid %d", child_pid); + wait(&status); + T_LOG("parent: child process exited. status=%d", WEXITSTATUS(status)); + + + T_ASSERT_POSIX_SUCCESS(setrlimit(RLIMIT_STACK, &save), "Restore original limtis"); + posix_spawn_file_actions_destroy(&fact); + + T_ASSERT_TRUE(WIFSIGNALED(status), "child exit with a signal"); + exit_signal = WTERMSIG(status); + T_ASSERT_EQ(exit_signal, SIGSEGV, "child should receive SIGSEGV"); + + return; +} diff --git a/tests/stack.c b/tests/stack.c index f910b28..f9458ad 100644 --- a/tests/stack.c +++ b/tests/stack.c @@ -8,17 +8,14 @@ #define call_chkstk(value) \ __asm__ volatile("orr x9, xzr, %0\t\n" \ "bl _thread_chkstk_darwin" : : "i"(value) : "x9") -#define TRAPSIG SIGTRAP #elif defined(__x86_64__) #define call_chkstk(value) \ __asm__ volatile("movq %0, %%rax\t\n" \ "callq _thread_chkstk_darwin" : : "i"(value) : "rax") -#define TRAPSIG SIGILL #elif defined(__i386__) #define call_chkstk(value) \ __asm__ volatile("movl %0, %%eax\t\n" \ "calll _thread_chkstk_darwin" : : "i"(value) : "eax") -#define TRAPSIG SIGILL #endif static void @@ -41,7 +38,17 @@ T_DECL(chkstk, "chkstk", call_chkstk(1 << 16); T_PASS("calling with 1 << 16"); - signal(TRAPSIG, got_signal); + stack_t ss = { + .ss_sp = malloc(MINSIGSTKSZ), + .ss_size = MINSIGSTKSZ, + }; + T_ASSERT_POSIX_SUCCESS(sigaltstack(&ss, NULL), "sigaltstack"); + + struct sigaction sa = { + .sa_handler = got_signal, + .sa_flags = SA_ONSTACK, + }; + T_ASSERT_POSIX_SUCCESS(sigaction(SIGSEGV, &sa, NULL), "sigaction"); call_chkstk(1 << 24); T_FAIL("should have crashed"); diff --git a/tests/stack_size.c b/tests/stack_size.c index 3a52747..2c4780a 100644 --- a/tests/stack_size.c +++ b/tests/stack_size.c @@ -3,7 +3,11 @@ #include #include "darwintest_defaults.h" +#if defined(__arm64__) +#define PTHREAD_T_OFFSET (12*1024) +#else #define PTHREAD_T_OFFSET (0) +#endif static void * function(void *arg) diff --git a/xcodescripts/install-codes.sh b/xcodescripts/install-codes.sh index 685b494..cbe1b84 100644 --- a/xcodescripts/install-codes.sh +++ b/xcodescripts/install-codes.sh @@ -1,4 +1,7 @@ #!/bin/bash -e + +if [ "${DRIVERKIT}" = 1 ]; then exit 0; fi + # install kdebug trace files based on the input file INPUT=${SCRIPT_INPUT_FILE_0} OUTPUT=${SCRIPT_OUTPUT_FILE_0} diff --git a/xcodescripts/install-lldbmacros.sh b/xcodescripts/install-lldbmacros.sh index 9501f96..ca2d331 100644 --- a/xcodescripts/install-lldbmacros.sh +++ b/xcodescripts/install-lldbmacros.sh @@ -16,3 +16,9 @@ for variant in $BUILD_VARIANTS; do ln -sf init.py $DWARF_DSYM_FOLDER_PATH/$DWARF_DSYM_FILE_NAME/Contents/Resources/Python/$EXECUTABLE_NAME$SUFFIX.py done + +if test "$PLATFORM_NAME" != macosx; then + mkdir -p $DSTROOT/AppleInternal/KextObjects/Python/$MODULE_NAME || true + rsync -aq $SRCROOT/lldbmacros/* $DSTROOT/AppleInternal/KextObjects/Python/$MODULE_NAME + ln -sf init.py $DSTROOT/AppleInternal/KextObjects/Python/$MODULE_NAME/$EXECUTABLE_NAME.py +fi diff --git a/xcodescripts/install-manpages.sh b/xcodescripts/install-manpages.sh index 26a2205..b8da6de 100644 --- a/xcodescripts/install-manpages.sh +++ b/xcodescripts/install-manpages.sh @@ -23,6 +23,7 @@ if [ "$ACTION" = installhdrs ]; then exit 0; fi if [ "${RC_ProjectName%_Sim}" != "${RC_ProjectName}" ]; then exit 0; fi +if [ "${DRIVERKIT}" = 1 ]; then exit 0; fi set -x set -e diff --git a/xcodescripts/install-symlinks.sh b/xcodescripts/install-symlinks.sh index cc4fb2c..e2b1058 100644 --- a/xcodescripts/install-symlinks.sh +++ b/xcodescripts/install-symlinks.sh @@ -27,6 +27,8 @@ if [ "$ACTION" = build ]; then exit 0; fi # Symlink old header locations. # +DSTROOT="${DSTROOT}/${SDK_INSTALL_HEADERS_ROOT}" + ln -sf "pthread/pthread.h" "$DSTROOT/usr/include/pthread.h" ln -sf "pthread/pthread_impl.h" "$DSTROOT/usr/include/pthread_impl.h" ln -sf "pthread/pthread_spis.h" "$DSTROOT/usr/include/pthread_spis.h" diff --git a/xcodescripts/install-sys-headers.sh b/xcodescripts/install-sys-headers.sh index ca631d1..a5b4eba 100644 --- a/xcodescripts/install-sys-headers.sh +++ b/xcodescripts/install-sys-headers.sh @@ -25,6 +25,8 @@ set -e if [ "$ACTION" = build ]; then exit 0; fi +DSTROOT="${DSTROOT}/${SDK_INSTALL_HEADERS_ROOT}" + DESTDIR="$DSTROOT/usr/include/sys" mkdir -p "$DESTDIR" for X in \ diff --git a/xcodescripts/kext.xcconfig b/xcodescripts/kext.xcconfig index 84e9079..c28a730 100644 --- a/xcodescripts/kext.xcconfig +++ b/xcodescripts/kext.xcconfig @@ -24,7 +24,7 @@ INFOPLIST_FILE = kern/pthread-Info.plist ALWAYS_SEARCH_USER_PATHS = NO SRCROOT_SEARCH_PATHS = $(SRCROOT) $(SRCROOT)/pthread $(SRCROOT)/private HEADER_SEARCH_PATHS = $(SDKROOT)/System/Library/Frameworks/Kernel.framework/PrivateHeaders $(SDKROOT)/System/Library/Frameworks/Kernel.framework/Headers $(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders $(SDKROOT)/System/Library/Frameworks/System.framework/Headers $(SRCROOT_SEARCH_PATHS) -GCC_C_LANGUAGE_STANDARD = gnu99 +GCC_C_LANGUAGE_STANDARD = gnu11 CLANG_CXX_LANGUAGE_STANDARD = gnu++0x CLANG_CXX_LIBRARY = libc++ GCC_PRECOMPILE_PREFIX_HEADER = YES @@ -32,7 +32,7 @@ CODE_SIGN_IDENTITY = - DEBUG_INFORMATION_FORMAT = dwarf-with-dsym GCC_OPTIMIZATION_LEVEL_normal = s -GCC_OPTIMIZATION_LEVEL_development = 0 +GCC_OPTIMIZATION_LEVEL_development = s GCC_OPTIMIZATION_LEVEL = $(GCC_OPTIMIZATION_LEVEL_$(PTHREAD_VARIANT)) DEAD_CODE_STRIPPING = NO diff --git a/xcodescripts/pthread.dirty b/xcodescripts/pthread.dirty index 2a8f66e..45990a8 100644 --- a/xcodescripts/pthread.dirty +++ b/xcodescripts/pthread.dirty @@ -17,7 +17,6 @@ _exitf # int-sized ___is_threaded -___libdispatch_offset ___pthread_supported_features ___pthread_tsd_lock ___pthread_tsd_max diff --git a/xcodescripts/pthread.xcconfig b/xcodescripts/pthread.xcconfig index 1dedcaa..9094c6d 100644 --- a/xcodescripts/pthread.xcconfig +++ b/xcodescripts/pthread.xcconfig @@ -4,15 +4,26 @@ SDKROOT = macosx.internal SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator BUILD_VARIANTS = normal debug -INSTALL_PATH = /usr/lib/system +SDK_INSTALL_VARIANT = $(SDK_INSTALL_VARIANT_$(DRIVERKIT)) +SDK_INSTALL_VARIANT_1 = driverkit +SDK_INSTALL_VARIANT_ = default +SDK_INSTALL_ROOT = $(SDK_INSTALL_ROOT_$(SDK_INSTALL_VARIANT)) +SDK_INSTALL_ROOT_driverkit = $(DRIVERKITROOT) +SDK_INSTALL_HEADERS_ROOT = $(SDK_INSTALL_HEADERS_ROOT_$(SDK_INSTALL_VARIANT)) +SDK_INSTALL_HEADERS_ROOT_driverkit = $(SDK_INSTALL_ROOT)/$(SDK_RUNTIME_HEADERS_PREFIX) +SDK_RUNTIME_HEADERS_PREFIX = Runtime + +INSTALL_PATH = $(SDK_INSTALL_ROOT)/usr/lib/system EXECUTABLE_PREFIX = lib PRODUCT_NAME = system_pthread -PUBLIC_HEADERS_FOLDER_PATH = /usr/include/pthread -PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/pthread +PUBLIC_HEADERS_FOLDER_PATH = $(SDK_INSTALL_HEADERS_ROOT)/usr/include/pthread +PRIVATE_HEADERS_FOLDER_PATH = $(SDK_INSTALL_HEADERS_ROOT)/usr/local/include/pthread SRCROOT_SEARCH_PATHS = $(SRCROOT) $(SRCROOT)/private $(SRCROOT)/os $(SRCROOT)/src/resolver -SYSTEM_FRAMEWORK_HEADERS = $(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders -HEADER_SEARCH_PATHS = $($(PRODUCT_NAME)_SEARCH_PATHS) $(SRCROOT_SEARCH_PATHS) $(SYSTEM_FRAMEWORK_HEADERS) $(SDKROOT)/usr/local/include $(inherited) +SYSTEM_FRAMEWORK_HEADERS = $(SDKROOT)/$(SDK_INSTALL_HEADERS_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders +HEADER_SEARCH_PATHS = $($(PRODUCT_NAME)_SEARCH_PATHS) $(SRCROOT_SEARCH_PATHS) $(inherited) +SYSTEM_HEADER_SEARCH_PATHS = $(SYSTEM_FRAMEWORK_HEADERS) $(SDKROOT)/$(SDK_INSTALL_HEADERS_ROOT)/usr/local/include $(SDKROOT)/$(SDK_INSTALL_HEADERS_ROOT)/usr/include +SYSTEM_FRAMEWORK_SEARCH_PATHS = $(SDKROOT)/$(SDK_INSTALL_HEADERS_ROOT)/System/Library/Frameworks INSTALLHDRS_SCRIPT_PHASE = YES ALWAYS_SEARCH_USER_PATHS = YES USE_HEADERMAP = NO @@ -61,7 +72,7 @@ BASE_PREPROCESSOR_MACROS = __LIBC__ __DARWIN_UNIX03=1 __DARWIN_64_BIT_INO_T=1 __ GCC_PREPROCESSOR_DEFINITIONS = $(BASE_PREPROCESSOR_MACROS) $(PLATFORM_PREPROCESSOR_DEFINITIONS) // TODO: Remove -fstack-protector on _debug when it is moved to libplatform -OTHER_CFLAGS = -fno-stack-protector -fno-builtin $(PLATFORM_CFLAGS) $($(PRODUCT_NAME)_CFLAGS) +OTHER_CFLAGS = -fno-stack-protector -fno-stack-check -fno-builtin $(PLATFORM_CFLAGS) $($(PRODUCT_NAME)_CFLAGS) OTHER_CFLAGS_normal = -momit-leaf-frame-pointer OTHER_CFLAGS_debug = -fno-inline -O0 -DDEBUG=1 @@ -70,11 +81,15 @@ DYLIB_CURRENT_VERSION = $(RC_ProjectSourceVersion) DYLIB_COMPATIBILITY_VERSION = 1 DIRTY_LDFLAGS = -Wl,-dirty_data_list,$(SRCROOT)/xcodescripts/pthread.dirty DIRTY_LDFLAGS[sdk=macos*] = -DYLIB_LDFLAGS = -Wl,-alias_list,$(SRCROOT)/xcodescripts/pthread.aliases -Wl,-umbrella,System -L/usr/lib/system -lsystem_kernel -lsystem_platform -ldyld -lcompiler_rt -OTHER_LDFLAGS = $(DYLIB_LDFLAGS) $(DIRTY_LDFLAGS) $(CR_LDFLAGS) $(PLATFORM_LDFLAGS) +DYLIB_LDFLAGS = -Wl,-alias_list,$(SRCROOT)/xcodescripts/pthread.aliases -Wl,-umbrella,System -L$(SDK_INSTALL_ROOT)/usr/lib/system -lsystem_kernel -lsystem_platform -ldyld -lcompiler_rt +OTHER_LDFLAGS = $(DYLIB_LDFLAGS) $(DIRTY_LDFLAGS) $(CR_LDFLAGS) $(PLATFORM_LDFLAGS) $(SIMULATOR_LDFLAGS) + +SIMULATOR_LDFLAGS = +SIMULATOR_LDFLAGS[sdk=macosx*] = -Wl,-simulator_support +IS_ZIPPERED = YES + // Simulator build rules EXCLUDED_SOURCE_FILE_NAMES[sdk=iphonesimulator*] = *.c *.s SKIP_INSTALL[sdk=iphonesimulator*] = YES OTHER_LDFLAGS[sdk=iphonesimulator*] = - -- 2.45.2