Home | History | Annotate | Line # | Download | only in Support
      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 
     24 using namespace llvm;
     25 
     26 //===----------------------------------------------------------------------===//
     27 //=== WARNING: Implementation here must contain only TRULY operating system
     28 //===          independent code.
     29 //===----------------------------------------------------------------------===//
     30 
     31 bool 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.
     42 void llvm::llvm_execute_on_thread(void (*Fn)(void *), void *UserData,
     43                                   llvm::Optional<unsigned> StackSizeInBytes) {
     44   (void)StackSizeInBytes;
     45   Fn(UserData);
     46 }
     47 
     48 uint64_t llvm::get_threadid() { return 0; }
     49 
     50 uint32_t llvm::get_max_thread_name_length() { return 0; }
     51 
     52 void llvm::set_thread_name(const Twine &Name) {}
     53 
     54 void llvm::get_thread_name(SmallVectorImpl<char> &Name) { Name.clear(); }
     55 
     56 llvm::BitVector llvm::get_thread_affinity_mask() { return {}; }
     57 
     58 unsigned llvm::ThreadPoolStrategy::compute_thread_count() const {
     59   // When threads are disabled, ensure clients will loop at least once.
     60   return 1;
     61 }
     62 
     63 #if LLVM_ENABLE_THREADS == 0
     64 void llvm::llvm_execute_on_thread_async(
     65     llvm::unique_function<void()> Func,
     66     llvm::Optional<unsigned> StackSizeInBytes) {
     67   (void)Func;
     68   (void)StackSizeInBytes;
     69   report_fatal_error("Spawning a detached thread doesn't make sense with no "
     70                      "threading support");
     71 }
     72 #else
     73 // Support for non-Win32, non-pthread implementation.
     74 void llvm::llvm_execute_on_thread_async(
     75     llvm::unique_function<void()> Func,
     76     llvm::Optional<unsigned> StackSizeInBytes) {
     77   (void)StackSizeInBytes;
     78   std::thread(std::move(Func)).detach();
     79 }
     80 #endif
     81 
     82 #else
     83 
     84 int computeHostNumHardwareThreads();
     85 
     86 unsigned llvm::ThreadPoolStrategy::compute_thread_count() const {
     87   int MaxThreadCount = UseHyperThreads ? computeHostNumHardwareThreads()
     88                                        : sys::getHostNumPhysicalCores();
     89   if (MaxThreadCount <= 0)
     90     MaxThreadCount = 1;
     91   if (ThreadsRequested == 0)
     92     return MaxThreadCount;
     93   if (!Limit)
     94     return ThreadsRequested;
     95   return std::min((unsigned)MaxThreadCount, ThreadsRequested);
     96 }
     97 
     98 namespace {
     99 struct SyncThreadInfo {
    100   void (*UserFn)(void *);
    101   void *UserData;
    102 };
    103 
    104 using AsyncThreadInfo = llvm::unique_function<void()>;
    105 
    106 enum class JoiningPolicy { Join, Detach };
    107 } // namespace
    108 
    109 // Include the platform-specific parts of this class.
    110 #ifdef LLVM_ON_UNIX
    111 #include "Unix/Threading.inc"
    112 #endif
    113 #ifdef _WIN32
    114 #include "Windows/Threading.inc"
    115 #endif
    116 
    117 void llvm::llvm_execute_on_thread(void (*Fn)(void *), void *UserData,
    118                                   llvm::Optional<unsigned> StackSizeInBytes) {
    119 
    120   SyncThreadInfo Info = {Fn, UserData};
    121   llvm_execute_on_thread_impl(threadFuncSync, &Info, StackSizeInBytes,
    122                               JoiningPolicy::Join);
    123 }
    124 
    125 void llvm::llvm_execute_on_thread_async(
    126     llvm::unique_function<void()> Func,
    127     llvm::Optional<unsigned> StackSizeInBytes) {
    128   llvm_execute_on_thread_impl(&threadFuncAsync,
    129                               new AsyncThreadInfo(std::move(Func)),
    130                               StackSizeInBytes, JoiningPolicy::Detach);
    131 }
    132 
    133 #endif
    134 
    135 Optional<ThreadPoolStrategy>
    136 llvm::get_threadpool_strategy(StringRef Num, ThreadPoolStrategy Default) {
    137   if (Num == "all")
    138     return llvm::hardware_concurrency();
    139   if (Num.empty())
    140     return Default;
    141   unsigned V;
    142   if (Num.getAsInteger(10, V))
    143     return None; // malformed 'Num' value
    144   if (V == 0)
    145     return Default;
    146 
    147   // Do not take the Default into account. This effectively disables
    148   // heavyweight_hardware_concurrency() if the user asks for any number of
    149   // threads on the cmd-line.
    150   ThreadPoolStrategy S = llvm::hardware_concurrency();
    151   S.ThreadsRequested = V;
    152   return S;
    153 }
    154