170c8d12bSSiva Chandra Reddy //===-- Linux implementation of the pthread_create function ---------------===// 270c8d12bSSiva Chandra Reddy // 370c8d12bSSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 470c8d12bSSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information. 570c8d12bSSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 670c8d12bSSiva Chandra Reddy // 770c8d12bSSiva Chandra Reddy //===----------------------------------------------------------------------===// 870c8d12bSSiva Chandra Reddy 970c8d12bSSiva Chandra Reddy #include "pthread_create.h" 1070c8d12bSSiva Chandra Reddy 116a185718SNoah Goldstein #include "pthread_attr_destroy.h" 126a185718SNoah Goldstein #include "pthread_attr_init.h" 136a185718SNoah Goldstein 146a185718SNoah Goldstein #include "pthread_attr_getdetachstate.h" 156a185718SNoah Goldstein #include "pthread_attr_getguardsize.h" 166a185718SNoah Goldstein #include "pthread_attr_getstack.h" 176a185718SNoah Goldstein 1870c8d12bSSiva Chandra Reddy #include "src/__support/common.h" 195ff3ff33SPetr Hosek #include "src/__support/macros/config.h" 206a185718SNoah Goldstein #include "src/__support/macros/optimization.h" 2170c8d12bSSiva Chandra Reddy #include "src/__support/threads/thread.h" 22*46944b0cSJob Henandez Lara #include "src/errno/libc_errno.h" 2370c8d12bSSiva Chandra Reddy 2470c8d12bSSiva Chandra Reddy #include <pthread.h> // For pthread_* type definitions. 2570c8d12bSSiva Chandra Reddy 265ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL { 2770c8d12bSSiva Chandra Reddy 28b6bc9d72SGuillaume Chatelet static_assert(sizeof(pthread_t) == sizeof(LIBC_NAMESPACE::Thread), 29f4580c6dSSiva Chandra Reddy "Mismatch between pthread_t and internal Thread."); 3070c8d12bSSiva Chandra Reddy 3170c8d12bSSiva Chandra Reddy LLVM_LIBC_FUNCTION(int, pthread_create, 326a185718SNoah Goldstein (pthread_t *__restrict th, 336a185718SNoah Goldstein const pthread_attr_t *__restrict attr, 3470c8d12bSSiva Chandra Reddy __pthread_start_t func, void *arg)) { 356a185718SNoah Goldstein pthread_attr_t default_attr; 366a185718SNoah Goldstein if (attr == nullptr) { 376a185718SNoah Goldstein // We failed to initialize attributes (should be impossible) 38b6bc9d72SGuillaume Chatelet if (LIBC_UNLIKELY(LIBC_NAMESPACE::pthread_attr_init(&default_attr) != 0)) 396a185718SNoah Goldstein return EINVAL; 406a185718SNoah Goldstein 416a185718SNoah Goldstein attr = &default_attr; 426a185718SNoah Goldstein } 436a185718SNoah Goldstein 446a185718SNoah Goldstein void *stack; 456a185718SNoah Goldstein size_t stacksize, guardsize; 466a185718SNoah Goldstein int detachstate; 476a185718SNoah Goldstein 486a185718SNoah Goldstein // As of writing this all the `pthread_attr_get*` functions always succeed. 496a185718SNoah Goldstein if (LIBC_UNLIKELY( 50b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::pthread_attr_getstack(attr, &stack, &stacksize) != 0)) 516a185718SNoah Goldstein return EINVAL; 526a185718SNoah Goldstein 536a185718SNoah Goldstein if (LIBC_UNLIKELY( 54b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::pthread_attr_getguardsize(attr, &guardsize) != 0)) 55b6bc9d72SGuillaume Chatelet return EINVAL; 56b6bc9d72SGuillaume Chatelet 57b6bc9d72SGuillaume Chatelet if (LIBC_UNLIKELY( 58b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::pthread_attr_getdetachstate(attr, &detachstate) != 0)) 596a185718SNoah Goldstein return EINVAL; 606a185718SNoah Goldstein 616a185718SNoah Goldstein if (attr == &default_attr) 626a185718SNoah Goldstein // Should we fail here? Its non-issue as the moment as pthread_attr_destroy 636a185718SNoah Goldstein // can only succeed. 64b6bc9d72SGuillaume Chatelet if (LIBC_UNLIKELY(LIBC_NAMESPACE::pthread_attr_destroy(&default_attr) != 0)) 656a185718SNoah Goldstein return EINVAL; 666a185718SNoah Goldstein 676a185718SNoah Goldstein if (stacksize && stacksize < PTHREAD_STACK_MIN) 686a185718SNoah Goldstein return EINVAL; 696a185718SNoah Goldstein 706a185718SNoah Goldstein if (guardsize % EXEC_PAGESIZE != 0) 716a185718SNoah Goldstein return EINVAL; 726a185718SNoah Goldstein 736a185718SNoah Goldstein if (detachstate != PTHREAD_CREATE_DETACHED && 746a185718SNoah Goldstein detachstate != PTHREAD_CREATE_JOINABLE) 756a185718SNoah Goldstein return EINVAL; 766a185718SNoah Goldstein 776a185718SNoah Goldstein // Thread::run will check validity of the `stack` argument (stack alignment is 786a185718SNoah Goldstein // universal, not sure a pthread requirement). 796a185718SNoah Goldstein 80b6bc9d72SGuillaume Chatelet auto *thread = reinterpret_cast<LIBC_NAMESPACE::Thread *>(th); 816a185718SNoah Goldstein int result = thread->run(func, arg, stack, stacksize, guardsize, 826a185718SNoah Goldstein detachstate == PTHREAD_CREATE_DETACHED); 836a185718SNoah Goldstein if (result != 0 && result != EPERM && result != EINVAL) 8470c8d12bSSiva Chandra Reddy return EAGAIN; 8570c8d12bSSiva Chandra Reddy return result; 8670c8d12bSSiva Chandra Reddy } 8770c8d12bSSiva Chandra Reddy 885ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL 89