Threading.h revision 360784
1//===-- llvm/Support/Threading.h - Control multithreading mode --*- 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 file declares helper functions for running LLVM in a multi-threaded 10// environment. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_SUPPORT_THREADING_H 15#define LLVM_SUPPORT_THREADING_H 16 17#include "llvm/ADT/FunctionExtras.h" 18#include "llvm/ADT/SmallVector.h" 19#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX 20#include "llvm/Support/Compiler.h" 21#include <ciso646> // So we can check the C++ standard lib macros. 22#include <functional> 23 24#if defined(_MSC_VER) 25// MSVC's call_once implementation worked since VS 2015, which is the minimum 26// supported version as of this writing. 27#define LLVM_THREADING_USE_STD_CALL_ONCE 1 28#elif defined(LLVM_ON_UNIX) && \ 29 (defined(_LIBCPP_VERSION) || \ 30 !(defined(__NetBSD__) || defined(__OpenBSD__) || \ 31 (defined(__ppc__) || defined(__PPC__)))) 32// std::call_once from libc++ is used on all Unix platforms. Other 33// implementations like libstdc++ are known to have problems on NetBSD, 34// OpenBSD and PowerPC. 35#define LLVM_THREADING_USE_STD_CALL_ONCE 1 36#elif defined(LLVM_ON_UNIX) && \ 37 ((defined(__ppc__) || defined(__PPC__)) && defined(__LITTLE_ENDIAN__)) 38#define LLVM_THREADING_USE_STD_CALL_ONCE 1 39#else 40#define LLVM_THREADING_USE_STD_CALL_ONCE 0 41#endif 42 43#if LLVM_THREADING_USE_STD_CALL_ONCE 44#include <mutex> 45#else 46#include "llvm/Support/Atomic.h" 47#endif 48 49namespace llvm { 50class Twine; 51 52/// Returns true if LLVM is compiled with support for multi-threading, and 53/// false otherwise. 54bool llvm_is_multithreaded(); 55 56/// Execute the given \p UserFn on a separate thread, passing it the provided \p 57/// UserData and waits for thread completion. 58/// 59/// This function does not guarantee that the code will actually be executed 60/// on a separate thread or honoring the requested stack size, but tries to do 61/// so where system support is available. 62/// 63/// \param UserFn - The callback to execute. 64/// \param UserData - An argument to pass to the callback function. 65/// \param StackSizeInBytes - A requested size (in bytes) for the thread stack 66/// (or None for default) 67void llvm_execute_on_thread( 68 void (*UserFn)(void *), void *UserData, 69 llvm::Optional<unsigned> StackSizeInBytes = llvm::None); 70 71/// Schedule the given \p Func for execution on a separate thread, then return 72/// to the caller immediately. Roughly equivalent to 73/// `std::thread(Func).detach()`, except it allows requesting a specific stack 74/// size, if supported for the platform. 75/// 76/// This function would report a fatal error if it can't execute the code 77/// on a separate thread. 78/// 79/// \param Func - The callback to execute. 80/// \param StackSizeInBytes - A requested size (in bytes) for the thread stack 81/// (or None for default) 82void llvm_execute_on_thread_async( 83 llvm::unique_function<void()> Func, 84 llvm::Optional<unsigned> StackSizeInBytes = llvm::None); 85 86#if LLVM_THREADING_USE_STD_CALL_ONCE 87 88 typedef std::once_flag once_flag; 89 90#else 91 92 enum InitStatus { Uninitialized = 0, Wait = 1, Done = 2 }; 93 94 /// The llvm::once_flag structure 95 /// 96 /// This type is modeled after std::once_flag to use with llvm::call_once. 97 /// This structure must be used as an opaque object. It is a struct to force 98 /// autoinitialization and behave like std::once_flag. 99 struct once_flag { 100 volatile sys::cas_flag status = Uninitialized; 101 }; 102 103#endif 104 105 /// Execute the function specified as a parameter once. 106 /// 107 /// Typical usage: 108 /// \code 109 /// void foo() {...}; 110 /// ... 111 /// static once_flag flag; 112 /// call_once(flag, foo); 113 /// \endcode 114 /// 115 /// \param flag Flag used for tracking whether or not this has run. 116 /// \param F Function to call once. 117 template <typename Function, typename... Args> 118 void call_once(once_flag &flag, Function &&F, Args &&... ArgList) { 119#if LLVM_THREADING_USE_STD_CALL_ONCE 120 std::call_once(flag, std::forward<Function>(F), 121 std::forward<Args>(ArgList)...); 122#else 123 // For other platforms we use a generic (if brittle) version based on our 124 // atomics. 125 sys::cas_flag old_val = sys::CompareAndSwap(&flag.status, Wait, Uninitialized); 126 if (old_val == Uninitialized) { 127 std::forward<Function>(F)(std::forward<Args>(ArgList)...); 128 sys::MemoryFence(); 129 TsanIgnoreWritesBegin(); 130 TsanHappensBefore(&flag.status); 131 flag.status = Done; 132 TsanIgnoreWritesEnd(); 133 } else { 134 // Wait until any thread doing the call has finished. 135 sys::cas_flag tmp = flag.status; 136 sys::MemoryFence(); 137 while (tmp != Done) { 138 tmp = flag.status; 139 sys::MemoryFence(); 140 } 141 } 142 TsanHappensAfter(&flag.status); 143#endif 144 } 145 146 /// Get the amount of currency to use for tasks requiring significant 147 /// memory or other resources. Currently based on physical cores, if 148 /// available for the host system, otherwise falls back to 149 /// thread::hardware_concurrency(). 150 /// Returns 1 when LLVM is configured with LLVM_ENABLE_THREADS=OFF 151 unsigned heavyweight_hardware_concurrency(); 152 153 /// Get the number of threads that the current program can execute 154 /// concurrently. On some systems std::thread::hardware_concurrency() returns 155 /// the total number of cores, without taking affinity into consideration. 156 /// Returns 1 when LLVM is configured with LLVM_ENABLE_THREADS=OFF. 157 /// Fallback to std::thread::hardware_concurrency() if sched_getaffinity is 158 /// not available. 159 unsigned hardware_concurrency(); 160 161 /// Return the current thread id, as used in various OS system calls. 162 /// Note that not all platforms guarantee that the value returned will be 163 /// unique across the entire system, so portable code should not assume 164 /// this. 165 uint64_t get_threadid(); 166 167 /// Get the maximum length of a thread name on this platform. 168 /// A value of 0 means there is no limit. 169 uint32_t get_max_thread_name_length(); 170 171 /// Set the name of the current thread. Setting a thread's name can 172 /// be helpful for enabling useful diagnostics under a debugger or when 173 /// logging. The level of support for setting a thread's name varies 174 /// wildly across operating systems, and we only make a best effort to 175 /// perform the operation on supported platforms. No indication of success 176 /// or failure is returned. 177 void set_thread_name(const Twine &Name); 178 179 /// Get the name of the current thread. The level of support for 180 /// getting a thread's name varies wildly across operating systems, and it 181 /// is not even guaranteed that if you can successfully set a thread's name 182 /// that you can later get it back. This function is intended for diagnostic 183 /// purposes, and as with setting a thread's name no indication of whether 184 /// the operation succeeded or failed is returned. 185 void get_thread_name(SmallVectorImpl<char> &Name); 186 187 enum class ThreadPriority { 188 Background = 0, 189 Default = 1, 190 }; 191 /// If priority is Background tries to lower current threads priority such 192 /// that it does not affect foreground tasks significantly. Can be used for 193 /// long-running, latency-insensitive tasks to make sure cpu is not hogged by 194 /// this task. 195 /// If the priority is default tries to restore current threads priority to 196 /// default scheduling priority. 197 enum class SetThreadPriorityResult { FAILURE, SUCCESS }; 198 SetThreadPriorityResult set_thread_priority(ThreadPriority Priority); 199} 200 201#endif 202