1 //===-- Tests for pthread_create ------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "src/pthread/pthread_attr_destroy.h"
10 #include "src/pthread/pthread_attr_getdetachstate.h"
11 #include "src/pthread/pthread_attr_getguardsize.h"
12 #include "src/pthread/pthread_attr_getstack.h"
13 #include "src/pthread/pthread_attr_getstacksize.h"
14 #include "src/pthread/pthread_attr_init.h"
15 #include "src/pthread/pthread_attr_setdetachstate.h"
16 #include "src/pthread/pthread_attr_setguardsize.h"
17 #include "src/pthread/pthread_attr_setstack.h"
18 #include "src/pthread/pthread_attr_setstacksize.h"
19 #include "src/pthread/pthread_create.h"
20 #include "src/pthread/pthread_join.h"
21 #include "src/pthread/pthread_self.h"
23 #include "src/sys/mman/mmap.h"
24 #include "src/sys/mman/munmap.h"
25 #include "src/sys/random/getrandom.h"
27 #include "src/__support/CPP/array.h"
28 #include "src/__support/CPP/atomic.h"
29 #include "src/__support/CPP/new.h"
30 #include "src/__support/threads/thread.h"
32 #include "src/errno/libc_errno.h"
34 #include "test/IntegrationTest/test.h"
36 #include <linux/param.h> // For EXEC_PAGESIZE.
39 struct TestThreadArgs
{
43 static LIBC_NAMESPACE::AllocChecker global_ac
;
44 static LIBC_NAMESPACE::cpp::Atomic
<long> global_thr_count
= 0;
46 static void *successThread(void *Arg
) {
47 pthread_t th
= LIBC_NAMESPACE::pthread_self();
48 auto *thread
= reinterpret_cast<LIBC_NAMESPACE::Thread
*>(&th
);
50 ASSERT_ERRNO_SUCCESS();
52 ASSERT_TRUE(thread
->attrib
);
54 TestThreadArgs
*th_arg
= reinterpret_cast<TestThreadArgs
*>(Arg
);
55 pthread_attr_t
*expec_attrs
= &(th_arg
->attrs
);
56 void *ret
= th_arg
->ret
;
59 size_t expec_stacksize
, expec_guardsize
, expec_stacksize2
;
62 ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_getstack(expec_attrs
, &expec_stack
,
65 ASSERT_ERRNO_SUCCESS();
68 LIBC_NAMESPACE::pthread_attr_getstacksize(expec_attrs
, &expec_stacksize2
),
70 ASSERT_ERRNO_SUCCESS();
73 LIBC_NAMESPACE::pthread_attr_getguardsize(expec_attrs
, &expec_guardsize
),
75 ASSERT_ERRNO_SUCCESS();
78 LIBC_NAMESPACE::pthread_attr_getdetachstate(expec_attrs
, &expec_detached
),
80 ASSERT_ERRNO_SUCCESS();
82 ASSERT_EQ(expec_stacksize
, expec_stacksize2
);
84 ASSERT_TRUE(thread
->attrib
->stack
);
85 if (expec_stack
!= nullptr) {
86 ASSERT_EQ(thread
->attrib
->stack
, expec_stack
);
88 ASSERT_EQ(reinterpret_cast<uintptr_t>(thread
->attrib
->stack
) %
90 static_cast<uintptr_t>(0));
91 expec_stacksize
= (expec_stacksize
+ EXEC_PAGESIZE
- 1) & (-EXEC_PAGESIZE
);
94 ASSERT_TRUE(expec_stacksize
);
95 ASSERT_EQ(thread
->attrib
->stacksize
, expec_stacksize
);
96 ASSERT_EQ(thread
->attrib
->guardsize
, expec_guardsize
);
98 ASSERT_EQ(expec_detached
== PTHREAD_CREATE_JOINABLE
,
99 thread
->attrib
->detach_state
.load() ==
100 static_cast<uint32_t>(LIBC_NAMESPACE::DetachState::JOINABLE
));
101 ASSERT_EQ(expec_detached
== PTHREAD_CREATE_DETACHED
,
102 thread
->attrib
->detach_state
.load() ==
103 static_cast<uint32_t>(LIBC_NAMESPACE::DetachState::DETACHED
));
106 // Allocate some bytes on the stack on most of the stack and make sure we
107 // have read/write permissions on the memory.
108 size_t test_stacksize
= expec_stacksize
- 1024;
109 volatile uint8_t *bytes_on_stack
=
110 (volatile uint8_t *)__builtin_alloca(test_stacksize
);
112 for (size_t I
= 0; I
< test_stacksize
; ++I
) {
114 bytes_on_stack
[I
] = static_cast<uint8_t>(I
);
117 for (size_t I
= 0; I
< test_stacksize
; ++I
) {
118 // Read/write permissions
119 bytes_on_stack
[I
] += static_cast<uint8_t>(I
);
123 // TODO: If guardsize != 0 && expec_stack == nullptr we should confirm that
124 // [stack - expec_guardsize, stack) is both mapped and has PROT_NONE
125 // permissions. Maybe we can read from /proc/{self}/map?
127 ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_destroy(expec_attrs
), 0);
128 ASSERT_ERRNO_SUCCESS();
130 // Arg is malloced, so free.
132 global_thr_count
.fetch_sub(1);
136 static void run_success_config(int detachstate
, size_t guardsize
,
137 size_t stacksize
, bool customstack
) {
139 TestThreadArgs
*th_arg
= new (global_ac
) TestThreadArgs
{};
140 pthread_attr_t
*attr
= &(th_arg
->attrs
);
142 ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_init(attr
), 0);
143 ASSERT_ERRNO_SUCCESS();
145 ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_setdetachstate(attr
, detachstate
), 0);
146 ASSERT_ERRNO_SUCCESS();
148 ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_setguardsize(attr
, guardsize
), 0);
149 ASSERT_ERRNO_SUCCESS();
151 void *Stack
= nullptr;
153 Stack
= LIBC_NAMESPACE::mmap(nullptr, stacksize
, PROT_READ
| PROT_WRITE
,
154 MAP_PRIVATE
| MAP_ANONYMOUS
, -1, 0);
155 ASSERT_NE(Stack
, MAP_FAILED
);
156 ASSERT_NE(Stack
, static_cast<void *>(nullptr));
157 ASSERT_ERRNO_SUCCESS();
159 ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_setstack(attr
, Stack
, stacksize
), 0);
160 ASSERT_ERRNO_SUCCESS();
162 ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_setstacksize(attr
, stacksize
), 0);
163 ASSERT_ERRNO_SUCCESS();
166 void *expec_ret
= nullptr;
167 if (detachstate
== PTHREAD_CREATE_JOINABLE
) {
168 ASSERT_EQ(LIBC_NAMESPACE::getrandom(&expec_ret
, sizeof(expec_ret
), 0),
169 static_cast<ssize_t
>(sizeof(expec_ret
)));
170 ASSERT_ERRNO_SUCCESS();
173 th_arg
->ret
= expec_ret
;
174 global_thr_count
.fetch_add(1);
177 // th_arg and attr are cleanup by the thread.
178 ASSERT_EQ(LIBC_NAMESPACE::pthread_create(&tid
, attr
, successThread
,
179 reinterpret_cast<void *>(th_arg
)),
181 ASSERT_ERRNO_SUCCESS();
183 if (detachstate
== PTHREAD_CREATE_JOINABLE
) {
185 ASSERT_EQ(LIBC_NAMESPACE::pthread_join(tid
, &th_ret
), 0);
186 ASSERT_ERRNO_SUCCESS();
187 ASSERT_EQ(th_ret
, expec_ret
);
190 ASSERT_EQ(LIBC_NAMESPACE::munmap(Stack
, stacksize
), 0);
191 ASSERT_ERRNO_SUCCESS();
194 ASSERT_FALSE(customstack
);
198 static void run_success_tests() {
201 using LIBC_NAMESPACE::cpp::array
;
203 array
<int, 2> detachstates
= {PTHREAD_CREATE_DETACHED
,
204 PTHREAD_CREATE_JOINABLE
};
205 array
<size_t, 4> guardsizes
= {0, EXEC_PAGESIZE
, 2 * EXEC_PAGESIZE
,
206 123 * EXEC_PAGESIZE
};
207 array
<size_t, 6> stacksizes
= {PTHREAD_STACK_MIN
,
208 PTHREAD_STACK_MIN
+ 16,
209 (1 << 16) - EXEC_PAGESIZE
/ 2,
210 (1 << 16) + EXEC_PAGESIZE
/ 2,
213 array
<bool, 2> customstacks
= {true, false};
215 for (int detachstate
: detachstates
) {
216 for (size_t guardsize
: guardsizes
) {
217 for (size_t stacksize
: stacksizes
) {
218 for (bool customstack
: customstacks
) {
221 // TODO: figure out how to test a user allocated stack
222 // along with detached pthread safely. We can't let the
223 // thread deallocate it owns stack for obvious
224 // reasons. And there doesn't appear to be a good way to
225 // check if a detached thread has exited. NB: It's racey to just
226 // wait for an atomic variable at the end of the thread function as
227 // internal thread cleanup functions continue to use its stack.
228 // Maybe an `atexit` handler would work.
229 if (detachstate
== PTHREAD_CREATE_DETACHED
)
232 // Guardsize has no meaning with user provided stack.
236 run_success_config(detachstate
, guardsize
, stacksize
, customstack
);
243 // Wait for detached threads to finish testing (this is not gurantee they will
245 while (global_thr_count
.load())
249 static void *failure_thread(void *) {
250 // Should be unreachable;
255 static void create_and_check_failure_thread(pthread_attr_t
*attr
) {
258 LIBC_NAMESPACE::pthread_create(&tid
, attr
, failure_thread
, nullptr);
259 // EINVAL if we caught on overflow or something of that nature. EAGAIN if it
260 // was just really larger we failed mmap.
261 ASSERT_TRUE(result
== EINVAL
|| result
== EAGAIN
);
262 // pthread_create should NOT set errno on error
263 ASSERT_ERRNO_SUCCESS();
265 ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_destroy(attr
), 0);
266 ASSERT_ERRNO_SUCCESS();
269 static void run_failure_config(size_t guardsize
, size_t stacksize
) {
271 guardsize
&= -EXEC_PAGESIZE
;
272 ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_init(&attr
), 0);
273 ASSERT_ERRNO_SUCCESS();
275 ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_setguardsize(&attr
, guardsize
), 0);
276 ASSERT_ERRNO_SUCCESS();
278 ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_setstacksize(&attr
, stacksize
), 0);
279 ASSERT_ERRNO_SUCCESS();
281 create_and_check_failure_thread(&attr
);
284 static void run_failure_tests() {
285 // Just some tests where the user sets "valid" parameters but they fail
286 // (overflow or too large to allocate).
287 run_failure_config(SIZE_MAX
, PTHREAD_STACK_MIN
);
288 run_failure_config(SIZE_MAX
- PTHREAD_STACK_MIN
, PTHREAD_STACK_MIN
* 2);
289 run_failure_config(PTHREAD_STACK_MIN
, SIZE_MAX
);
290 run_failure_config(PTHREAD_STACK_MIN
, SIZE_MAX
- PTHREAD_STACK_MIN
);
291 run_failure_config(SIZE_MAX
/ 2, SIZE_MAX
/ 2);
292 run_failure_config(3 * (SIZE_MAX
/ 4), SIZE_MAX
/ 4);
293 run_failure_config(SIZE_MAX
/ 2 + 1234, SIZE_MAX
/ 2);
295 // Test invalid parameters that are impossible to obtain via the
296 // `pthread_attr_set*` API. Still test that this not entirely unlikely
297 // initialization doesn't cause any issues. Basically we wan't to make sure
298 // that `pthread_create` properly checks for input validity and doesn't rely
299 // on the `pthread_attr_set*` API.
302 // Stacksize too small.
303 ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_init(&attr
), 0);
304 ASSERT_ERRNO_SUCCESS();
305 attr
.__stacksize
= PTHREAD_STACK_MIN
- 16;
306 create_and_check_failure_thread(&attr
);
309 ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_init(&attr
), 0);
310 ASSERT_ERRNO_SUCCESS();
311 attr
.__stack
= reinterpret_cast<void *>(1);
312 create_and_check_failure_thread(&attr
);
314 // Stack + stacksize misaligned.
315 ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_init(&attr
), 0);
316 ASSERT_ERRNO_SUCCESS();
317 attr
.__stacksize
= PTHREAD_STACK_MIN
+ 1;
318 attr
.__stack
= reinterpret_cast<void *>(16);
319 create_and_check_failure_thread(&attr
);
321 // Guardsize misaligned.
322 ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_init(&attr
), 0);
323 ASSERT_ERRNO_SUCCESS();
324 attr
.__guardsize
= EXEC_PAGESIZE
/ 2;
325 create_and_check_failure_thread(&attr
);
327 // Detachstate is unknown.
328 ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_init(&attr
), 0);
329 ASSERT_ERRNO_SUCCESS();
330 attr
.__detachstate
= -1;
331 create_and_check_failure_thread(&attr
);
335 LIBC_NAMESPACE::libc_errno
= 0;