10b57cec5SDimitry Andric //===-- llvm/Support/Threading.cpp- Control multithreading mode --*- C++ -*-==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines helper functions for running LLVM in a multi-threaded
100b57cec5SDimitry Andric // environment.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/Support/Threading.h"
15480093f4SDimitry Andric #include "llvm/ADT/Optional.h"
160b57cec5SDimitry Andric #include "llvm/Config/config.h"
170b57cec5SDimitry Andric #include "llvm/Support/Host.h"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #include <cassert>
200b57cec5SDimitry Andric #include <errno.h>
210b57cec5SDimitry Andric #include <stdlib.h>
220b57cec5SDimitry Andric #include <string.h>
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
270b57cec5SDimitry Andric //=== WARNING: Implementation here must contain only TRULY operating system
280b57cec5SDimitry Andric //===          independent code.
290b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
300b57cec5SDimitry Andric 
llvm_is_multithreaded()310b57cec5SDimitry Andric bool llvm::llvm_is_multithreaded() {
320b57cec5SDimitry Andric #if LLVM_ENABLE_THREADS != 0
330b57cec5SDimitry Andric   return true;
340b57cec5SDimitry Andric #else
350b57cec5SDimitry Andric   return false;
360b57cec5SDimitry Andric #endif
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric #if LLVM_ENABLE_THREADS == 0 ||                                                \
400b57cec5SDimitry Andric     (!defined(_WIN32) && !defined(HAVE_PTHREAD_H))
get_threadid()410b57cec5SDimitry Andric uint64_t llvm::get_threadid() { return 0; }
420b57cec5SDimitry Andric 
get_max_thread_name_length()430b57cec5SDimitry Andric uint32_t llvm::get_max_thread_name_length() { return 0; }
440b57cec5SDimitry Andric 
set_thread_name(const Twine & Name)450b57cec5SDimitry Andric void llvm::set_thread_name(const Twine &Name) {}
460b57cec5SDimitry Andric 
get_thread_name(SmallVectorImpl<char> & Name)470b57cec5SDimitry Andric void llvm::get_thread_name(SmallVectorImpl<char> &Name) { Name.clear(); }
480b57cec5SDimitry Andric 
get_thread_affinity_mask()495ffd83dbSDimitry Andric llvm::BitVector llvm::get_thread_affinity_mask() { return {}; }
505ffd83dbSDimitry Andric 
compute_thread_count() const515ffd83dbSDimitry Andric unsigned llvm::ThreadPoolStrategy::compute_thread_count() const {
525ffd83dbSDimitry Andric   // When threads are disabled, ensure clients will loop at least once.
535ffd83dbSDimitry Andric   return 1;
545ffd83dbSDimitry Andric }
555ffd83dbSDimitry Andric 
560b57cec5SDimitry Andric #else
570b57cec5SDimitry Andric 
585ffd83dbSDimitry Andric int computeHostNumHardwareThreads();
590b57cec5SDimitry Andric 
compute_thread_count() const605ffd83dbSDimitry Andric unsigned llvm::ThreadPoolStrategy::compute_thread_count() const {
615ffd83dbSDimitry Andric   int MaxThreadCount = UseHyperThreads ? computeHostNumHardwareThreads()
625ffd83dbSDimitry Andric                                        : sys::getHostNumPhysicalCores();
635ffd83dbSDimitry Andric   if (MaxThreadCount <= 0)
645ffd83dbSDimitry Andric     MaxThreadCount = 1;
655ffd83dbSDimitry Andric   if (ThreadsRequested == 0)
665ffd83dbSDimitry Andric     return MaxThreadCount;
675ffd83dbSDimitry Andric   if (!Limit)
685ffd83dbSDimitry Andric     return ThreadsRequested;
695ffd83dbSDimitry Andric   return std::min((unsigned)MaxThreadCount, ThreadsRequested);
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric // Include the platform-specific parts of this class.
730b57cec5SDimitry Andric #ifdef LLVM_ON_UNIX
740b57cec5SDimitry Andric #include "Unix/Threading.inc"
750b57cec5SDimitry Andric #endif
760b57cec5SDimitry Andric #ifdef _WIN32
770b57cec5SDimitry Andric #include "Windows/Threading.inc"
780b57cec5SDimitry Andric #endif
790b57cec5SDimitry Andric 
80*5f7ddb14SDimitry Andric // Must be included after Threading.inc to provide definition for llvm::thread
81*5f7ddb14SDimitry Andric // because FreeBSD's condvar.h (included by user.h) misuses the "thread"
82*5f7ddb14SDimitry Andric // keyword.
83*5f7ddb14SDimitry Andric #include "llvm/Support/thread.h"
84480093f4SDimitry Andric 
85*5f7ddb14SDimitry Andric #if defined(__APPLE__)
86*5f7ddb14SDimitry Andric   // Darwin's default stack size for threads except the main one is only 512KB,
87*5f7ddb14SDimitry Andric   // which is not enough for some/many normal LLVM compilations. This implements
88*5f7ddb14SDimitry Andric   // the same interface as std::thread but requests the same stack size as the
89*5f7ddb14SDimitry Andric   // main thread (8MB) before creation.
90*5f7ddb14SDimitry Andric const llvm::Optional<unsigned> llvm::thread::DefaultStackSize = 8 * 1024 * 1024;
91*5f7ddb14SDimitry Andric #else
92*5f7ddb14SDimitry Andric const llvm::Optional<unsigned> llvm::thread::DefaultStackSize = None;
93*5f7ddb14SDimitry Andric #endif
94480093f4SDimitry Andric 
95480093f4SDimitry Andric 
960b57cec5SDimitry Andric #endif
975ffd83dbSDimitry Andric 
985ffd83dbSDimitry Andric Optional<ThreadPoolStrategy>
get_threadpool_strategy(StringRef Num,ThreadPoolStrategy Default)995ffd83dbSDimitry Andric llvm::get_threadpool_strategy(StringRef Num, ThreadPoolStrategy Default) {
1005ffd83dbSDimitry Andric   if (Num == "all")
1015ffd83dbSDimitry Andric     return llvm::hardware_concurrency();
1025ffd83dbSDimitry Andric   if (Num.empty())
1035ffd83dbSDimitry Andric     return Default;
1045ffd83dbSDimitry Andric   unsigned V;
1055ffd83dbSDimitry Andric   if (Num.getAsInteger(10, V))
1065ffd83dbSDimitry Andric     return None; // malformed 'Num' value
1075ffd83dbSDimitry Andric   if (V == 0)
1085ffd83dbSDimitry Andric     return Default;
1095ffd83dbSDimitry Andric 
1105ffd83dbSDimitry Andric   // Do not take the Default into account. This effectively disables
1115ffd83dbSDimitry Andric   // heavyweight_hardware_concurrency() if the user asks for any number of
1125ffd83dbSDimitry Andric   // threads on the cmd-line.
1135ffd83dbSDimitry Andric   ThreadPoolStrategy S = llvm::hardware_concurrency();
1145ffd83dbSDimitry Andric   S.ThreadsRequested = V;
1155ffd83dbSDimitry Andric   return S;
1165ffd83dbSDimitry Andric }
117