LLVM  14.0.0git
thread.h
Go to the documentation of this file.
1 //===-- llvm/Support/thread.h - Wrapper for <thread> ------------*- 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 // This header is a wrapper for <thread> that works around problems with the
10 // MSVC headers when exceptions are disabled. It also provides llvm::thread,
11 // which is either a typedef of std::thread or a replacement that calls the
12 // function synchronously depending on the value of LLVM_ENABLE_THREADS.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #ifndef LLVM_SUPPORT_THREAD_H
17 #define LLVM_SUPPORT_THREAD_H
18 
19 #include "llvm/ADT/Optional.h"
20 #include "llvm/Config/llvm-config.h"
21 
22 #ifdef _WIN32
23 typedef unsigned long DWORD;
24 typedef void *PVOID;
25 typedef PVOID HANDLE;
26 #endif
27 
28 #if LLVM_ENABLE_THREADS
29 
30 #include <thread>
31 
32 namespace llvm {
33 
34 #if LLVM_ON_UNIX || _WIN32
35 
36 /// LLVM thread following std::thread interface with added constructor to
37 /// specify stack size.
38 class thread {
39  template <typename FPtr, typename... Args, size_t... Indices>
40  static void Apply(std::tuple<FPtr, Args...> &Callee,
41  std::index_sequence<Indices...>) {
42  std::move(std::get<0>(Callee))(std::move(std::get<Indices + 1>(Callee))...);
43  }
44 
45  template <typename CalleeTuple> static void GenericThreadProxy(void *Ptr) {
46  std::unique_ptr<CalleeTuple> Callee(static_cast<CalleeTuple *>(Ptr));
47 
48  // FIXME: use std::apply when C++17 is allowed.
49  std::make_index_sequence<std::tuple_size<CalleeTuple>() - 1> Indices{};
50  Apply(*Callee.get(), Indices);
51  }
52 
53 public:
54 #if LLVM_ON_UNIX
55  using native_handle_type = pthread_t;
56  using id = pthread_t;
57  using start_routine_type = void *(*)(void *);
58 
59  template <typename CalleeTuple> static void *ThreadProxy(void *Ptr) {
60  GenericThreadProxy<CalleeTuple>(Ptr);
61  return nullptr;
62  }
63 #elif _WIN32
64  using native_handle_type = HANDLE;
65  using id = DWORD;
66  using start_routine_type = unsigned(__stdcall *)(void *);
67 
68  template <typename CalleeTuple>
69  static unsigned __stdcall ThreadProxy(void *Ptr) {
70  GenericThreadProxy<CalleeTuple>(Ptr);
71  return 0;
72  }
73 #endif
74 
76 
77  thread() : Thread(native_handle_type()) {}
78  thread(thread &&Other) noexcept
79  : Thread(std::exchange(Other.Thread, native_handle_type())) {}
80 
81  template <class Function, class... Args>
82  explicit thread(Function &&f, Args &&...args)
83  : thread(DefaultStackSize, f, args...) {}
84 
85  template <class Function, class... Args>
86  explicit thread(llvm::Optional<unsigned> StackSizeInBytes, Function &&f,
87  Args &&...args);
88  thread(const thread &) = delete;
89 
90  ~thread() {
91  if (joinable())
92  std::terminate();
93  }
94 
95  thread &operator=(thread &&Other) noexcept {
96  if (joinable())
97  std::terminate();
98  Thread = std::exchange(Other.Thread, native_handle_type());
99  return *this;
100  }
101 
102  bool joinable() const noexcept { return Thread != native_handle_type(); }
103 
104  inline id get_id() const noexcept;
105 
106  native_handle_type native_handle() const noexcept { return Thread; }
107 
108  static unsigned hardware_concurrency() {
110  };
111 
112  inline void join();
113  inline void detach();
114 
115  void swap(llvm::thread &Other) noexcept { std::swap(Thread, Other.Thread); }
116 
117 private:
118  native_handle_type Thread;
119 };
120 
123  llvm::Optional<unsigned> StackSizeInBytes);
128 
129 template <class Function, class... Args>
131  Args &&...args) {
133  typename std::decay<Args>::type...>
134  CalleeTuple;
135  std::unique_ptr<CalleeTuple> Callee(
136  new CalleeTuple(std::forward<Function>(f), std::forward<Args>(args)...));
137 
138  Thread = llvm_execute_on_thread_impl(ThreadProxy<CalleeTuple>, Callee.get(),
139  StackSizeInBytes);
140  if (Thread != native_handle_type())
141  Callee.release();
142 }
143 
145  return llvm_thread_get_id_impl(Thread);
146 }
147 
148 void thread::join() {
149  llvm_thread_join_impl(Thread);
150  Thread = native_handle_type();
151 }
152 
154  llvm_thread_detach_impl(Thread);
155  Thread = native_handle_type();
156 }
157 
158 namespace this_thread {
160 } // namespace this_thread
161 
162 #else // !LLVM_ON_UNIX && !_WIN32
163 
164 /// std::thread backed implementation of llvm::thread interface that ignores the
165 /// stack size request.
166 class thread {
167 public:
168  using native_handle_type = std::thread::native_handle_type;
169  using id = std::thread::id;
170 
171  thread() : Thread(std::thread()) {}
172  thread(thread &&Other) noexcept
173  : Thread(std::exchange(Other.Thread, std::thread())) {}
174 
175  template <class Function, class... Args>
176  explicit thread(llvm::Optional<unsigned> StackSizeInBytes, Function &&f,
177  Args &&...args)
178  : Thread(std::forward<Function>(f), std::forward<Args>(args)...) {}
179 
180  template <class Function, class... Args>
181  explicit thread(Function &&f, Args &&...args) : Thread(f, args...) {}
182 
183  thread(const thread &) = delete;
184 
185  ~thread() {}
186 
187  thread &operator=(thread &&Other) noexcept {
188  Thread = std::exchange(Other.Thread, std::thread());
189  return *this;
190  }
191 
192  bool joinable() const noexcept { return Thread.joinable(); }
193 
194  id get_id() const noexcept { return Thread.get_id(); }
195 
196  native_handle_type native_handle() noexcept { return Thread.native_handle(); }
197 
198  static unsigned hardware_concurrency() {
200  };
201 
202  inline void join() { Thread.join(); }
203  inline void detach() { Thread.detach(); }
204 
205  void swap(llvm::thread &Other) noexcept { std::swap(Thread, Other.Thread); }
206 
207 private:
208  std::thread Thread;
209 };
210 
211 namespace this_thread {
212  inline thread::id get_id() { return std::this_thread::get_id(); }
213 }
214 
215 #endif // LLVM_ON_UNIX || _WIN32
216 
217 } // namespace llvm
218 
219 #else // !LLVM_ENABLE_THREADS
220 
221 #include <utility>
222 
223 namespace llvm {
224 
225 struct thread {
226  thread() {}
227  thread(thread &&other) {}
228  template <class Function, class... Args>
229  explicit thread(llvm::Optional<unsigned> StackSizeInBytes, Function &&f,
230  Args &&...args) {
231  f(std::forward<Args>(args)...);
232  }
233  template <class Function, class... Args>
234  explicit thread(Function &&f, Args &&...args) {
235  f(std::forward<Args>(args)...);
236  }
237  thread(const thread &) = delete;
238 
239  void detach() {
240  report_fatal_error("Detaching from a thread does not make sense with no "
241  "threading support");
242  }
243  void join() {}
244  static unsigned hardware_concurrency() { return 1; };
245 };
246 
247 } // namespace llvm
248 
249 #endif // LLVM_ENABLE_THREADS
250 
251 #endif // LLVM_SUPPORT_THREAD_H
llvm::this_thread::get_id
thread::id get_id()
Definition: thread.h:159
llvm::llvm_thread_get_id_impl
thread::id llvm_thread_get_id_impl(thread::native_handle_type Thread)
llvm::thread::operator=
thread & operator=(thread &&Other) noexcept
Definition: thread.h:95
llvm::hardware_concurrency
ThreadPoolStrategy hardware_concurrency(unsigned ThreadCount=0)
Returns a default thread strategy where all available hardware resources are to be used,...
Definition: Threading.h:188
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
Optional.h
llvm::thread::hardware_concurrency
static unsigned hardware_concurrency()
Definition: thread.h:108
llvm::Function
Definition: Function.h:62
llvm::thread::ThreadProxy
static void * ThreadProxy(void *Ptr)
Definition: thread.h:59
Thread
uint64_t Thread
Definition: Profile.cpp:48
llvm::llvm_thread_get_current_id_impl
thread::id llvm_thread_get_current_id_impl()
llvm::thread::thread
thread(Function &&f, Args &&...args)
Definition: thread.h:82
llvm::llvm_thread_join_impl
void llvm_thread_join_impl(thread::native_handle_type Thread)
llvm::llvm_thread_detach_impl
void llvm_thread_detach_impl(thread::native_handle_type Thread)
llvm::llvm_execute_on_thread_impl
thread::native_handle_type llvm_execute_on_thread_impl(thread::start_routine_type ThreadFunc, void *Arg, llvm::Optional< unsigned > StackSizeInBytes)
llvm::Optional< unsigned >
Arg
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
Definition: AMDGPULibCalls.cpp:206
f
Itanium Name Demangler i e convert the string _Z1fv into f()". You can also use the CRTP base ManglingParser to perform some simple analysis on the mangled name
llvm::thread::id
pthread_t id
Definition: thread.h:56
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
llvm::thread::get_id
id get_id() const noexcept
Definition: thread.h:144
llvm::thread::detach
void detach()
Definition: thread.h:153
type
AMD64 Optimization Manual has some nice information about optimizing integer multiplication by a constant How much of it applies to Intel s X86 implementation There are definite trade offs to xmm0 cvttss2siq rdx jb L3 subss xmm0 rax cvttss2siq rdx xorq rdx rax ret instead of xmm1 cvttss2siq rcx movaps xmm2 subss xmm2 cvttss2siq rax rdx xorq rax ucomiss xmm0 cmovb rax ret Seems like the jb branch has high likelihood of being taken It would have saved a few instructions It s not possible to reference and DH registers in an instruction requiring REX prefix divb and mulb both produce results in AH If isel emits a CopyFromReg which gets turned into a movb and that can be allocated a r8b r15b To get around isel emits a CopyFromReg from AX and then right shift it down by and truncate it It s not pretty but it works We need some register allocation magic to make the hack go which would often require a callee saved register Callees usually need to keep this value live for most of their body so it doesn t add a significant burden on them We currently implement this in however this is suboptimal because it means that it would be quite awkward to implement the optimization for callers A better implementation would be to relax the LLVM IR rules for sret arguments to allow a function with an sret argument to have a non void return type
Definition: README-X86-64.txt:70
const
aarch64 promote const
Definition: AArch64PromoteConstant.cpp:232
llvm::thread
LLVM thread following std::thread interface with added constructor to specify stack size.
Definition: thread.h:38
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::AMDGPU::SDWA::DWORD
@ DWORD
Definition: SIDefines.h:656
std::swap
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:840
llvm::thread::thread
thread()
Definition: thread.h:77
llvm::ReplayInlineScope::Function
@ Function
llvm::thread::join
void join()
Definition: thread.h:148
llvm::thread::~thread
~thread()
Definition: thread.h:90
llvm::thread::native_handle
native_handle_type native_handle() const noexcept
Definition: thread.h:106
Callee
amdgpu Simplify well known AMD library false FunctionCallee Callee
Definition: AMDGPULibCalls.cpp:206
llvm::thread::DefaultStackSize
static const llvm::Optional< unsigned > DefaultStackSize
Definition: thread.h:75
std
Definition: BitVector.h:838
llvm::thread::joinable
bool joinable() const noexcept
Definition: thread.h:102
llvm::thread::native_handle_type
pthread_t native_handle_type
Definition: thread.h:55
llvm::thread::thread
thread(thread &&Other) noexcept
Definition: thread.h:78
llvm::AMDGPU::HSAMD::Kernel::Key::Args
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Definition: AMDGPUMetadata.h:389
llvm::thread::swap
void swap(llvm::thread &Other) noexcept
Definition: thread.h:115
llvm::thread::start_routine_type
void *(*)(void *) start_routine_type
Definition: thread.h:57
Other
Optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:1184