1218885Sdim//===-- llvm/Support/Threading.h - Control multithreading mode --*- C++ -*-===// 2218885Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6218885Sdim// 7218885Sdim//===----------------------------------------------------------------------===// 8218885Sdim// 9276479Sdim// This file declares helper functions for running LLVM in a multi-threaded 10276479Sdim// environment. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14249423Sdim#ifndef LLVM_SUPPORT_THREADING_H 15249423Sdim#define LLVM_SUPPORT_THREADING_H 16218885Sdim 17360784Sdim#include "llvm/ADT/FunctionExtras.h" 18321369Sdim#include "llvm/ADT/SmallVector.h" 19309124Sdim#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX 20309124Sdim#include "llvm/Support/Compiler.h" 21309124Sdim#include <ciso646> // So we can check the C++ standard lib macros. 22309124Sdim#include <functional> 23309124Sdim 24321369Sdim#if defined(_MSC_VER) 25321369Sdim// MSVC's call_once implementation worked since VS 2015, which is the minimum 26321369Sdim// supported version as of this writing. 27321369Sdim#define LLVM_THREADING_USE_STD_CALL_ONCE 1 28321369Sdim#elif defined(LLVM_ON_UNIX) && \ 29321369Sdim (defined(_LIBCPP_VERSION) || \ 30344779Sdim !(defined(__NetBSD__) || defined(__OpenBSD__) || \ 31344779Sdim (defined(__ppc__) || defined(__PPC__)))) 32310194Sdim// std::call_once from libc++ is used on all Unix platforms. Other 33310194Sdim// implementations like libstdc++ are known to have problems on NetBSD, 34310194Sdim// OpenBSD and PowerPC. 35309124Sdim#define LLVM_THREADING_USE_STD_CALL_ONCE 1 36353358Sdim#elif defined(LLVM_ON_UNIX) && \ 37353358Sdim ((defined(__ppc__) || defined(__PPC__)) && defined(__LITTLE_ENDIAN__)) 38353358Sdim#define LLVM_THREADING_USE_STD_CALL_ONCE 1 39309124Sdim#else 40309124Sdim#define LLVM_THREADING_USE_STD_CALL_ONCE 0 41309124Sdim#endif 42309124Sdim 43309124Sdim#if LLVM_THREADING_USE_STD_CALL_ONCE 44309124Sdim#include <mutex> 45309124Sdim#else 46309124Sdim#include "llvm/Support/Atomic.h" 47309124Sdim#endif 48309124Sdim 49218885Sdimnamespace llvm { 50321369Sdimclass Twine; 51218885Sdim 52321369Sdim/// Returns true if LLVM is compiled with support for multi-threading, and 53321369Sdim/// false otherwise. 54321369Sdimbool llvm_is_multithreaded(); 55309124Sdim 56360784Sdim/// Execute the given \p UserFn on a separate thread, passing it the provided \p 57360784Sdim/// UserData and waits for thread completion. 58321369Sdim/// 59321369Sdim/// This function does not guarantee that the code will actually be executed 60321369Sdim/// on a separate thread or honoring the requested stack size, but tries to do 61321369Sdim/// so where system support is available. 62321369Sdim/// 63321369Sdim/// \param UserFn - The callback to execute. 64321369Sdim/// \param UserData - An argument to pass to the callback function. 65360784Sdim/// \param StackSizeInBytes - A requested size (in bytes) for the thread stack 66360784Sdim/// (or None for default) 67360784Sdimvoid llvm_execute_on_thread( 68360784Sdim void (*UserFn)(void *), void *UserData, 69360784Sdim llvm::Optional<unsigned> StackSizeInBytes = llvm::None); 70321369Sdim 71360784Sdim/// Schedule the given \p Func for execution on a separate thread, then return 72360784Sdim/// to the caller immediately. Roughly equivalent to 73360784Sdim/// `std::thread(Func).detach()`, except it allows requesting a specific stack 74360784Sdim/// size, if supported for the platform. 75360784Sdim/// 76360784Sdim/// This function would report a fatal error if it can't execute the code 77360784Sdim/// on a separate thread. 78360784Sdim/// 79360784Sdim/// \param Func - The callback to execute. 80360784Sdim/// \param StackSizeInBytes - A requested size (in bytes) for the thread stack 81360784Sdim/// (or None for default) 82360784Sdimvoid llvm_execute_on_thread_async( 83360784Sdim llvm::unique_function<void()> Func, 84360784Sdim llvm::Optional<unsigned> StackSizeInBytes = llvm::None); 85360784Sdim 86309124Sdim#if LLVM_THREADING_USE_STD_CALL_ONCE 87309124Sdim 88309124Sdim typedef std::once_flag once_flag; 89309124Sdim 90309124Sdim#else 91309124Sdim 92309124Sdim enum InitStatus { Uninitialized = 0, Wait = 1, Done = 2 }; 93309124Sdim 94341825Sdim /// The llvm::once_flag structure 95321369Sdim /// 96321369Sdim /// This type is modeled after std::once_flag to use with llvm::call_once. 97321369Sdim /// This structure must be used as an opaque object. It is a struct to force 98321369Sdim /// autoinitialization and behave like std::once_flag. 99321369Sdim struct once_flag { 100321369Sdim volatile sys::cas_flag status = Uninitialized; 101321369Sdim }; 102309124Sdim 103309124Sdim#endif 104309124Sdim 105341825Sdim /// Execute the function specified as a parameter once. 106309124Sdim /// 107309124Sdim /// Typical usage: 108309124Sdim /// \code 109309124Sdim /// void foo() {...}; 110309124Sdim /// ... 111321369Sdim /// static once_flag flag; 112309124Sdim /// call_once(flag, foo); 113309124Sdim /// \endcode 114309124Sdim /// 115309124Sdim /// \param flag Flag used for tracking whether or not this has run. 116309124Sdim /// \param F Function to call once. 117309124Sdim template <typename Function, typename... Args> 118309124Sdim void call_once(once_flag &flag, Function &&F, Args &&... ArgList) { 119309124Sdim#if LLVM_THREADING_USE_STD_CALL_ONCE 120309124Sdim std::call_once(flag, std::forward<Function>(F), 121309124Sdim std::forward<Args>(ArgList)...); 122309124Sdim#else 123309124Sdim // For other platforms we use a generic (if brittle) version based on our 124309124Sdim // atomics. 125321369Sdim sys::cas_flag old_val = sys::CompareAndSwap(&flag.status, Wait, Uninitialized); 126309124Sdim if (old_val == Uninitialized) { 127309124Sdim std::forward<Function>(F)(std::forward<Args>(ArgList)...); 128309124Sdim sys::MemoryFence(); 129309124Sdim TsanIgnoreWritesBegin(); 130321369Sdim TsanHappensBefore(&flag.status); 131321369Sdim flag.status = Done; 132309124Sdim TsanIgnoreWritesEnd(); 133309124Sdim } else { 134309124Sdim // Wait until any thread doing the call has finished. 135321369Sdim sys::cas_flag tmp = flag.status; 136309124Sdim sys::MemoryFence(); 137309124Sdim while (tmp != Done) { 138321369Sdim tmp = flag.status; 139309124Sdim sys::MemoryFence(); 140309124Sdim } 141309124Sdim } 142321369Sdim TsanHappensAfter(&flag.status); 143309124Sdim#endif 144309124Sdim } 145314564Sdim 146314564Sdim /// Get the amount of currency to use for tasks requiring significant 147314564Sdim /// memory or other resources. Currently based on physical cores, if 148314564Sdim /// available for the host system, otherwise falls back to 149314564Sdim /// thread::hardware_concurrency(). 150314564Sdim /// Returns 1 when LLVM is configured with LLVM_ENABLE_THREADS=OFF 151314564Sdim unsigned heavyweight_hardware_concurrency(); 152321369Sdim 153327952Sdim /// Get the number of threads that the current program can execute 154327952Sdim /// concurrently. On some systems std::thread::hardware_concurrency() returns 155327952Sdim /// the total number of cores, without taking affinity into consideration. 156327952Sdim /// Returns 1 when LLVM is configured with LLVM_ENABLE_THREADS=OFF. 157327952Sdim /// Fallback to std::thread::hardware_concurrency() if sched_getaffinity is 158327952Sdim /// not available. 159327952Sdim unsigned hardware_concurrency(); 160327952Sdim 161341825Sdim /// Return the current thread id, as used in various OS system calls. 162321369Sdim /// Note that not all platforms guarantee that the value returned will be 163321369Sdim /// unique across the entire system, so portable code should not assume 164321369Sdim /// this. 165321369Sdim uint64_t get_threadid(); 166321369Sdim 167341825Sdim /// Get the maximum length of a thread name on this platform. 168321369Sdim /// A value of 0 means there is no limit. 169321369Sdim uint32_t get_max_thread_name_length(); 170321369Sdim 171341825Sdim /// Set the name of the current thread. Setting a thread's name can 172321369Sdim /// be helpful for enabling useful diagnostics under a debugger or when 173321369Sdim /// logging. The level of support for setting a thread's name varies 174321369Sdim /// wildly across operating systems, and we only make a best effort to 175321369Sdim /// perform the operation on supported platforms. No indication of success 176321369Sdim /// or failure is returned. 177321369Sdim void set_thread_name(const Twine &Name); 178321369Sdim 179341825Sdim /// Get the name of the current thread. The level of support for 180321369Sdim /// getting a thread's name varies wildly across operating systems, and it 181321369Sdim /// is not even guaranteed that if you can successfully set a thread's name 182321369Sdim /// that you can later get it back. This function is intended for diagnostic 183321369Sdim /// purposes, and as with setting a thread's name no indication of whether 184321369Sdim /// the operation succeeded or failed is returned. 185321369Sdim void get_thread_name(SmallVectorImpl<char> &Name); 186353358Sdim 187353358Sdim enum class ThreadPriority { 188353358Sdim Background = 0, 189353358Sdim Default = 1, 190353358Sdim }; 191353358Sdim /// If priority is Background tries to lower current threads priority such 192353358Sdim /// that it does not affect foreground tasks significantly. Can be used for 193353358Sdim /// long-running, latency-insensitive tasks to make sure cpu is not hogged by 194353358Sdim /// this task. 195353358Sdim /// If the priority is default tries to restore current threads priority to 196353358Sdim /// default scheduling priority. 197353358Sdim enum class SetThreadPriorityResult { FAILURE, SUCCESS }; 198353358Sdim SetThreadPriorityResult set_thread_priority(ThreadPriority Priority); 199218885Sdim} 200218885Sdim 201218885Sdim#endif 202