xref: /llvm-project/libc/test/integration/src/pthread/pthread_create_test.cpp (revision 3eb1e6d8e930f5aff17b8d6bcc160f5bbf8cabc7)
16a185718SNoah Goldstein //===-- Tests for pthread_create ------------------------------------------===//
26a185718SNoah Goldstein //
36a185718SNoah Goldstein // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
46a185718SNoah Goldstein // See https://llvm.org/LICENSE.txt for license information.
56a185718SNoah Goldstein // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66a185718SNoah Goldstein //
76a185718SNoah Goldstein //===----------------------------------------------------------------------===//
86a185718SNoah Goldstein 
96a185718SNoah Goldstein #include "src/pthread/pthread_attr_destroy.h"
106a185718SNoah Goldstein #include "src/pthread/pthread_attr_getdetachstate.h"
116a185718SNoah Goldstein #include "src/pthread/pthread_attr_getguardsize.h"
126a185718SNoah Goldstein #include "src/pthread/pthread_attr_getstack.h"
136a185718SNoah Goldstein #include "src/pthread/pthread_attr_getstacksize.h"
146a185718SNoah Goldstein #include "src/pthread/pthread_attr_init.h"
156a185718SNoah Goldstein #include "src/pthread/pthread_attr_setdetachstate.h"
166a185718SNoah Goldstein #include "src/pthread/pthread_attr_setguardsize.h"
176a185718SNoah Goldstein #include "src/pthread/pthread_attr_setstack.h"
186a185718SNoah Goldstein #include "src/pthread/pthread_attr_setstacksize.h"
196a185718SNoah Goldstein #include "src/pthread/pthread_create.h"
206a185718SNoah Goldstein #include "src/pthread/pthread_join.h"
216a185718SNoah Goldstein #include "src/pthread/pthread_self.h"
226a185718SNoah Goldstein 
236a185718SNoah Goldstein #include "src/sys/mman/mmap.h"
246a185718SNoah Goldstein #include "src/sys/mman/munmap.h"
256a185718SNoah Goldstein #include "src/sys/random/getrandom.h"
266a185718SNoah Goldstein 
276a185718SNoah Goldstein #include "src/__support/CPP/array.h"
286a185718SNoah Goldstein #include "src/__support/CPP/atomic.h"
296a185718SNoah Goldstein #include "src/__support/CPP/new.h"
306a185718SNoah Goldstein #include "src/__support/threads/thread.h"
316a185718SNoah Goldstein 
326a185718SNoah Goldstein #include "src/errno/libc_errno.h"
336a185718SNoah Goldstein 
346a185718SNoah Goldstein #include "test/IntegrationTest/test.h"
356a185718SNoah Goldstein 
366a185718SNoah Goldstein #include <linux/param.h> // For EXEC_PAGESIZE.
376a185718SNoah Goldstein #include <pthread.h>
386a185718SNoah Goldstein 
396a185718SNoah Goldstein struct TestThreadArgs {
406a185718SNoah Goldstein   pthread_attr_t attrs;
416a185718SNoah Goldstein   void *ret;
426a185718SNoah Goldstein };
43b6bc9d72SGuillaume Chatelet static LIBC_NAMESPACE::AllocChecker global_ac;
44b6bc9d72SGuillaume Chatelet static LIBC_NAMESPACE::cpp::Atomic<long> global_thr_count = 0;
456a185718SNoah Goldstein 
successThread(void * Arg)466a185718SNoah Goldstein static void *successThread(void *Arg) {
47b6bc9d72SGuillaume Chatelet   pthread_t th = LIBC_NAMESPACE::pthread_self();
48b6bc9d72SGuillaume Chatelet   auto *thread = reinterpret_cast<LIBC_NAMESPACE::Thread *>(&th);
496a185718SNoah Goldstein 
5073874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
516a185718SNoah Goldstein   ASSERT_TRUE(thread);
526a185718SNoah Goldstein   ASSERT_TRUE(thread->attrib);
536a185718SNoah Goldstein 
546a185718SNoah Goldstein   TestThreadArgs *th_arg = reinterpret_cast<TestThreadArgs *>(Arg);
556a185718SNoah Goldstein   pthread_attr_t *expec_attrs = &(th_arg->attrs);
566a185718SNoah Goldstein   void *ret = th_arg->ret;
576a185718SNoah Goldstein 
586a185718SNoah Goldstein   void *expec_stack;
596a185718SNoah Goldstein   size_t expec_stacksize, expec_guardsize, expec_stacksize2;
606a185718SNoah Goldstein   int expec_detached;
616a185718SNoah Goldstein 
62b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_getstack(expec_attrs, &expec_stack,
636a185718SNoah Goldstein                                                   &expec_stacksize),
646a185718SNoah Goldstein             0);
6573874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
666a185718SNoah Goldstein 
676a185718SNoah Goldstein   ASSERT_EQ(
68b6bc9d72SGuillaume Chatelet       LIBC_NAMESPACE::pthread_attr_getstacksize(expec_attrs, &expec_stacksize2),
696a185718SNoah Goldstein       0);
7073874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
716a185718SNoah Goldstein 
726a185718SNoah Goldstein   ASSERT_EQ(
73b6bc9d72SGuillaume Chatelet       LIBC_NAMESPACE::pthread_attr_getguardsize(expec_attrs, &expec_guardsize),
74b6bc9d72SGuillaume Chatelet       0);
7573874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
766a185718SNoah Goldstein 
776a185718SNoah Goldstein   ASSERT_EQ(
78b6bc9d72SGuillaume Chatelet       LIBC_NAMESPACE::pthread_attr_getdetachstate(expec_attrs, &expec_detached),
796a185718SNoah Goldstein       0);
8073874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
816a185718SNoah Goldstein 
826a185718SNoah Goldstein   ASSERT_EQ(expec_stacksize, expec_stacksize2);
836a185718SNoah Goldstein 
846a185718SNoah Goldstein   ASSERT_TRUE(thread->attrib->stack);
856a185718SNoah Goldstein   if (expec_stack != nullptr) {
866a185718SNoah Goldstein     ASSERT_EQ(thread->attrib->stack, expec_stack);
876a185718SNoah Goldstein   } else {
886a185718SNoah Goldstein     ASSERT_EQ(reinterpret_cast<uintptr_t>(thread->attrib->stack) %
896a185718SNoah Goldstein                   EXEC_PAGESIZE,
906a185718SNoah Goldstein               static_cast<uintptr_t>(0));
916a185718SNoah Goldstein     expec_stacksize = (expec_stacksize + EXEC_PAGESIZE - 1) & (-EXEC_PAGESIZE);
926a185718SNoah Goldstein   }
936a185718SNoah Goldstein 
946a185718SNoah Goldstein   ASSERT_TRUE(expec_stacksize);
956a185718SNoah Goldstein   ASSERT_EQ(thread->attrib->stacksize, expec_stacksize);
966a185718SNoah Goldstein   ASSERT_EQ(thread->attrib->guardsize, expec_guardsize);
976a185718SNoah Goldstein 
986a185718SNoah Goldstein   ASSERT_EQ(expec_detached == PTHREAD_CREATE_JOINABLE,
996a185718SNoah Goldstein             thread->attrib->detach_state.load() ==
100b6bc9d72SGuillaume Chatelet                 static_cast<uint32_t>(LIBC_NAMESPACE::DetachState::JOINABLE));
1016a185718SNoah Goldstein   ASSERT_EQ(expec_detached == PTHREAD_CREATE_DETACHED,
1026a185718SNoah Goldstein             thread->attrib->detach_state.load() ==
103b6bc9d72SGuillaume Chatelet                 static_cast<uint32_t>(LIBC_NAMESPACE::DetachState::DETACHED));
1046a185718SNoah Goldstein 
1056a185718SNoah Goldstein   {
1066a185718SNoah Goldstein     // Allocate some bytes on the stack on most of the stack and make sure we
107872e46a9SSiva Chandra Reddy     // have read/write permissions on the memory.
108872e46a9SSiva Chandra Reddy     size_t test_stacksize = expec_stacksize - 1024;
1096a185718SNoah Goldstein     volatile uint8_t *bytes_on_stack =
1106a185718SNoah Goldstein         (volatile uint8_t *)__builtin_alloca(test_stacksize);
1116a185718SNoah Goldstein 
1126a185718SNoah Goldstein     for (size_t I = 0; I < test_stacksize; ++I) {
1136a185718SNoah Goldstein       // Write permissions
1146a185718SNoah Goldstein       bytes_on_stack[I] = static_cast<uint8_t>(I);
1156a185718SNoah Goldstein     }
1166a185718SNoah Goldstein 
1176a185718SNoah Goldstein     for (size_t I = 0; I < test_stacksize; ++I) {
1186a185718SNoah Goldstein       // Read/write permissions
1196a185718SNoah Goldstein       bytes_on_stack[I] += static_cast<uint8_t>(I);
1206a185718SNoah Goldstein     }
1216a185718SNoah Goldstein   }
1226a185718SNoah Goldstein 
1236a185718SNoah Goldstein   // TODO: If guardsize != 0 && expec_stack == nullptr we should confirm that
1246a185718SNoah Goldstein   // [stack - expec_guardsize, stack) is both mapped and has PROT_NONE
1256a185718SNoah Goldstein   // permissions. Maybe we can read from /proc/{self}/map?
1266a185718SNoah Goldstein 
127b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_destroy(expec_attrs), 0);
12873874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
1296a185718SNoah Goldstein 
1306a185718SNoah Goldstein   // Arg is malloced, so free.
1316a185718SNoah Goldstein   delete th_arg;
1326a185718SNoah Goldstein   global_thr_count.fetch_sub(1);
1336a185718SNoah Goldstein   return ret;
1346a185718SNoah Goldstein }
1356a185718SNoah Goldstein 
run_success_config(int detachstate,size_t guardsize,size_t stacksize,bool customstack)1366a185718SNoah Goldstein static void run_success_config(int detachstate, size_t guardsize,
1376a185718SNoah Goldstein                                size_t stacksize, bool customstack) {
1386a185718SNoah Goldstein 
1396a185718SNoah Goldstein   TestThreadArgs *th_arg = new (global_ac) TestThreadArgs{};
1406a185718SNoah Goldstein   pthread_attr_t *attr = &(th_arg->attrs);
1416a185718SNoah Goldstein 
142b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_init(attr), 0);
14373874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
1446a185718SNoah Goldstein 
145b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_setdetachstate(attr, detachstate), 0);
14673874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
1476a185718SNoah Goldstein 
148b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_setguardsize(attr, guardsize), 0);
14973874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
1506a185718SNoah Goldstein 
1516a185718SNoah Goldstein   void *Stack = nullptr;
1526a185718SNoah Goldstein   if (customstack) {
153b6bc9d72SGuillaume Chatelet     Stack = LIBC_NAMESPACE::mmap(nullptr, stacksize, PROT_READ | PROT_WRITE,
1546a185718SNoah Goldstein                                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1556a185718SNoah Goldstein     ASSERT_NE(Stack, MAP_FAILED);
1566a185718SNoah Goldstein     ASSERT_NE(Stack, static_cast<void *>(nullptr));
15773874f7aSGuillaume Chatelet     ASSERT_ERRNO_SUCCESS();
1586a185718SNoah Goldstein 
159b6bc9d72SGuillaume Chatelet     ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_setstack(attr, Stack, stacksize), 0);
16073874f7aSGuillaume Chatelet     ASSERT_ERRNO_SUCCESS();
1616a185718SNoah Goldstein   } else {
162b6bc9d72SGuillaume Chatelet     ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_setstacksize(attr, stacksize), 0);
16373874f7aSGuillaume Chatelet     ASSERT_ERRNO_SUCCESS();
1646a185718SNoah Goldstein   }
1656a185718SNoah Goldstein 
1666a185718SNoah Goldstein   void *expec_ret = nullptr;
1676a185718SNoah Goldstein   if (detachstate == PTHREAD_CREATE_JOINABLE) {
168b6bc9d72SGuillaume Chatelet     ASSERT_EQ(LIBC_NAMESPACE::getrandom(&expec_ret, sizeof(expec_ret), 0),
1696a185718SNoah Goldstein               static_cast<ssize_t>(sizeof(expec_ret)));
17073874f7aSGuillaume Chatelet     ASSERT_ERRNO_SUCCESS();
1716a185718SNoah Goldstein   }
1726a185718SNoah Goldstein 
1736a185718SNoah Goldstein   th_arg->ret = expec_ret;
1746a185718SNoah Goldstein   global_thr_count.fetch_add(1);
1756a185718SNoah Goldstein 
1766a185718SNoah Goldstein   pthread_t tid;
1776a185718SNoah Goldstein   // th_arg and attr are cleanup by the thread.
178b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_create(&tid, attr, successThread,
1796a185718SNoah Goldstein                                            reinterpret_cast<void *>(th_arg)),
1806a185718SNoah Goldstein             0);
18173874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
1826a185718SNoah Goldstein 
1836a185718SNoah Goldstein   if (detachstate == PTHREAD_CREATE_JOINABLE) {
1846a185718SNoah Goldstein     void *th_ret;
185b6bc9d72SGuillaume Chatelet     ASSERT_EQ(LIBC_NAMESPACE::pthread_join(tid, &th_ret), 0);
18673874f7aSGuillaume Chatelet     ASSERT_ERRNO_SUCCESS();
1876a185718SNoah Goldstein     ASSERT_EQ(th_ret, expec_ret);
1886a185718SNoah Goldstein 
1896a185718SNoah Goldstein     if (customstack) {
190b6bc9d72SGuillaume Chatelet       ASSERT_EQ(LIBC_NAMESPACE::munmap(Stack, stacksize), 0);
19173874f7aSGuillaume Chatelet       ASSERT_ERRNO_SUCCESS();
1926a185718SNoah Goldstein     }
1936a185718SNoah Goldstein   } else {
1946a185718SNoah Goldstein     ASSERT_FALSE(customstack);
1956a185718SNoah Goldstein   }
1966a185718SNoah Goldstein }
1976a185718SNoah Goldstein 
run_success_tests()1986a185718SNoah Goldstein static void run_success_tests() {
1996a185718SNoah Goldstein 
2006a185718SNoah Goldstein   // Test parameters
201b6bc9d72SGuillaume Chatelet   using LIBC_NAMESPACE::cpp::array;
2026a185718SNoah Goldstein 
2036a185718SNoah Goldstein   array<int, 2> detachstates = {PTHREAD_CREATE_DETACHED,
2046a185718SNoah Goldstein                                 PTHREAD_CREATE_JOINABLE};
2056a185718SNoah Goldstein   array<size_t, 4> guardsizes = {0, EXEC_PAGESIZE, 2 * EXEC_PAGESIZE,
2066a185718SNoah Goldstein                                  123 * EXEC_PAGESIZE};
2076a185718SNoah Goldstein   array<size_t, 6> stacksizes = {PTHREAD_STACK_MIN,
2086a185718SNoah Goldstein                                  PTHREAD_STACK_MIN + 16,
2096a185718SNoah Goldstein                                  (1 << 16) - EXEC_PAGESIZE / 2,
2106a185718SNoah Goldstein                                  (1 << 16) + EXEC_PAGESIZE / 2,
2116a185718SNoah Goldstein                                  1234560,
2126a185718SNoah Goldstein                                  1234560 * 2};
2136a185718SNoah Goldstein   array<bool, 2> customstacks = {true, false};
2146a185718SNoah Goldstein 
2156a185718SNoah Goldstein   for (int detachstate : detachstates) {
2166a185718SNoah Goldstein     for (size_t guardsize : guardsizes) {
2176a185718SNoah Goldstein       for (size_t stacksize : stacksizes) {
2186a185718SNoah Goldstein         for (bool customstack : customstacks) {
2196a185718SNoah Goldstein           if (customstack) {
2206a185718SNoah Goldstein 
2216a185718SNoah Goldstein             // TODO: figure out how to test a user allocated stack
2226a185718SNoah Goldstein             // along with detached pthread safely. We can't let the
2236a185718SNoah Goldstein             // thread deallocate it owns stack for obvious
2246a185718SNoah Goldstein             // reasons. And there doesn't appear to be a good way to
2256a185718SNoah Goldstein             // check if a detached thread has exited. NB: It's racey to just
2266a185718SNoah Goldstein             // wait for an atomic variable at the end of the thread function as
2276a185718SNoah Goldstein             // internal thread cleanup functions continue to use its stack.
2286a185718SNoah Goldstein             // Maybe an `atexit` handler would work.
2296a185718SNoah Goldstein             if (detachstate == PTHREAD_CREATE_DETACHED)
2306a185718SNoah Goldstein               continue;
2316a185718SNoah Goldstein 
2326a185718SNoah Goldstein             // Guardsize has no meaning with user provided stack.
2336a185718SNoah Goldstein             if (guardsize)
2346a185718SNoah Goldstein               continue;
2356a185718SNoah Goldstein 
2366a185718SNoah Goldstein             run_success_config(detachstate, guardsize, stacksize, customstack);
2376a185718SNoah Goldstein           }
2386a185718SNoah Goldstein         }
2396a185718SNoah Goldstein       }
2406a185718SNoah Goldstein     }
2416a185718SNoah Goldstein   }
2426a185718SNoah Goldstein 
2436a185718SNoah Goldstein   // Wait for detached threads to finish testing (this is not gurantee they will
2446a185718SNoah Goldstein   // have cleaned up)
2456a185718SNoah Goldstein   while (global_thr_count.load())
2466a185718SNoah Goldstein     ;
2476a185718SNoah Goldstein }
2486a185718SNoah Goldstein 
failure_thread(void *)2496a185718SNoah Goldstein static void *failure_thread(void *) {
2506a185718SNoah Goldstein   // Should be unreachable;
2516a185718SNoah Goldstein   ASSERT_TRUE(false);
2526a185718SNoah Goldstein   return nullptr;
2536a185718SNoah Goldstein }
2546a185718SNoah Goldstein 
create_and_check_failure_thread(pthread_attr_t * attr)2556a185718SNoah Goldstein static void create_and_check_failure_thread(pthread_attr_t *attr) {
2566a185718SNoah Goldstein   pthread_t tid;
257b6bc9d72SGuillaume Chatelet   int result =
258b6bc9d72SGuillaume Chatelet       LIBC_NAMESPACE::pthread_create(&tid, attr, failure_thread, nullptr);
2596a185718SNoah Goldstein   // EINVAL if we caught on overflow or something of that nature. EAGAIN if it
2606a185718SNoah Goldstein   // was just really larger we failed mmap.
2616a185718SNoah Goldstein   ASSERT_TRUE(result == EINVAL || result == EAGAIN);
2626a185718SNoah Goldstein   // pthread_create should NOT set errno on error
26373874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
2646a185718SNoah Goldstein 
265b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_destroy(attr), 0);
26673874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
2676a185718SNoah Goldstein }
2686a185718SNoah Goldstein 
run_failure_config(size_t guardsize,size_t stacksize)2696a185718SNoah Goldstein static void run_failure_config(size_t guardsize, size_t stacksize) {
2706a185718SNoah Goldstein   pthread_attr_t attr;
2716a185718SNoah Goldstein   guardsize &= -EXEC_PAGESIZE;
272b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_init(&attr), 0);
27373874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
2746a185718SNoah Goldstein 
275b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_setguardsize(&attr, guardsize), 0);
27673874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
2776a185718SNoah Goldstein 
278b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_setstacksize(&attr, stacksize), 0);
27973874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
2806a185718SNoah Goldstein 
2816a185718SNoah Goldstein   create_and_check_failure_thread(&attr);
2826a185718SNoah Goldstein }
2836a185718SNoah Goldstein 
run_failure_tests()2846a185718SNoah Goldstein static void run_failure_tests() {
2856a185718SNoah Goldstein   // Just some tests where the user sets "valid" parameters but they fail
2866a185718SNoah Goldstein   // (overflow or too large to allocate).
2876a185718SNoah Goldstein   run_failure_config(SIZE_MAX, PTHREAD_STACK_MIN);
2886a185718SNoah Goldstein   run_failure_config(SIZE_MAX - PTHREAD_STACK_MIN, PTHREAD_STACK_MIN * 2);
2896a185718SNoah Goldstein   run_failure_config(PTHREAD_STACK_MIN, SIZE_MAX);
2906a185718SNoah Goldstein   run_failure_config(PTHREAD_STACK_MIN, SIZE_MAX - PTHREAD_STACK_MIN);
2916a185718SNoah Goldstein   run_failure_config(SIZE_MAX / 2, SIZE_MAX / 2);
2927db91b4aSMikhail R. Gadelha   run_failure_config(3 * (SIZE_MAX / 4), SIZE_MAX / 4);
2936a185718SNoah Goldstein   run_failure_config(SIZE_MAX / 2 + 1234, SIZE_MAX / 2);
2946a185718SNoah Goldstein 
2956a185718SNoah Goldstein   // Test invalid parameters that are impossible to obtain via the
2966a185718SNoah Goldstein   // `pthread_attr_set*` API. Still test that this not entirely unlikely
2976a185718SNoah Goldstein   // initialization doesn't cause any issues. Basically we wan't to make sure
2986a185718SNoah Goldstein   // that `pthread_create` properly checks for input validity and doesn't rely
2996a185718SNoah Goldstein   // on the `pthread_attr_set*` API.
3006a185718SNoah Goldstein   pthread_attr_t attr;
3016a185718SNoah Goldstein 
3026a185718SNoah Goldstein   // Stacksize too small.
303b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_init(&attr), 0);
30473874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
3056a185718SNoah Goldstein   attr.__stacksize = PTHREAD_STACK_MIN - 16;
3066a185718SNoah Goldstein   create_and_check_failure_thread(&attr);
3076a185718SNoah Goldstein 
3086a185718SNoah Goldstein   // Stack misaligned.
309b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_init(&attr), 0);
31073874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
3116a185718SNoah Goldstein   attr.__stack = reinterpret_cast<void *>(1);
3126a185718SNoah Goldstein   create_and_check_failure_thread(&attr);
3136a185718SNoah Goldstein 
3146a185718SNoah Goldstein   // Stack + stacksize misaligned.
315b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_init(&attr), 0);
31673874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
3176a185718SNoah Goldstein   attr.__stacksize = PTHREAD_STACK_MIN + 1;
3186a185718SNoah Goldstein   attr.__stack = reinterpret_cast<void *>(16);
3196a185718SNoah Goldstein   create_and_check_failure_thread(&attr);
3206a185718SNoah Goldstein 
3216a185718SNoah Goldstein   // Guardsize misaligned.
322b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_init(&attr), 0);
32373874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
3246a185718SNoah Goldstein   attr.__guardsize = EXEC_PAGESIZE / 2;
3256a185718SNoah Goldstein   create_and_check_failure_thread(&attr);
3266a185718SNoah Goldstein 
3276a185718SNoah Goldstein   // Detachstate is unknown.
328b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_attr_init(&attr), 0);
32973874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
3306a185718SNoah Goldstein   attr.__detachstate = -1;
3316a185718SNoah Goldstein   create_and_check_failure_thread(&attr);
3326a185718SNoah Goldstein }
3336a185718SNoah Goldstein 
TEST_MAIN()3346a185718SNoah Goldstein TEST_MAIN() {
335*3eb1e6d8Smichaelrj-google   LIBC_NAMESPACE::libc_errno = 0;
3366a185718SNoah Goldstein   run_success_tests();
3376a185718SNoah Goldstein   run_failure_tests();
3386a185718SNoah Goldstein   return 0;
3396a185718SNoah Goldstein }
340