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