1//===-- llvm/Support/Threading.h - Control multithreading mode --*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file declares helper functions for running LLVM in a multi-threaded 11// environment. 12// 13//===----------------------------------------------------------------------===// 14 15#ifndef LLVM_SUPPORT_THREADING_H 16#define LLVM_SUPPORT_THREADING_H 17 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__) || defined(__ppc__))) 31// std::call_once from libc++ is used on all Unix platforms. Other 32// implementations like libstdc++ are known to have problems on NetBSD, 33// OpenBSD and PowerPC. 34#define LLVM_THREADING_USE_STD_CALL_ONCE 1 35#else 36#define LLVM_THREADING_USE_STD_CALL_ONCE 0 37#endif 38 39#if LLVM_THREADING_USE_STD_CALL_ONCE 40#include <mutex> 41#else 42#include "llvm/Support/Atomic.h" 43#endif 44 45namespace llvm { 46class Twine; 47 48/// Returns true if LLVM is compiled with support for multi-threading, and 49/// false otherwise. 50bool llvm_is_multithreaded(); 51 52/// llvm_execute_on_thread - Execute the given \p UserFn on a separate 53/// thread, passing it the provided \p UserData and waits for thread 54/// completion. 55/// 56/// This function does not guarantee that the code will actually be executed 57/// on a separate thread or honoring the requested stack size, but tries to do 58/// so where system support is available. 59/// 60/// \param UserFn - The callback to execute. 61/// \param UserData - An argument to pass to the callback function. 62/// \param RequestedStackSize - If non-zero, a requested size (in bytes) for 63/// the thread stack. 64void llvm_execute_on_thread(void (*UserFn)(void *), void *UserData, 65 unsigned RequestedStackSize = 0); 66 67#if LLVM_THREADING_USE_STD_CALL_ONCE 68 69 typedef std::once_flag once_flag; 70 71#else 72 73 enum InitStatus { Uninitialized = 0, Wait = 1, Done = 2 }; 74 75 /// \brief The llvm::once_flag structure 76 /// 77 /// This type is modeled after std::once_flag to use with llvm::call_once. 78 /// This structure must be used as an opaque object. It is a struct to force 79 /// autoinitialization and behave like std::once_flag. 80 struct once_flag { 81 volatile sys::cas_flag status = Uninitialized; 82 }; 83 84#endif 85 86 /// \brief Execute the function specified as a parameter once. 87 /// 88 /// Typical usage: 89 /// \code 90 /// void foo() {...}; 91 /// ... 92 /// static once_flag flag; 93 /// call_once(flag, foo); 94 /// \endcode 95 /// 96 /// \param flag Flag used for tracking whether or not this has run. 97 /// \param F Function to call once. 98 template <typename Function, typename... Args> 99 void call_once(once_flag &flag, Function &&F, Args &&... ArgList) { 100#if LLVM_THREADING_USE_STD_CALL_ONCE 101 std::call_once(flag, std::forward<Function>(F), 102 std::forward<Args>(ArgList)...); 103#else 104 // For other platforms we use a generic (if brittle) version based on our 105 // atomics. 106 sys::cas_flag old_val = sys::CompareAndSwap(&flag.status, Wait, Uninitialized); 107 if (old_val == Uninitialized) { 108 std::forward<Function>(F)(std::forward<Args>(ArgList)...); 109 sys::MemoryFence(); 110 TsanIgnoreWritesBegin(); 111 TsanHappensBefore(&flag.status); 112 flag.status = Done; 113 TsanIgnoreWritesEnd(); 114 } else { 115 // Wait until any thread doing the call has finished. 116 sys::cas_flag tmp = flag.status; 117 sys::MemoryFence(); 118 while (tmp != Done) { 119 tmp = flag.status; 120 sys::MemoryFence(); 121 } 122 } 123 TsanHappensAfter(&flag.status); 124#endif 125 } 126 127 /// Get the amount of currency to use for tasks requiring significant 128 /// memory or other resources. Currently based on physical cores, if 129 /// available for the host system, otherwise falls back to 130 /// thread::hardware_concurrency(). 131 /// Returns 1 when LLVM is configured with LLVM_ENABLE_THREADS=OFF 132 unsigned heavyweight_hardware_concurrency(); 133 134 /// Get the number of threads that the current program can execute 135 /// concurrently. On some systems std::thread::hardware_concurrency() returns 136 /// the total number of cores, without taking affinity into consideration. 137 /// Returns 1 when LLVM is configured with LLVM_ENABLE_THREADS=OFF. 138 /// Fallback to std::thread::hardware_concurrency() if sched_getaffinity is 139 /// not available. 140 unsigned hardware_concurrency(); 141 142 /// \brief Return the current thread id, as used in various OS system calls. 143 /// Note that not all platforms guarantee that the value returned will be 144 /// unique across the entire system, so portable code should not assume 145 /// this. 146 uint64_t get_threadid(); 147 148 /// \brief Get the maximum length of a thread name on this platform. 149 /// A value of 0 means there is no limit. 150 uint32_t get_max_thread_name_length(); 151 152 /// \brief Set the name of the current thread. Setting a thread's name can 153 /// be helpful for enabling useful diagnostics under a debugger or when 154 /// logging. The level of support for setting a thread's name varies 155 /// wildly across operating systems, and we only make a best effort to 156 /// perform the operation on supported platforms. No indication of success 157 /// or failure is returned. 158 void set_thread_name(const Twine &Name); 159 160 /// \brief Get the name of the current thread. The level of support for 161 /// getting a thread's name varies wildly across operating systems, and it 162 /// is not even guaranteed that if you can successfully set a thread's name 163 /// that you can later get it back. This function is intended for diagnostic 164 /// purposes, and as with setting a thread's name no indication of whether 165 /// the operation succeeded or failed is returned. 166 void get_thread_name(SmallVectorImpl<char> &Name); 167} 168 169#endif 170