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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of libc/src/pthread/pthread_create.cpp