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