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/ADT/SmallVector.h" 17 #include "llvm/ADT/StringRef.h" 18 #include "llvm/Config/config.h" 19 #include "llvm/Config/llvm-config.h" 20 #include "llvm/Support/MemoryBuffer.h" 21 #include "llvm/Support/raw_ostream.h" 22 23 #include <cassert> 24 #include <errno.h> 25 #include <stdlib.h> 26 #include <string.h> 27 28 using namespace llvm; 29 30 //===----------------------------------------------------------------------===// 31 //=== WARNING: Implementation here must contain only TRULY operating system 32 //=== independent code. 33 //===----------------------------------------------------------------------===// 34 35 #if LLVM_ENABLE_THREADS == 0 || \ 36 (!defined(_WIN32) && !defined(HAVE_PTHREAD_H)) 37 uint64_t llvm::get_threadid() { return 0; } 38 39 uint32_t llvm::get_max_thread_name_length() { return 0; } 40 41 void llvm::set_thread_name(const Twine &Name) {} 42 43 void llvm::get_thread_name(SmallVectorImpl<char> &Name) { Name.clear(); } 44 45 llvm::BitVector llvm::get_thread_affinity_mask() { return {}; } 46 47 unsigned llvm::ThreadPoolStrategy::compute_thread_count() const { 48 // When threads are disabled, ensure clients will loop at least once. 49 return 1; 50 } 51 52 #else 53 54 static int computeHostNumHardwareThreads(); 55 56 unsigned llvm::ThreadPoolStrategy::compute_thread_count() const { 57 int MaxThreadCount = 58 UseHyperThreads ? computeHostNumHardwareThreads() : get_physical_cores(); 59 if (MaxThreadCount <= 0) 60 MaxThreadCount = 1; 61 if (ThreadsRequested == 0) 62 return MaxThreadCount; 63 if (!Limit) 64 return ThreadsRequested; 65 return std::min((unsigned)MaxThreadCount, ThreadsRequested); 66 } 67 68 // Include the platform-specific parts of this class. 69 #ifdef LLVM_ON_UNIX 70 #include "Unix/Threading.inc" 71 #endif 72 #ifdef _WIN32 73 #include "Windows/Threading.inc" 74 #endif 75 76 // Must be included after Threading.inc to provide definition for llvm::thread 77 // because FreeBSD's condvar.h (included by user.h) misuses the "thread" 78 // keyword. 79 #include "llvm/Support/thread.h" 80 81 #if defined(__APPLE__) 82 // Darwin's default stack size for threads except the main one is only 512KB, 83 // which is not enough for some/many normal LLVM compilations. This implements 84 // the same interface as std::thread but requests the same stack size as the 85 // main thread (8MB) before creation. 86 const llvm::Optional<unsigned> llvm::thread::DefaultStackSize = 8 * 1024 * 1024; 87 #else 88 const llvm::Optional<unsigned> llvm::thread::DefaultStackSize; 89 #endif 90 91 92 #endif 93 94 Optional<ThreadPoolStrategy> 95 llvm::get_threadpool_strategy(StringRef Num, ThreadPoolStrategy Default) { 96 if (Num == "all") 97 return llvm::hardware_concurrency(); 98 if (Num.empty()) 99 return Default; 100 unsigned V; 101 if (Num.getAsInteger(10, V)) 102 return None; // malformed 'Num' value 103 if (V == 0) 104 return Default; 105 106 // Do not take the Default into account. This effectively disables 107 // heavyweight_hardware_concurrency() if the user asks for any number of 108 // threads on the cmd-line. 109 ThreadPoolStrategy S = llvm::hardware_concurrency(); 110 S.ThreadsRequested = V; 111 return S; 112 } 113 114 #if defined(__linux__) && (defined(__i386__) || defined(__x86_64__)) 115 // On Linux, the number of physical cores can be computed from /proc/cpuinfo, 116 // using the number of unique physical/core id pairs. The following 117 // implementation reads the /proc/cpuinfo format on an x86_64 system. 118 static int computeHostNumPhysicalCores() { 119 // Enabled represents the number of physical id/core id pairs with at least 120 // one processor id enabled by the CPU affinity mask. 121 cpu_set_t Affinity, Enabled; 122 if (sched_getaffinity(0, sizeof(Affinity), &Affinity) != 0) 123 return -1; 124 CPU_ZERO(&Enabled); 125 126 // Read /proc/cpuinfo as a stream (until EOF reached). It cannot be 127 // mmapped because it appears to have 0 size. 128 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 129 llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo"); 130 if (std::error_code EC = Text.getError()) { 131 llvm::errs() << "Can't read " 132 << "/proc/cpuinfo: " << EC.message() << "\n"; 133 return -1; 134 } 135 SmallVector<StringRef, 8> strs; 136 (*Text)->getBuffer().split(strs, "\n", /*MaxSplit=*/-1, 137 /*KeepEmpty=*/false); 138 int CurProcessor = -1; 139 int CurPhysicalId = -1; 140 int CurSiblings = -1; 141 int CurCoreId = -1; 142 for (StringRef Line : strs) { 143 std::pair<StringRef, StringRef> Data = Line.split(':'); 144 auto Name = Data.first.trim(); 145 auto Val = Data.second.trim(); 146 // These fields are available if the kernel is configured with CONFIG_SMP. 147 if (Name == "processor") 148 Val.getAsInteger(10, CurProcessor); 149 else if (Name == "physical id") 150 Val.getAsInteger(10, CurPhysicalId); 151 else if (Name == "siblings") 152 Val.getAsInteger(10, CurSiblings); 153 else if (Name == "core id") { 154 Val.getAsInteger(10, CurCoreId); 155 // The processor id corresponds to an index into cpu_set_t. 156 if (CPU_ISSET(CurProcessor, &Affinity)) 157 CPU_SET(CurPhysicalId * CurSiblings + CurCoreId, &Enabled); 158 } 159 } 160 return CPU_COUNT(&Enabled); 161 } 162 #elif defined(__linux__) && defined(__s390x__) 163 static int computeHostNumPhysicalCores() { 164 return sysconf(_SC_NPROCESSORS_ONLN); 165 } 166 #elif defined(__linux__) && !defined(__ANDROID__) 167 static int computeHostNumPhysicalCores() { 168 cpu_set_t Affinity; 169 if (sched_getaffinity(0, sizeof(Affinity), &Affinity) == 0) 170 return CPU_COUNT(&Affinity); 171 172 // The call to sched_getaffinity() may have failed because the Affinity 173 // mask is too small for the number of CPU's on the system (i.e. the 174 // system has more than 1024 CPUs). Allocate a mask large enough for 175 // twice as many CPUs. 176 cpu_set_t *DynAffinity; 177 DynAffinity = CPU_ALLOC(2048); 178 if (sched_getaffinity(0, CPU_ALLOC_SIZE(2048), DynAffinity) == 0) { 179 int NumCPUs = CPU_COUNT(DynAffinity); 180 CPU_FREE(DynAffinity); 181 return NumCPUs; 182 } 183 return -1; 184 } 185 #elif defined(__APPLE__) 186 // Gets the number of *physical cores* on the machine. 187 static int computeHostNumPhysicalCores() { 188 uint32_t count; 189 size_t len = sizeof(count); 190 sysctlbyname("hw.physicalcpu", &count, &len, NULL, 0); 191 if (count < 1) { 192 int nm[2]; 193 nm[0] = CTL_HW; 194 nm[1] = HW_AVAILCPU; 195 sysctl(nm, 2, &count, &len, NULL, 0); 196 if (count < 1) 197 return -1; 198 } 199 return count; 200 } 201 #elif defined(__MVS__) 202 static int computeHostNumPhysicalCores() { 203 enum { 204 // Byte offset of the pointer to the Communications Vector Table (CVT) in 205 // the Prefixed Save Area (PSA). The table entry is a 31-bit pointer and 206 // will be zero-extended to uintptr_t. 207 FLCCVT = 16, 208 // Byte offset of the pointer to the Common System Data Area (CSD) in the 209 // CVT. The table entry is a 31-bit pointer and will be zero-extended to 210 // uintptr_t. 211 CVTCSD = 660, 212 // Byte offset to the number of live CPs in the LPAR, stored as a signed 213 // 32-bit value in the table. 214 CSD_NUMBER_ONLINE_STANDARD_CPS = 264, 215 }; 216 char *PSA = 0; 217 char *CVT = reinterpret_cast<char *>( 218 static_cast<uintptr_t>(reinterpret_cast<unsigned int &>(PSA[FLCCVT]))); 219 char *CSD = reinterpret_cast<char *>( 220 static_cast<uintptr_t>(reinterpret_cast<unsigned int &>(CVT[CVTCSD]))); 221 return reinterpret_cast<int &>(CSD[CSD_NUMBER_ONLINE_STANDARD_CPS]); 222 } 223 #elif defined(_WIN32) && LLVM_ENABLE_THREADS != 0 224 // Defined in llvm/lib/Support/Windows/Threading.inc 225 int computeHostNumPhysicalCores(); 226 #else 227 // On other systems, return -1 to indicate unknown. 228 static int computeHostNumPhysicalCores() { return -1; } 229 #endif 230 231 int llvm::get_physical_cores() { 232 static int NumCores = computeHostNumPhysicalCores(); 233 return NumCores; 234 } 235