1//===--- A platform independent indirection for a thread class --*- C++ -*-===//
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#ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_THREAD_H
10#define LLVM_LIBC_SRC___SUPPORT_THREADS_THREAD_H
11
12#include "src/__support/CPP/atomic.h"
13#include "src/__support/CPP/optional.h"
14#include "src/__support/CPP/string_view.h"
15#include "src/__support/CPP/stringstream.h"
16#include "src/__support/macros/attributes.h"
17#include "src/__support/macros/properties/architectures.h"
18
19#include <linux/param.h> // for exec_pagesize.
20
21#include <stddef.h> // For size_t
22#include <stdint.h>
23
24namespace LIBC_NAMESPACE {
25
26using ThreadRunnerPosix = void *(void *);
27using ThreadRunnerStdc = int(void *);
28
29union ThreadRunner {
30 ThreadRunnerPosix *posix_runner;
31 ThreadRunnerStdc *stdc_runner;
32};
33
34union ThreadReturnValue {
35 void *posix_retval;
36 int stdc_retval;
37 constexpr ThreadReturnValue() : posix_retval(nullptr) {}
38 constexpr ThreadReturnValue(int r) : stdc_retval(r) {}
39 constexpr ThreadReturnValue(void *r) : posix_retval(r) {}
40};
41
42#if (defined(LIBC_TARGET_ARCH_IS_AARCH64) || \
43 defined(LIBC_TARGET_ARCH_IS_X86_64) || \
44 defined(LIBC_TARGET_ARCH_IS_ANY_RISCV))
45constexpr unsigned int STACK_ALIGNMENT = 16;
46#endif
47// TODO: Provide stack alignment requirements for other architectures.
48
49enum class DetachState : uint32_t {
50 JOINABLE = 0x11,
51 EXITING = 0x22,
52 DETACHED = 0x33
53};
54
55enum class ThreadStyle : uint8_t { POSIX = 0x1, STDC = 0x2 };
56
57// Detach type is useful in testing the detach operation.
58enum class DetachType : int {
59 // Indicates that the detach operation just set the detach state to DETACHED
60 // and returned.
61 SIMPLE = 1,
62
63 // Indicates that the detach operation performed thread cleanup.
64 CLEANUP = 2
65};
66
67class ThreadAtExitCallbackMgr;
68
69// A data type to hold common thread attributes which have to be stored as
70// thread state. Note that this is different from public attribute types like
71// pthread_attr_t which might contain information which need not be saved as
72// part of a thread's state. For example, the stack guard size.
73//
74// Thread attributes are typically stored on the stack. So, we align as required
75// for the target architecture.
76struct alignas(STACK_ALIGNMENT) ThreadAttributes {
77 // We want the "detach_state" attribute to be an atomic value as it could be
78 // updated by one thread while the self thread is reading it. It is a tristate
79 // variable with the following state transitions:
80 // 1. The a thread is created in a detached state, then user code should never
81 // call a detach or join function. Calling either of them can lead to
82 // undefined behavior.
83 // The value of |detach_state| is expected to be DetachState::DETACHED for
84 // its lifetime.
85 // 2. If a thread is created in a joinable state, |detach_state| will start
86 // with the value DetachState::JOINABLE. Another thread can detach this
87 // thread before it exits. The state transitions will as follows:
88 // (a) If the detach method sees the state as JOINABLE, then it will
89 // compare exchange to a state of DETACHED. The thread will clean
90 // itself up after it finishes.
91 // (b) If the detach method does not see JOINABLE in (a), then it will
92 // conclude that the thread is EXITING and will wait until the thread
93 // exits. It will clean up the thread resources once the thread
94 // exits.
95 cpp::Atomic<uint32_t> detach_state;
96 void *stack; // Pointer to the thread stack
97 unsigned long long stacksize; // Size of the stack
98 unsigned long long guardsize; // Guard size on stack
99 uintptr_t tls; // Address to the thread TLS memory
100 uintptr_t tls_size; // The size of area pointed to by |tls|.
101 unsigned char owned_stack; // Indicates if the thread owns this stack memory
102 int tid;
103 ThreadStyle style;
104 ThreadReturnValue retval;
105 ThreadAtExitCallbackMgr *atexit_callback_mgr;
106 void *platform_data;
107
108 constexpr ThreadAttributes()
109 : detach_state(uint32_t(DetachState::DETACHED)), stack(nullptr),
110 stacksize(0), guardsize(0), tls(0), tls_size(0), owned_stack(false),
111 tid(-1), style(ThreadStyle::POSIX), retval(),
112 atexit_callback_mgr(nullptr), platform_data(nullptr) {}
113};
114
115using TSSDtor = void(void *);
116
117// Create a new TSS key and associate the |dtor| as the corresponding
118// destructor. Can be used to implement public functions like
119// pthread_key_create.
120cpp::optional<unsigned int> new_tss_key(TSSDtor *dtor);
121
122// Delete the |key|. Can be used to implement public functions like
123// pthread_key_delete.
124//
125// Return true on success, false on failure.
126bool tss_key_delete(unsigned int key);
127
128// Set the value associated with |key| for the current thread. Can be used
129// to implement public functions like pthread_setspecific.
130//
131// Return true on success, false on failure.
132bool set_tss_value(unsigned int key, void *value);
133
134// Return the value associated with |key| for the current thread. Return
135// nullptr if |key| is invalid. Can be used to implement public functions like
136// pthread_getspecific.
137void *get_tss_value(unsigned int key);
138
139struct Thread {
140 // NB: Default stacksize of 64kb is exceedingly small compared to the 2mb norm
141 // and will break many programs expecting the full 2mb.
142 static constexpr size_t DEFAULT_STACKSIZE = 1 << 16;
143 static constexpr size_t DEFAULT_GUARDSIZE = EXEC_PAGESIZE;
144 static constexpr bool DEFAULT_DETACHED = false;
145
146 ThreadAttributes *attrib;
147
148 constexpr Thread() : attrib(nullptr) {}
149 constexpr Thread(ThreadAttributes *attr) : attrib(attr) {}
150
151 int run(ThreadRunnerPosix *func, void *arg, void *stack = nullptr,
152 size_t stacksize = DEFAULT_STACKSIZE,
153 size_t guardsize = DEFAULT_GUARDSIZE,
154 bool detached = DEFAULT_DETACHED) {
155 ThreadRunner runner;
156 runner.posix_runner = func;
157 return run(style: ThreadStyle::POSIX, runner, arg, stack, stacksize, guardsize,
158 detached);
159 }
160
161 int run(ThreadRunnerStdc *func, void *arg, void *stack = nullptr,
162 size_t stacksize = DEFAULT_STACKSIZE,
163 size_t guardsize = DEFAULT_GUARDSIZE,
164 bool detached = DEFAULT_DETACHED) {
165 ThreadRunner runner;
166 runner.stdc_runner = func;
167 return run(style: ThreadStyle::STDC, runner, arg, stack, stacksize, guardsize,
168 detached);
169 }
170
171 int join(int *val) {
172 ThreadReturnValue retval;
173 int status = join(retval);
174 if (status != 0)
175 return status;
176 if (val != nullptr)
177 *val = retval.stdc_retval;
178 return 0;
179 }
180
181 int join(void **val) {
182 ThreadReturnValue retval;
183 int status = join(retval);
184 if (status != 0)
185 return status;
186 if (val != nullptr)
187 *val = retval.posix_retval;
188 return 0;
189 }
190
191 // Platform should implement the functions below.
192
193 // Return 0 on success or an error value on failure.
194 int run(ThreadStyle style, ThreadRunner runner, void *arg, void *stack,
195 size_t stacksize, size_t guardsize, bool detached);
196
197 // Return 0 on success or an error value on failure.
198 int join(ThreadReturnValue &retval);
199
200 // Detach a joinable thread.
201 //
202 // This method does not have error return value. However, the type of detach
203 // is returned to help with testing.
204 int detach();
205
206 // Wait for the thread to finish. This method can only be called
207 // if:
208 // 1. A detached thread is guaranteed to be running.
209 // 2. A joinable thread has not been detached or joined. As long as it has
210 // not been detached or joined, wait can be called multiple times.
211 //
212 // Also, only one thread can wait and expect to get woken up when the thread
213 // finishes.
214 //
215 // NOTE: This function is to be used for testing only. There is no standard
216 // which requires exposing it via a public API.
217 void wait();
218
219 // Return true if this thread is equal to the other thread.
220 bool operator==(const Thread &other) const;
221
222 // Set the name of the thread. Return the error number on error.
223 int set_name(const cpp::string_view &name);
224
225 // Return the name of the thread in |name|. Return the error number of error.
226 int get_name(cpp::StringStream &name) const;
227};
228
229extern LIBC_THREAD_LOCAL Thread self;
230
231// Platforms should implement this function.
232[[noreturn]] void thread_exit(ThreadReturnValue retval, ThreadStyle style);
233
234namespace internal {
235// Internal namespace containing utilities which are to be used by platform
236// implementations of threads.
237
238// Return the current thread's atexit callback manager. After thread startup
239// but before running the thread function, platform implementations should
240// set the "atexit_callback_mgr" field of the thread's attributes to the value
241// returned by this function.
242ThreadAtExitCallbackMgr *get_thread_atexit_callback_mgr();
243
244// Call the currently registered thread specific atexit callbacks. Useful for
245// implementing the thread_exit function.
246void call_atexit_callbacks(ThreadAttributes *attrib);
247
248} // namespace internal
249
250} // namespace LIBC_NAMESPACE
251
252#endif // LLVM_LIBC_SRC___SUPPORT_THREADS_THREAD_H
253

source code of libc/src/__support/threads/thread.h