]> git.saurik.com Git - apple/libpthread.git/commitdiff
libpthread-416.11.1.tar.gz macos-1015 v416.11.1
authorApple <opensource@apple.com>
Fri, 31 Jan 2020 01:57:10 +0000 (01:57 +0000)
committerApple <opensource@apple.com>
Fri, 31 Jan 2020 01:57:10 +0000 (01:57 +0000)
39 files changed:
kern/kern_support.c
kern/kern_synch.c
libpthread.xcodeproj/project.pbxproj
man/pthread_setname_np.3
private/private.h
private/tsd_private.h
private/workqueue_private.h
pthread/pthread.h
src/internal.h
src/pthread.c
src/pthread_asm.s
src/pthread_cancelable.c
src/pthread_cond.c
src/pthread_cwd.c
src/pthread_dependency.c
src/pthread_mutex.c
src/pthread_rwlock.c
src/pthread_support.c [deleted file]
src/pthread_tsd.c
src/qos.c
src/thread_setup.c [deleted file]
sys/qos.h
sys/qos_private.h
tests/Makefile
tests/cond_timed.c
tests/helpers/stackoverflow_crash.c [new file with mode: 0644]
tests/pthread_create_from_mach_thread.c [new file with mode: 0644]
tests/pthread_threadid_np.c
tests/setrlimit_sigsegv.c [new file with mode: 0644]
tests/stack.c
tests/stack_size.c
xcodescripts/install-codes.sh
xcodescripts/install-lldbmacros.sh
xcodescripts/install-manpages.sh
xcodescripts/install-symlinks.sh
xcodescripts/install-sys-headers.sh
xcodescripts/kext.xcconfig
xcodescripts/pthread.dirty
xcodescripts/pthread.xcconfig

index e424cceac63775df0fe150a14de1d316cd3aa847..0e576c21a59e6319ce2b365da711f259e624fe31 100644 (file)
@@ -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.
+ * <rdar://problem/19941744> 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) {
index 7dabe413562e5a8bb30ef8a14fece8f94631359f..583bea2a65e55148dea51649f7c849c338c249f2 100644 (file)
@@ -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;
index 1c4fd1a07292ce8965a0a5ba9daf68fccd0f5044..5c193fdfa7707b10eacd3efbd17915e0c9cd287b 100644 (file)
                        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 */,
                        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 */
                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 */; };
                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 */; };
                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 */; };
                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, ); }; };
                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 */; };
                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 */; };
                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 */; };
                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, ); }; };
 /* 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 */;
                        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 */;
                        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 */;
                C975D5D615C9CECA0098ECD8 /* pthread_cond_legacy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pthread_cond_legacy.c; sourceTree = "<group>"; };
                C975D5D815C9CEEA0098ECD8 /* pthread_mutex_legacy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pthread_mutex_legacy.c; sourceTree = "<group>"; };
                C975D5DA15C9CEFA0098ECD8 /* pthread_rwlock_legacy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pthread_rwlock_legacy.c; sourceTree = "<group>"; };
-               C975D5DC15C9D16B0098ECD8 /* pthread_support.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pthread_support.c; sourceTree = "<group>"; };
                C979E9FB18A1BC2A000951E5 /* kern_trace.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = kern_trace.h; sourceTree = "<group>"; };
                C979E9FC18A2BF2C000951E5 /* install-codes.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "install-codes.sh"; sourceTree = "<group>"; };
                C98005141899BD2000368E4D /* workqueue_internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = workqueue_internal.h; sourceTree = "<group>"; };
                C9A325F815B7513200270056 /* pthread_tsd.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pthread_tsd.c; sourceTree = "<group>"; };
                C9A325F915B7513200270056 /* workqueue_private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = workqueue_private.h; sourceTree = "<group>"; };
                C9A325FA15B7513200270056 /* pthread.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = pthread.c; sourceTree = "<group>"; };
-               C9A325FC15B7513200270056 /* thread_setup.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = thread_setup.c; sourceTree = "<group>"; };
                C9A325FE15B7513700270056 /* pthread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pthread.h; sourceTree = "<group>"; };
                C9A325FF15B7513700270056 /* pthread_impl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pthread_impl.h; sourceTree = "<group>"; };
                C9A3260015B7513700270056 /* pthread_spis.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pthread_spis.h; sourceTree = "<group>"; };
                                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 */,
                        );
                                C90E7A9B15DC3C3800A06D48 /* Sources */,
                                C90E7A9C15DC3C3800A06D48 /* Frameworks */,
                                C90E7A9D15DC3C3800A06D48 /* Headers */,
