1*71db0c75SAndroid Build Coastguard Worker //===-- Linux implementation of the pthread_create function ---------------===// 2*71db0c75SAndroid Build Coastguard Worker // 3*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information. 5*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*71db0c75SAndroid Build Coastguard Worker // 7*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 8*71db0c75SAndroid Build Coastguard Worker 9*71db0c75SAndroid Build Coastguard Worker #include "pthread_create.h" 10*71db0c75SAndroid Build Coastguard Worker 11*71db0c75SAndroid Build Coastguard Worker #include "pthread_attr_destroy.h" 12*71db0c75SAndroid Build Coastguard Worker #include "pthread_attr_init.h" 13*71db0c75SAndroid Build Coastguard Worker 14*71db0c75SAndroid Build Coastguard Worker #include "pthread_attr_getdetachstate.h" 15*71db0c75SAndroid Build Coastguard Worker #include "pthread_attr_getguardsize.h" 16*71db0c75SAndroid Build Coastguard Worker #include "pthread_attr_getstack.h" 17*71db0c75SAndroid Build Coastguard Worker 18*71db0c75SAndroid Build Coastguard Worker #include "src/__support/common.h" 19*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/config.h" 20*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/optimization.h" 21*71db0c75SAndroid Build Coastguard Worker #include "src/__support/threads/thread.h" 22*71db0c75SAndroid Build Coastguard Worker #include "src/errno/libc_errno.h" 23*71db0c75SAndroid Build Coastguard Worker 24*71db0c75SAndroid Build Coastguard Worker #include <pthread.h> // For pthread_* type definitions. 25*71db0c75SAndroid Build Coastguard Worker 26*71db0c75SAndroid Build Coastguard Worker namespace LIBC_NAMESPACE_DECL { 27*71db0c75SAndroid Build Coastguard Worker 28*71db0c75SAndroid Build Coastguard Worker static_assert(sizeof(pthread_t) == sizeof(LIBC_NAMESPACE::Thread), 29*71db0c75SAndroid Build Coastguard Worker "Mismatch between pthread_t and internal Thread."); 30*71db0c75SAndroid Build Coastguard Worker 31*71db0c75SAndroid Build Coastguard Worker LLVM_LIBC_FUNCTION(int, pthread_create, 32*71db0c75SAndroid Build Coastguard Worker (pthread_t *__restrict th, 33*71db0c75SAndroid Build Coastguard Worker const pthread_attr_t *__restrict attr, 34*71db0c75SAndroid Build Coastguard Worker __pthread_start_t func, void *arg)) { 35*71db0c75SAndroid Build Coastguard Worker pthread_attr_t default_attr; 36*71db0c75SAndroid Build Coastguard Worker if (attr == nullptr) { 37*71db0c75SAndroid Build Coastguard Worker // We failed to initialize attributes (should be impossible) 38*71db0c75SAndroid Build Coastguard Worker if (LIBC_UNLIKELY(LIBC_NAMESPACE::pthread_attr_init(&default_attr) != 0)) 39*71db0c75SAndroid Build Coastguard Worker return EINVAL; 40*71db0c75SAndroid Build Coastguard Worker 41*71db0c75SAndroid Build Coastguard Worker attr = &default_attr; 42*71db0c75SAndroid Build Coastguard Worker } 43*71db0c75SAndroid Build Coastguard Worker 44*71db0c75SAndroid Build Coastguard Worker void *stack; 45*71db0c75SAndroid Build Coastguard Worker size_t stacksize, guardsize; 46*71db0c75SAndroid Build Coastguard Worker int detachstate; 47*71db0c75SAndroid Build Coastguard Worker 48*71db0c75SAndroid Build Coastguard Worker // As of writing this all the `pthread_attr_get*` functions always succeed. 49*71db0c75SAndroid Build Coastguard Worker if (LIBC_UNLIKELY( 50*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::pthread_attr_getstack(attr, &stack, &stacksize) != 0)) 51*71db0c75SAndroid Build Coastguard Worker return EINVAL; 52*71db0c75SAndroid Build Coastguard Worker 53*71db0c75SAndroid Build Coastguard Worker if (LIBC_UNLIKELY( 54*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::pthread_attr_getguardsize(attr, &guardsize) != 0)) 55*71db0c75SAndroid Build Coastguard Worker return EINVAL; 56*71db0c75SAndroid Build Coastguard Worker 57*71db0c75SAndroid Build Coastguard Worker if (LIBC_UNLIKELY( 58*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::pthread_attr_getdetachstate(attr, &detachstate) != 0)) 59*71db0c75SAndroid Build Coastguard Worker return EINVAL; 60*71db0c75SAndroid Build Coastguard Worker 61*71db0c75SAndroid Build Coastguard Worker if (attr == &default_attr) 62*71db0c75SAndroid Build Coastguard Worker // Should we fail here? Its non-issue as the moment as pthread_attr_destroy 63*71db0c75SAndroid Build Coastguard Worker // can only succeed. 64*71db0c75SAndroid Build Coastguard Worker if (LIBC_UNLIKELY(LIBC_NAMESPACE::pthread_attr_destroy(&default_attr) != 0)) 65*71db0c75SAndroid Build Coastguard Worker return EINVAL; 66*71db0c75SAndroid Build Coastguard Worker 67*71db0c75SAndroid Build Coastguard Worker if (stacksize && stacksize < PTHREAD_STACK_MIN) 68*71db0c75SAndroid Build Coastguard Worker return EINVAL; 69*71db0c75SAndroid Build Coastguard Worker 70*71db0c75SAndroid Build Coastguard Worker if (guardsize % EXEC_PAGESIZE != 0) 71*71db0c75SAndroid Build Coastguard Worker return EINVAL; 72*71db0c75SAndroid Build Coastguard Worker 73*71db0c75SAndroid Build Coastguard Worker if (detachstate != PTHREAD_CREATE_DETACHED && 74*71db0c75SAndroid Build Coastguard Worker detachstate != PTHREAD_CREATE_JOINABLE) 75*71db0c75SAndroid Build Coastguard Worker return EINVAL; 76*71db0c75SAndroid Build Coastguard Worker 77*71db0c75SAndroid Build Coastguard Worker // Thread::run will check validity of the `stack` argument (stack alignment is 78*71db0c75SAndroid Build Coastguard Worker // universal, not sure a pthread requirement). 79*71db0c75SAndroid Build Coastguard Worker 80*71db0c75SAndroid Build Coastguard Worker auto *thread = reinterpret_cast<LIBC_NAMESPACE::Thread *>(th); 81*71db0c75SAndroid Build Coastguard Worker int result = thread->run(func, arg, stack, stacksize, guardsize, 82*71db0c75SAndroid Build Coastguard Worker detachstate == PTHREAD_CREATE_DETACHED); 83*71db0c75SAndroid Build Coastguard Worker if (result != 0 && result != EPERM && result != EINVAL) 84*71db0c75SAndroid Build Coastguard Worker return EAGAIN; 85*71db0c75SAndroid Build Coastguard Worker return result; 86*71db0c75SAndroid Build Coastguard Worker } 87*71db0c75SAndroid Build Coastguard Worker 88*71db0c75SAndroid Build Coastguard Worker } // namespace LIBC_NAMESPACE_DECL 89