]>
Commit | Line | Data |
---|---|---|
c6e5f90c A |
1 | |
2 | #include <pthread.h> | |
3 | #include <mach/mach.h> | |
4 | #include <stdlib.h> | |
5 | #include <unistd.h> | |
6 | #include <signal.h> | |
7 | #include <pthread_spis.h> | |
8 | ||
9 | #include "darwintest_defaults.h" | |
10 | ||
11 | #define CHILD_STACK_COUNT 1024 | |
12 | static uint64_t child_stack[CHILD_STACK_COUNT]; | |
13 | ||
14 | static void* | |
15 | pthread_runner(void* __unused arg) | |
16 | { | |
17 | T_PASS("mach -> pthread conversion successful"); | |
18 | T_END; | |
19 | } | |
20 | ||
21 | static void * | |
22 | mach_bootstrap(void * __unused arg) | |
23 | { | |
24 | pthread_t thread; | |
25 | pthread_create_from_mach_thread(&thread, NULL, pthread_runner, NULL); | |
26 | while (1) { | |
27 | swtch_pri(0); // mach_yield | |
28 | } | |
29 | } | |
30 | ||
31 | T_DECL(pthread_create_from_mach_thread, "pthread_create_from_mach_thread", | |
32 | T_META_ALL_VALID_ARCHS(YES), | |
33 | // Having leaks running will suppress the behavior we are testing | |
34 | T_META_CHECK_LEAKS(false), | |
35 | T_META_ENVVAR("MallocStackLogging=1") | |
36 | ) | |
37 | { | |
38 | T_PASS("MallocStackLogging: %s", getenv("MallocStackLogging")); | |
39 | ||
40 | // Create a mach_thread to start with | |
41 | mach_port_t task = mach_task_self(); | |
42 | ||
43 | thread_state_flavor_t flavor; | |
44 | mach_msg_type_number_t count; | |
45 | ||
46 | uintptr_t start_addr = (uintptr_t)&mach_bootstrap; | |
47 | // Force alignment to 16-bytes | |
48 | uintptr_t stack_top = ((uintptr_t)&child_stack[CHILD_STACK_COUNT]) & ~0xf; | |
49 | ||
50 | #if defined(__x86_64__) | |
51 | T_PASS("x86_64"); | |
52 | flavor = x86_THREAD_STATE64; | |
53 | count = x86_THREAD_STATE64_COUNT; | |
54 | x86_thread_state64_t state = { | |
55 | .__rip = start_addr, | |
56 | // Must be 16-byte-off-by-8 aligned <rdar://problem/15886599> | |
57 | .__rsp = stack_top - 8, | |
58 | }; | |
59 | #elif defined(__arm64__) | |
60 | T_PASS("arm64"); | |
61 | flavor = ARM_THREAD_STATE64; | |
62 | count = ARM_THREAD_STATE64_COUNT; | |
63 | arm_thread_state64_t state = { }; | |
64 | arm_thread_state64_set_pc_fptr(state, &mach_bootstrap); | |
65 | arm_thread_state64_set_sp(state, stack_top); | |
66 | (void)start_addr; | |
67 | #elif defined(__arm__) | |
68 | T_PASS("arm (32)"); | |
69 | flavor = ARM_THREAD_STATE; | |
70 | count = ARM_THREAD_STATE_COUNT; | |
71 | arm_thread_state_t state = { | |
72 | .__pc = start_addr, | |
73 | .__sp = stack_top, | |
74 | .__cpsr = 0x20, | |
75 | }; | |
76 | #else | |
77 | #error Unknown architecture | |
78 | #endif | |
79 | ||
80 | thread_state_t state_ptr = (thread_state_t)&state; | |
81 | thread_t task_thread; | |
82 | T_PASS("Launching Thread"); | |
83 | ||
84 | kern_return_t ret = thread_create_running(task, flavor, state_ptr, count, &task_thread); | |
85 | T_ASSERT_MACH_SUCCESS(ret, "mach thread created"); | |
86 | // Wait forever | |
87 | sigset_t empty; | |
88 | T_QUIET; T_ASSERT_POSIX_ZERO(sigemptyset(&empty), NULL); | |
89 | while (sigsuspend(&empty)) { | |
90 | continue; | |
91 | } | |
92 | T_FAIL("Didn't wait forever?"); | |
93 | } |