}
 
        PTHREAD_TRACE(pthread_thread_create | DBG_FUNC_START, flags, 0, 0, 0);
-
-       kret = pthread_kern->thread_create(ctask, &th);
+       
+       /* Create thread and make it immovable, do not pin control port yet */
+       if (pthread_kern->thread_create_immovable) {
+               kret = pthread_kern->thread_create_immovable(ctask, &th);
+       } else {
+               kret = pthread_kern->thread_create(ctask, &th);
+       }
+       
        if (kret != KERN_SUCCESS)
                return(ENOMEM);
        thread_reference(th);
 
        pthread_kern->thread_set_tag(th, THREAD_TAG_PTHREAD);
 
-       sright = (void *)pthread_kern->convert_thread_to_port(th);
-       th_thport = pthread_kern->ipc_port_copyout_send(sright, pthread_kern->task_get_ipcspace(ctask));
+       if (pthread_kern->convert_thread_to_port_pinned) {
+               /* Convert to immovable/pinned thread port, but port is not pinned yet */
+               sright = (void *)pthread_kern->convert_thread_to_port_pinned(th);
+       } else {
+               sright = (void *)pthread_kern->convert_thread_to_port(th);
+       }
+       
+       if (pthread_kern->ipc_port_copyout_send_pinned) {
+               /* Atomically, pin and copy out the port */
+               th_thport = pthread_kern->ipc_port_copyout_send_pinned(sright, pthread_kern->task_get_ipcspace(ctask));
+       } else {
+               th_thport = pthread_kern->ipc_port_copyout_send(sright, pthread_kern->task_get_ipcspace(ctask));
+       }
+       
        if (!MACH_PORT_VALID(th_thport)) {
                error = EMFILE; // userland will convert this into a crash
                goto out;
        if (pthread_kern->thread_will_park_or_terminate) {
                pthread_kern->thread_will_park_or_terminate(th);
        }
-       (void)thread_terminate(th);
+       if (pthread_kern->thread_terminate_pinned) {
+               (void)pthread_kern->thread_terminate_pinned(th);
+       } else {
+               (void)thread_terminate(th);
+       }
        if (sem != MACH_PORT_NULL) {
                kret = pthread_kern->semaphore_signal_internal_trap(sem);
                if (kret != KERN_SUCCESS) {
 
                6ED6E66C22BFFC3200CE82C2 /* imports_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imports_internal.h; sourceTree = "<group>"; };
                6ED6E67322C0033B00CE82C2 /* prototypes_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prototypes_internal.h; sourceTree = "<group>"; };
                74E594A41613AAF4006C417B /* libpthread_eOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpthread_eOS.a; sourceTree = BUILT_PRODUCTS_DIR; };
+               84D2815025314CEB0097326C /* sys_pthread_types.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = sys_pthread_types.modulemap; sourceTree = "<group>"; };
                9202B2301D1A5B3F00945880 /* introspection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = introspection.h; sourceTree = "<group>"; };
                9235CA551CA48D010015C92B /* kext_development.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = kext_development.xcconfig; sourceTree = "<group>"; };
                9240BF321AA669C4003C99B4 /* wqtrace.lua */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = wqtrace.lua; path = tools/wqtrace.lua; sourceTree = SOURCE_ROOT; };
                        children = (
                                C9A325FD15B7513700270056 /* pthread */,
                                FC5A372217CEB3D6008C323E /* sys */,
+                               84D2815025314CEB0097326C /* sys_pthread_types.modulemap */,
                        );
                        path = include;
                        sourceTree = "<group>";
 
 
 /* pthread.c */
 void _pthread_deallocate(pthread_t t, bool from_mach_thread);
-void _pthread_main_thread_init(pthread_t p);
+void _pthread_main_thread_init(pthread_t p, mach_port_name_t main_th);
 void _pthread_main_thread_postfork_init(pthread_t p);
 void _pthread_bsdthread_init(struct _pthread_registration_data *data);
 void *_pthread_atomic_xchg_ptr(void **p, void *v);
 
        _pthread_init_signature(_main_thread_ptr);
 }
 
+static void
+parse_main_thread_port(const char *apple[], mach_port_name_t *main_th)
+{
+       const char *p, *s;
+       p = _simple_getenv(apple, "th_port");
+       if (p) {
+               *main_th = (mach_port_name_t)_pthread_strtoul(p, &s, 16);
+               bzero((char *)p, strlen(p));
+       }
+}
+
 int
 __pthread_init(const struct _libpthread_functions *pthread_funcs,
                const char *envp[], const char *apple[],
                        stackaddr, stacksize, allocaddr, allocsize);
        thread->tl_joinable = true;
 
+       // Get main thread port name from the kernel.
+       mach_port_name_t main_th_port = MACH_PORT_NULL;
+       parse_main_thread_port(apple, &main_th_port);
+
        // Finish initialization with common code that is reinvoked on the
        // child side of a fork.
 
        // Finishes initialization of main thread attributes.
        // Initializes the thread list and add the main thread.
        // Calls _pthread_set_self() to prepare the main thread for execution.
-       _pthread_main_thread_init(thread);
+       _pthread_main_thread_init(thread, main_th_port);
 
        struct _pthread_registration_data registration_data;
        // Set up kernel entry points with __bsdthread_register.
 #endif // !VARIANT_DYLD
 
 void
-_pthread_main_thread_init(pthread_t p)
+_pthread_main_thread_init(pthread_t p, mach_port_name_t main_thread_port)
 {
        TAILQ_INIT(&__pthread_head);
        _pthread_lock_init(&_pthread_list_lock);
        p->__cleanup_stack = NULL;
        p->tl_join_ctx = NULL;
        p->tl_exit_gate = MACH_PORT_NULL;
-       _pthread_tsd_slot(p, MACH_THREAD_SELF) = mach_thread_self();
+
+       if (main_thread_port != MACH_PORT_NULL) {
+               _pthread_tsd_slot(p, MACH_THREAD_SELF) = main_thread_port;
+       } else {
+               // Can't get thread port from kernel or we are forking, fallback to mach_thread_self
+               _pthread_tsd_slot(p, MACH_THREAD_SELF) = mach_thread_self();
+       }
        _pthread_tsd_slot(p, MIG_REPLY) = mach_reply_port();
        _pthread_tsd_slot(p, MACH_SPECIAL_REPLY) = MACH_PORT_NULL;
        _pthread_tsd_slot(p, SEMAPHORE_CACHE) = SEMAPHORE_NULL;
 void
 _pthread_main_thread_postfork_init(pthread_t p)
 {
-       _pthread_main_thread_init(p);
+       _pthread_main_thread_init(p, MACH_PORT_NULL);
        _pthread_set_self_internal(p);
 }
 
 
 
     find "${DSTROOT}/${SDK_INSTALL_HEADERS_ROOT}$2" -type f -name *.h -print0 | \
         xargs -0I % unifdef -t ${COPY_HEADERS_UNIFDEF_FLAGS} -o "%" "%"
+}
+
+install_modulemaps()
+{
+    mkdir -p "${DSTROOT}/${SDK_INSTALL_HEADERS_ROOT}$2"
+    cp "${SRCROOT}/$1/"*.modulemap "${DSTROOT}/${SDK_INSTALL_HEADERS_ROOT}$2"
+
     find "${DSTROOT}/${SDK_INSTALL_HEADERS_ROOT}$2" -type f -name *.modulemap -print0 | \
         xargs -0I % unifdef -t ${COPY_HEADERS_UNIFDEF_FLAGS} -o "%" "%"
 }
 
 install_headers "include/sys" "/usr/include"
 install_headers "private/sys" "/usr/local/include"
+
+install_modulemaps "include" "/usr/include"