]> git.saurik.com Git - apple/libpthread.git/blobdiff - tests/pthread_create_from_mach_thread.c
libpthread-416.11.1.tar.gz
[apple/libpthread.git] / tests / pthread_create_from_mach_thread.c
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?");
+}