23#include <mach/mach_init.h>
24#include <mach/mach_port.h>
25#include <pthread/qos.h>
26#include <sys/sysctl.h>
32#if defined(__FreeBSD__) || defined(__OpenBSD__)
33#include <pthread_np.h>
36#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
38#include <sys/cpuset.h>
39#include <sys/sysctl.h>
44#if defined(__NetBSD__)
48#if defined(__OpenBSD__)
54#include <sys/syscall.h>
60llvm_execute_on_thread_impl(
void *(*ThreadFunc)(
void *),
void *Arg,
61 std::optional<unsigned> StackSizeInBytes) {
66 if ((errnum = ::pthread_attr_init(&Attr)) != 0) {
71 if ((errnum = ::pthread_attr_destroy(&Attr)) != 0) {
77 if (StackSizeInBytes) {
78 if ((errnum = ::pthread_attr_setstacksize(&Attr, *StackSizeInBytes)) != 0) {
85 if ((errnum = ::pthread_create(&
Thread, &Attr, ThreadFunc, Arg)) != 0)
91void llvm_thread_detach_impl(pthread_t
Thread) {
94 if ((errnum = ::pthread_detach(
Thread)) != 0) {
99void llvm_thread_join_impl(pthread_t
Thread) {
102 if ((errnum = ::pthread_join(
Thread,
nullptr)) != 0) {
107pthread_t llvm_thread_get_id_impl(pthread_t
Thread) {
return Thread; }
109pthread_t llvm_thread_get_current_id_impl() { return ::pthread_self(); }
114#if defined(__APPLE__)
118 thread_port_t Self = mach_thread_self();
119 mach_port_deallocate(mach_task_self(), Self);
121#elif defined(__FreeBSD__)
122 return uint64_t(pthread_getthreadid_np());
123#elif defined(__NetBSD__)
125#elif defined(__OpenBSD__)
127#elif defined(__ANDROID__)
129#elif defined(__linux__)
130 return uint64_t(syscall(SYS_gettid));
136static constexpr uint32_t get_max_thread_name_length_impl() {
137#if defined(__NetBSD__)
138 return PTHREAD_MAX_NAMELEN_NP;
139#elif defined(__APPLE__)
141#elif defined(__linux__)
142#if HAVE_PTHREAD_SETNAME_NP
147#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
149#elif defined(__OpenBSD__)
157 return get_max_thread_name_length_impl();
162 SmallString<64> Storage;
163 StringRef NameStr =
Name.toNullTerminatedStringRef(Storage);
174#if defined(__linux__)
175#if (defined(__GLIBC__) && defined(_GNU_SOURCE)) || defined(__ANDROID__)
176#if HAVE_PTHREAD_SETNAME_NP
177 ::pthread_setname_np(::pthread_self(), NameStr.data());
180#elif defined(__FreeBSD__) || defined(__OpenBSD__)
181 ::pthread_set_name_np(::pthread_self(), NameStr.data());
182#elif defined(__NetBSD__)
183 ::pthread_setname_np(::pthread_self(),
"%s",
184 const_cast<char *
>(NameStr.data()));
185#elif defined(__APPLE__)
186 ::pthread_setname_np(NameStr.data());
193#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
194 int pid = ::getpid();
197 struct kinfo_proc *kp =
nullptr, *nkp;
200 int ctl[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD,
204 error = sysctl(ctl, 4, kp, &len,
nullptr, 0);
205 if (kp ==
nullptr || (
error != 0 && errno == ENOMEM)) {
207 len +=
sizeof(*kp) + len / 10;
208 nkp = (
struct kinfo_proc *)::realloc(kp, len);
209 if (nkp ==
nullptr) {
221 for (
size_t i = 0; i < len /
sizeof(*kp); i++) {
222 if (kp[i].ki_tid == (lwpid_t)tid) {
223 Name.append(kp[i].ki_tdname, kp[i].ki_tdname + strlen(kp[i].ki_tdname));
229#elif defined(__NetBSD__)
230 constexpr uint32_t len = get_max_thread_name_length_impl();
232 ::pthread_getname_np(::pthread_self(), buf, len);
234 Name.append(buf, buf + strlen(buf));
235#elif defined(__OpenBSD__)
236 constexpr uint32_t len = get_max_thread_name_length_impl();
238 ::pthread_get_name_np(::pthread_self(), buf, len);
240 Name.append(buf, buf + strlen(buf));
241#elif defined(__linux__)
242#if HAVE_PTHREAD_GETNAME_NP
243 constexpr uint32_t len = get_max_thread_name_length_impl();
244 char Buffer[len] = {
'\0'};
245 if (0 == ::pthread_getname_np(::pthread_self(), Buffer, len))
246 Name.append(Buffer, Buffer + strlen(Buffer));
252#if defined(__linux__) && defined(SCHED_IDLE)
256 sched_param priority;
258 priority.sched_priority = 0;
261 return !pthread_setschedparam(
264 Priority == ThreadPriority::Default ? SCHED_OTHER : SCHED_IDLE,
266 ? SetThreadPriorityResult::SUCCESS
267 : SetThreadPriorityResult::FAILURE;
268#elif defined(__APPLE__)
279 const auto qosClass = [&]() {
281 case ThreadPriority::Background:
282 return QOS_CLASS_BACKGROUND;
283 case ThreadPriority::Low:
284 return QOS_CLASS_UTILITY;
285 case ThreadPriority::Default:
286 return QOS_CLASS_DEFAULT;
289 return !pthread_set_qos_class_self_np(qosClass, 0)
290 ? SetThreadPriorityResult::SUCCESS
291 : SetThreadPriorityResult::FAILURE;
293 return SetThreadPriorityResult::FAILURE;
298static int computeHostNumHardwareThreads() {
299#if defined(__FreeBSD__)
302 if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1,
sizeof(mask),
304 return CPU_COUNT(&mask);
305#elif defined(__linux__)
307 if (sched_getaffinity(0,
sizeof(Set), &Set) == 0)
308 return CPU_COUNT(&Set);
311 if (
unsigned Val = std::thread::hardware_concurrency())
317 unsigned ThreadPoolNum)
const {}
326#if defined(__linux__) && (defined(__i386__) || defined(__x86_64__))
330static int computeHostNumPhysicalCores() {
334 if (sched_getaffinity(0,
sizeof(Affinity), &Affinity) != 0)
342 if (std::error_code EC =
Text.getError()) {
344 <<
"/proc/cpuinfo: " <<
EC.message() <<
"\n";
347 SmallVector<StringRef, 8> strs;
348 (*Text)->getBuffer().split(strs,
"\n", -1,
350 int CurProcessor = -1;
351 int CurPhysicalId = -1;
352 int CurSiblings = -1;
354 for (StringRef Line : strs) {
355 std::pair<StringRef, StringRef>
Data =
Line.split(
':');
357 auto Val =
Data.second.trim();
359 if (
Name ==
"processor")
360 Val.getAsInteger(10, CurProcessor);
361 else if (
Name ==
"physical id")
362 Val.getAsInteger(10, CurPhysicalId);
363 else if (
Name ==
"siblings")
364 Val.getAsInteger(10, CurSiblings);
365 else if (
Name ==
"core id") {
366 Val.getAsInteger(10, CurCoreId);
368 if (CPU_ISSET(CurProcessor, &Affinity))
369 CPU_SET(CurPhysicalId * CurSiblings + CurCoreId, &
Enabled);
374#elif (defined(__linux__) && defined(__s390x__)) || defined(_AIX)
375static int computeHostNumPhysicalCores() {
376 return sysconf(_SC_NPROCESSORS_ONLN);
378#elif defined(__linux__) && !defined(__ANDROID__)
379static int computeHostNumPhysicalCores() {
381 if (sched_getaffinity(0,
sizeof(Affinity), &Affinity) == 0)
382 return CPU_COUNT(&Affinity);
388 cpu_set_t *DynAffinity;
389 DynAffinity = CPU_ALLOC(2048);
390 if (sched_getaffinity(0, CPU_ALLOC_SIZE(2048), DynAffinity) == 0) {
391 int NumCPUs = CPU_COUNT(DynAffinity);
392 CPU_FREE(DynAffinity);
397#elif defined(__APPLE__)
399static int computeHostNumPhysicalCores() {
401 size_t len =
sizeof(
count);
402 sysctlbyname(
"hw.physicalcpu", &
count, &len, NULL, 0);
407 sysctl(nm, 2, &
count, &len, NULL, 0);
413#elif defined(__MVS__)
414static int computeHostNumPhysicalCores() {
426 CSD_NUMBER_ONLINE_STANDARD_CPS = 264,
429 char *CVT =
reinterpret_cast<char *
>(
430 static_cast<uintptr_t
>(
reinterpret_cast<unsigned int &
>(PSA[FLCCVT])));
431 char *CSD =
reinterpret_cast<char *
>(
432 static_cast<uintptr_t
>(
reinterpret_cast<unsigned int &
>(CVT[CVTCSD])));
433 return reinterpret_cast<int &
>(CSD[CSD_NUMBER_ONLINE_STANDARD_CPS]);
437static int computeHostNumPhysicalCores() {
return -1; }
441 static int NumCores = computeHostNumPhysicalCores();
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
This file defines the SmallString class.
This file defines the SmallVector class.
static void ReportErrnumFatal(const char *Msg, int errnum)
Represents either an error or a value T.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileAsStream(const Twine &Filename)
Read all of the specified file into a MemoryBuffer as a stream (i.e.
void apply_thread_strategy(unsigned ThreadPoolNum) const
Assign the current thread to an ideal hardware CPU or NUMA node.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
SetThreadPriorityResult set_thread_priority(ThreadPriority Priority)
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
llvm::BitVector get_thread_affinity_mask()
Returns a mask that represents on which hardware thread, core, CPU, NUMA group, the calling thread ca...
uint32_t get_max_thread_name_length()
Get the maximum length of a thread name on this platform.
unsigned get_cpus()
Returns how many physical CPUs or NUMA groups the system has.
void set_thread_name(const Twine &Name)
Set the name of the current thread.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void get_thread_name(SmallVectorImpl< char > &Name)
Get the name of the current thread.
int get_physical_cores()
Returns how many physical cores (as opposed to logical cores returned from thread::hardware_concurren...
uint64_t get_threadid()
Return the current thread id, as used in various OS system calls.
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
auto mask(ShuffFunc S, unsigned Length, OptArgs... args) -> MaskT