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