Threading.cpp revision 360784
1//===-- llvm/Support/Threading.cpp- 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 defines helper functions for running LLVM in a multi-threaded 10// environment. 11// 12//===----------------------------------------------------------------------===// 13 14#include "llvm/Support/Threading.h" 15#include "llvm/ADT/Optional.h" 16#include "llvm/Config/config.h" 17#include "llvm/Support/Host.h" 18 19#include <cassert> 20#include <errno.h> 21#include <stdlib.h> 22#include <string.h> 23 24using namespace llvm; 25 26//===----------------------------------------------------------------------===// 27//=== WARNING: Implementation here must contain only TRULY operating system 28//=== independent code. 29//===----------------------------------------------------------------------===// 30 31bool llvm::llvm_is_multithreaded() { 32#if LLVM_ENABLE_THREADS != 0 33 return true; 34#else 35 return false; 36#endif 37} 38 39#if LLVM_ENABLE_THREADS == 0 || \ 40 (!defined(_WIN32) && !defined(HAVE_PTHREAD_H)) 41// Support for non-Win32, non-pthread implementation. 42void llvm::llvm_execute_on_thread(void (*Fn)(void *), void *UserData, 43 llvm::Optional<unsigned> StackSizeInBytes) { 44 (void)StackSizeInBytes; 45 Fn(UserData); 46} 47 48unsigned llvm::heavyweight_hardware_concurrency() { return 1; } 49 50unsigned llvm::hardware_concurrency() { return 1; } 51 52uint64_t llvm::get_threadid() { return 0; } 53 54uint32_t llvm::get_max_thread_name_length() { return 0; } 55 56void llvm::set_thread_name(const Twine &Name) {} 57 58void llvm::get_thread_name(SmallVectorImpl<char> &Name) { Name.clear(); } 59 60#if LLVM_ENABLE_THREADS == 0 61void llvm::llvm_execute_on_thread_async( 62 llvm::unique_function<void()> Func, 63 llvm::Optional<unsigned> StackSizeInBytes) { 64 (void)Func; 65 (void)StackSizeInBytes; 66 report_fatal_error("Spawning a detached thread doesn't make sense with no " 67 "threading support"); 68} 69#else 70// Support for non-Win32, non-pthread implementation. 71void llvm::llvm_execute_on_thread_async( 72 llvm::unique_function<void()> Func, 73 llvm::Optional<unsigned> StackSizeInBytes) { 74 (void)StackSizeInBytes; 75 std::thread(std::move(Func)).detach(); 76} 77#endif 78 79#else 80 81#include <thread> 82unsigned llvm::heavyweight_hardware_concurrency() { 83 // Since we can't get here unless LLVM_ENABLE_THREADS == 1, it is safe to use 84 // `std::thread` directly instead of `llvm::thread` (and indeed, doing so 85 // allows us to not define `thread` in the llvm namespace, which conflicts 86 // with some platforms such as FreeBSD whose headers also define a struct 87 // called `thread` in the global namespace which can cause ambiguity due to 88 // ADL. 89 int NumPhysical = sys::getHostNumPhysicalCores(); 90 if (NumPhysical == -1) 91 return std::thread::hardware_concurrency(); 92 return NumPhysical; 93} 94 95unsigned llvm::hardware_concurrency() { 96#if defined(HAVE_SCHED_GETAFFINITY) && defined(HAVE_CPU_COUNT) 97 cpu_set_t Set; 98 if (sched_getaffinity(0, sizeof(Set), &Set)) 99 return CPU_COUNT(&Set); 100#endif 101 // Guard against std::thread::hardware_concurrency() returning 0. 102 if (unsigned Val = std::thread::hardware_concurrency()) 103 return Val; 104 return 1; 105} 106 107namespace { 108struct SyncThreadInfo { 109 void (*UserFn)(void *); 110 void *UserData; 111}; 112 113using AsyncThreadInfo = llvm::unique_function<void()>; 114 115enum class JoiningPolicy { Join, Detach }; 116} // namespace 117 118// Include the platform-specific parts of this class. 119#ifdef LLVM_ON_UNIX 120#include "Unix/Threading.inc" 121#endif 122#ifdef _WIN32 123#include "Windows/Threading.inc" 124#endif 125 126void llvm::llvm_execute_on_thread(void (*Fn)(void *), void *UserData, 127 llvm::Optional<unsigned> StackSizeInBytes) { 128 129 SyncThreadInfo Info = {Fn, UserData}; 130 llvm_execute_on_thread_impl(threadFuncSync, &Info, StackSizeInBytes, 131 JoiningPolicy::Join); 132} 133 134void llvm::llvm_execute_on_thread_async( 135 llvm::unique_function<void()> Func, 136 llvm::Optional<unsigned> StackSizeInBytes) { 137 llvm_execute_on_thread_impl(&threadFuncAsync, 138 new AsyncThreadInfo(std::move(Func)), 139 StackSizeInBytes, JoiningPolicy::Detach); 140} 141 142#endif 143