-                               C04545891C5844F8006A53B3 /* Symlink libpthread_dyld.a to libpthread.a */,
                        );
                        buildRules = (
                        );
                C9A325D915B7347000270056 /* Project object */ = {
                        isa = PBXProject;
                        attributes = {
-                               LastUpgradeCheck = 0900;
+                               LastUpgradeCheck = 1100;
                                ORGANIZATIONNAME = "";
                                TargetAttributes = {
                                        92799B441B96A5FD00861404 = {
                                C91D01B5162892FF0002E29A /* Kext */,
                                C98832C115DEB44000B3308E /* Embedded */,
                                92799B441B96A5FD00861404 /* Tests */,
+                               C900AEA7215AF7170011B58C /* Introspection */,
+                               E4B7FCA822000AF50010A840 /* libpthread_driverkit */,
                                C9A325E115B7347000270056 /* libsystem_pthread */,
                                E4F449A41E82D03500A7FB9A /* libsystem_pthread noresolver */,
                                6E8C16511B14F08A00C8987C /* libsystem_pthread introspection */,
                        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;
                        );
                        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 */ = {
                        );
                        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 */ = {
                        );
                        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 */ = {
                        );
                        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 */ = {
                        );
                        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 */
                                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 */,
                                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 */,
                                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 */,
                                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;
                };
                                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 */,
                                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 */,
                                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 */,
                                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 */,
 /* 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 */;
                        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 */;
                        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 */;
                        };
                        name = Release;
                };
+               C900AEAB215AF7170011B58C /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                       };
+                       name = Release;
+               };
+               C900AEAC215AF7170011B58C /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                       };
+                       name = Debug;
+               };
                C90E7AA015DC3C3800A06D48 /* Release */ = {
                        isa = XCBuildConfiguration;
                        baseConfigurationReference = C04545B91C584F8B006A53B3 /* static.xcconfig */;
                        };
                        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 */;
                        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 = (
                        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 = (
index 13a9108f9f6c979c76b6076f68997c4ced4a9784..502e93652ddc9f4ee77ef806e7003726266cd55c 100644 (file)
@@ -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.
index b321442be2f0e9fe0f65c0a3d8c12ab6b6e32762..33d5e2534cbc4026f12ecc500ea6d78cdfaf0438 100644 (file)
@@ -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__
index 4b48d58b9f7714ce35ef01cc5d7991f484e5b5ae..e83ea66e61ad4a11d5daf95b3a5de4e30d798a34 100644 (file)
 #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
index 9cd0e951d6df271b6fbb472a48d552a7b3572436..11b0e5e143b565b685b34d4b6defe52dadb37d55 100644 (file)
@@ -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))
index f5fdff6b7e126f635b7204b0779a15be08c320c3..a042c82aed0c273022038e80cf9075b66f98357a 100644 (file)
@@ -188,7 +188,7 @@ __BEGIN_DECLS
 #define PTHREAD_MUTEX_INITIALIZER {_PTHREAD_MUTEX_SIG_init, {0}}
 
 /* <rdar://problem/10854763> */
-#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}}
index e8cc16158aec17e3882f1d5166027c56e891b286..daa2179040879b42efa5880e36e4d99e38e8e7fb 100644 (file)
@@ -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.
+ * <rdar://problem/19941744> 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 <os/semaphore_private.h>
 #include <os/alloc_once_private.h>
@@ -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);
 
index 3c3ea6a02645a2a1d6ad3e3ab27d0fbc640f69fa..8eca496e496194d7436954bfbc69798d8a9631da 100644 (file)
 #include <machine/vmparam.h>
 #define        __APPLE_API_PRIVATE
 #include <machine/cpu_capabilities.h>
+#if __has_include(<ptrauth.h>)
+#include <ptrauth.h>
+#endif // __has_include(<ptrauth.h>)
 
 #include <_simple.h>
 #include <platform/string.h>
 #include <platform/compat.h>
 
+#include <stack_logging.h>
+
+// 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. <rdar://36418708>
+               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. <rdar://36418708>
+               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 <platform/string.h>
@@ -2623,3 +2661,4 @@ memcpy(void* a, const void* b, unsigned long s)
        return _platform_memmove(a, b, s);
 }
 
+#endif // !VARIANT_DYLD
index 90afe461bfec6a8168ae7a1c616940160d91f9d8..244957a86209a8deca3904c593bfb2f97e9c5144 100644 (file)
        .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 <mach/arm/syscall_sw.h>
+
+#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
index 8bb9c08a7c3e1aa1a418c1c649a85cb046a02e96..3df57a7953cab52c7704b02f6c6e58baa3d6fc29 100644 (file)
@@ -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 {
index 79e38baa07b6cdc481c3bc6762466fa61a58a603..725134fa2f45e34f44afb5f7b66cf6b46ca156e1 100644 (file)
@@ -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 {
index 7a8d500f110085bad758dd569abf3388b0c7233e..3126c3b8a4973189356c8790466762826b815a49 100644 (file)
@@ -2,9 +2,9 @@
 #include <fcntl.h>
 #include <unistd.h>
 
-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);
 }
index 282dfc3dffd8691fbdb1f8141be820a1846d7044..3836f15988500b679fa81b512c880384cc233d59 100644 (file)
@@ -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");
index edc97ee38cbcdb10948eed3da81fd43d4f748084..e1e5c2e042f9714b2174d55195d7c41b6328fa75 100644 (file)
@@ -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;
        }
index 5b0bc9a70916ccf5a155683294dcbed23f0fd301..dac212ab4743d72df90348b75fce1c2098345646 100644 (file)
@@ -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 (file)
index f8c529f..0000000
+++ /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 <dlfcn.h>
-#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();
-}
index 54b1bb020d060eedc48e723f994af6a0c49e81e1..b8e5d1aeef0dc3ce826a13fe94cea2547f5b5f2a 100644 (file)
 #include "internal.h"
 #include <TargetConditionals.h>
 
+#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 <dlfcn.h>
-
 #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 <dlfcn.h>
 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
index ef360896e694091bf3b2d021a3132c6d26d53d7e..8aef21b45edd816916007f854cfbc0d8ac8fb4b0 100644 (file)
--- 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 (file)
index 22cc689..0000000
+++ /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
index d33af6bc0798f2580c9e6376552013984bfec655..2aa7dcd5c65306d9f3fe1578c9153ce14344728a 100644 (file)
--- a/sys/qos.h
+++ b/sys/qos.h
 #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
index 0a3892635d3c582c28728b16f59f1ea4adc635de..b968f87e2aefcabaa38452e1b15f344b09dd35e6 100644 (file)
@@ -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
index 84e2717439c7292b53be73eb0518e6020ea781d4..f41b8730698264c3e0a9b56339989c401524c69a 100644 (file)
@@ -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
index 3f3c4e7a1d6ced1e7566802e86bafc1eeaf4baba..89734e9aad754c4cf3093eccd4ade24efd05d006 100644 (file)
@@ -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 <rdar://38144536>");
+#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 <rdar://38144536>");
+#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 <rdar://38144536>");
+#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 (file)
index 0000000..2858033
--- /dev/null
@@ -0,0 +1,56 @@
+#include<stdio.h>
+#include<sys/resource.h>
+
+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 (file)
index 0000000..0f4fc91
--- /dev/null
@@ -0,0 +1,93 @@
+
+#include <pthread.h>
+#include <mach/mach.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread_spis.h>
+
+#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 <rdar://problem/15886599>
+        .__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?");
+}
index 46eb527136fb58bd305982be4d5ed5cff71a610c..9529f2633a1556b71ea39e4b62e88916e0e00767 100644 (file)
@@ -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 (file)
index 0000000..8f578d5
--- /dev/null
@@ -0,0 +1,52 @@
+#include "darwintest_defaults.h"
+#include <spawn.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+
+
+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;
+}
index f910b286a12b3224ed8d13d21c61e49ce4a910f9..f9458adc2722484ead2c2771c18b7c9a9a294ff4 100644 (file)
@@ -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");
index 3a52747a7bb396ce01aa84d525d673694443f165..2c4780ad94272064554790babb46d4f150518528 100644 (file)
@@ -3,7 +3,11 @@
 #include <stdlib.h>
 #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)
index 685b494e58c4271208922b897a1966e90561136c..cbe1b844e5c494386a91b1e83e57a9b56b47509c 100644 (file)
@@ -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}
index 9501f969e6bd98298022414bb311804ac367b7ed..ca2d3314fba78109271b462df7730eb34b7ff8f3 100644 (file)
@@ -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
index 26a220587ed60852c546c809395c519777505a08..b8da6deaf7a0446f7c1d2ad83ca7317441f0e7ff 100644 (file)
@@ -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
index cc4fb2c0aa0e084251bb6554ad0b448ecb0b4e59..e2b10589ee6e7bca943b7887377ef5386e90e42d 100644 (file)
@@ -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"
index ca631d1d4bc296cc09741935bc8182127d52f425..a5b4eba646a5fe9334cb8a184e6f92f4fc0baf7b 100644 (file)
@@ -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 \
index 84e90796bddc820d2695bfef0642ac03a1429923..c28a73014dd8b43a41b9960338a1038d39226183 100644 (file)
@@ -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
index 2a8f66e7b9a72ab0e9a68cd65d1649825fc77a82..45990a804b59829688bbf4db1cca14f828b38f0b 100644 (file)
@@ -17,7 +17,6 @@ _exitf
 
 # int-sized
 ___is_threaded
-___libdispatch_offset
 ___pthread_supported_features
 ___pthread_tsd_lock
 ___pthread_tsd_max
index 1dedcaa5a2353f880edeef01161f7aff885d34e0..9094c6dfe61f8adeb59335ffe714f75b72f77247 100644 (file)
@@ -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*] =
-