1//===- Unix/Threading.inc - Unix Threading Implementation ----- -*- 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 provides the Unix specific implementation of Threading functions.
10//
11//===----------------------------------------------------------------------===//
12
13#include "Unix.h"
14#include "llvm/ADT/ScopeExit.h"
15#include "llvm/ADT/SmallString.h"
16#include "llvm/ADT/Twine.h"
17
18#if defined(__APPLE__)
19#include <mach/mach_init.h>
20#include <mach/mach_port.h>
21#endif
22
23#include <pthread.h>
24
25#if defined(__FreeBSD__) || defined(__OpenBSD__)
26#include <pthread_np.h> // For pthread_getthreadid_np() / pthread_set_name_np()
27#endif
28
29#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
30#include <errno.h>
31#include <sys/sysctl.h>
32#include <sys/user.h>
33#include <unistd.h>
34#endif
35
36#if defined(__NetBSD__)
37#include <lwp.h> // For _lwp_self()
38#endif
39
40#if defined(__OpenBSD__)
41#include <unistd.h> // For getthrid()
42#endif
43
44#if defined(__linux__)
45#include <sched.h>       // For sched_getaffinity
46#include <sys/syscall.h> // For syscall codes
47#include <unistd.h>      // For syscall()
48#endif
49
50static void *threadFuncSync(void *Arg) {
51  SyncThreadInfo *TI = static_cast<SyncThreadInfo *>(Arg);
52  TI->UserFn(TI->UserData);
53  return nullptr;
54}
55
56static void *threadFuncAsync(void *Arg) {
57  std::unique_ptr<AsyncThreadInfo> Info(static_cast<AsyncThreadInfo *>(Arg));
58  (*Info)();
59  return nullptr;
60}
61
62static void
63llvm_execute_on_thread_impl(void *(*ThreadFunc)(void *), void *Arg,
64                            llvm::Optional<unsigned> StackSizeInBytes,
65                            JoiningPolicy JP) {
66  int errnum;
67
68  // Construct the attributes object.
69  pthread_attr_t Attr;
70  if ((errnum = ::pthread_attr_init(&Attr)) != 0) {
71    ReportErrnumFatal("pthread_attr_init failed", errnum);
72  }
73
74  auto AttrGuard = llvm::make_scope_exit([&] {
75    if ((errnum = ::pthread_attr_destroy(&Attr)) != 0) {
76      ReportErrnumFatal("pthread_attr_destroy failed", errnum);
77    }
78  });
79
80  // Set the requested stack size, if given.
81  if (StackSizeInBytes) {
82    if ((errnum = ::pthread_attr_setstacksize(&Attr, *StackSizeInBytes)) != 0) {
83      ReportErrnumFatal("pthread_attr_setstacksize failed", errnum);
84    }
85  }
86
87  // Construct and execute the thread.
88  pthread_t Thread;
89  if ((errnum = ::pthread_create(&Thread, &Attr, ThreadFunc, Arg)) != 0)
90    ReportErrnumFatal("pthread_create failed", errnum);
91
92  if (JP == JoiningPolicy::Join) {
93    // Wait for the thread
94    if ((errnum = ::pthread_join(Thread, nullptr)) != 0) {
95      ReportErrnumFatal("pthread_join failed", errnum);
96    }
97  }
98}
99
100uint64_t llvm::get_threadid() {
101#if defined(__APPLE__)
102  // Calling "mach_thread_self()" bumps the reference count on the thread
103  // port, so we need to deallocate it. mach_task_self() doesn't bump the ref
104  // count.
105  thread_port_t Self = mach_thread_self();
106  mach_port_deallocate(mach_task_self(), Self);
107  return Self;
108#elif defined(__FreeBSD__)
109  return uint64_t(pthread_getthreadid_np());
110#elif defined(__NetBSD__)
111  return uint64_t(_lwp_self());
112#elif defined(__OpenBSD__)
113  return uint64_t(getthrid());
114#elif defined(__ANDROID__)
115  return uint64_t(gettid());
116#elif defined(__linux__)
117  return uint64_t(syscall(SYS_gettid));
118#else
119  return uint64_t(pthread_self());
120#endif
121}
122
123
124static constexpr uint32_t get_max_thread_name_length_impl() {
125#if defined(__NetBSD__)
126  return PTHREAD_MAX_NAMELEN_NP;
127#elif defined(__APPLE__)
128  return 64;
129#elif defined(__linux__)
130#if HAVE_PTHREAD_SETNAME_NP
131  return 16;
132#else
133  return 0;
134#endif
135#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
136  return 16;
137#elif defined(__OpenBSD__)
138  return 32;
139#else
140  return 0;
141#endif
142}
143
144uint32_t llvm::get_max_thread_name_length() {
145  return get_max_thread_name_length_impl();
146}
147
148void llvm::set_thread_name(const Twine &Name) {
149  // Make sure the input is null terminated.
150  SmallString<64> Storage;
151  StringRef NameStr = Name.toNullTerminatedStringRef(Storage);
152
153  // Truncate from the beginning, not the end, if the specified name is too
154  // long.  For one, this ensures that the resulting string is still null
155  // terminated, but additionally the end of a long thread name will usually
156  // be more unique than the beginning, since a common pattern is for similar
157  // threads to share a common prefix.
158  // Note that the name length includes the null terminator.
159  if (get_max_thread_name_length() > 0)
160    NameStr = NameStr.take_back(get_max_thread_name_length() - 1);
161  (void)NameStr;
162#if defined(__linux__)
163#if (defined(__GLIBC__) && defined(_GNU_SOURCE)) || defined(__ANDROID__)
164#if HAVE_PTHREAD_SETNAME_NP
165  ::pthread_setname_np(::pthread_self(), NameStr.data());
166#endif
167#endif
168#elif defined(__FreeBSD__) || defined(__OpenBSD__)
169  ::pthread_set_name_np(::pthread_self(), NameStr.data());
170#elif defined(__NetBSD__)
171  ::pthread_setname_np(::pthread_self(), "%s",
172    const_cast<char *>(NameStr.data()));
173#elif defined(__APPLE__)
174  ::pthread_setname_np(NameStr.data());
175#endif
176}
177
178void llvm::get_thread_name(SmallVectorImpl<char> &Name) {
179  Name.clear();
180
181#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
182  int pid = ::getpid();
183  uint64_t tid = get_threadid();
184
185  struct kinfo_proc *kp = nullptr, *nkp;
186  size_t len = 0;
187  int error;
188  int ctl[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD,
189    (int)pid };
190
191  while (1) {
192    error = sysctl(ctl, 4, kp, &len, nullptr, 0);
193    if (kp == nullptr || (error != 0 && errno == ENOMEM)) {
194      // Add extra space in case threads are added before next call.
195      len += sizeof(*kp) + len / 10;
196      nkp = (struct kinfo_proc *)::realloc(kp, len);
197      if (nkp == nullptr) {
198        free(kp);
199        return;
200      }
201      kp = nkp;
202      continue;
203    }
204    if (error != 0)
205      len = 0;
206    break;
207  }
208
209  for (size_t i = 0; i < len / sizeof(*kp); i++) {
210    if (kp[i].ki_tid == (lwpid_t)tid) {
211      Name.append(kp[i].ki_tdname, kp[i].ki_tdname + strlen(kp[i].ki_tdname));
212      break;
213    }
214  }
215  free(kp);
216  return;
217#elif defined(__NetBSD__)
218  constexpr uint32_t len = get_max_thread_name_length_impl();
219  char buf[len];
220  ::pthread_getname_np(::pthread_self(), buf, len);
221
222  Name.append(buf, buf + strlen(buf));
223#elif defined(__OpenBSD__)
224  constexpr uint32_t len = get_max_thread_name_length_impl();
225  char buf[len];
226  ::pthread_get_name_np(::pthread_self(), buf, len);
227
228  Name.append(buf, buf + strlen(buf));
229#elif defined(__linux__)
230#if HAVE_PTHREAD_GETNAME_NP
231  constexpr uint32_t len = get_max_thread_name_length_impl();
232  char Buffer[len] = {'\0'};  // FIXME: working around MSan false positive.
233  if (0 == ::pthread_getname_np(::pthread_self(), Buffer, len))
234    Name.append(Buffer, Buffer + strlen(Buffer));
235#endif
236#endif
237}
238
239SetThreadPriorityResult llvm::set_thread_priority(ThreadPriority Priority) {
240#if defined(__linux__) && defined(SCHED_IDLE)
241  // Some *really* old glibcs are missing SCHED_IDLE.
242  // http://man7.org/linux/man-pages/man3/pthread_setschedparam.3.html
243  // http://man7.org/linux/man-pages/man2/sched_setscheduler.2.html
244  sched_param priority;
245  // For each of the above policies, param->sched_priority must be 0.
246  priority.sched_priority = 0;
247  // SCHED_IDLE    for running very low priority background jobs.
248  // SCHED_OTHER   the standard round-robin time-sharing policy;
249  return !pthread_setschedparam(
250             pthread_self(),
251             Priority == ThreadPriority::Background ? SCHED_IDLE : SCHED_OTHER,
252             &priority)
253             ? SetThreadPriorityResult::SUCCESS
254             : SetThreadPriorityResult::FAILURE;
255#elif defined(__APPLE__)
256  // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getpriority.2.html
257  // When setting a thread into background state the scheduling priority is set
258  // to lowest value, disk and network IO are throttled. Network IO will be
259  // throttled for any sockets the thread opens after going into background
260  // state. Any previously opened sockets are not affected.
261
262  // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/getiopolicy_np.3.html
263  // I/Os with THROTTLE policy are called THROTTLE I/Os. If a THROTTLE I/O
264  // request occurs within a small time window (usually a fraction of a second)
265  // of another NORMAL I/O request, the thread that issues the THROTTLE I/O is
266  // forced to sleep for a certain interval. This slows down the thread that
267  // issues the THROTTLE I/O so that NORMAL I/Os can utilize most of the disk
268  // I/O bandwidth.
269  return !setpriority(PRIO_DARWIN_THREAD, 0,
270                      Priority == ThreadPriority::Background ? PRIO_DARWIN_BG
271                                                             : 0)
272             ? SetThreadPriorityResult::SUCCESS
273             : SetThreadPriorityResult::FAILURE;
274#endif
275  return SetThreadPriorityResult::FAILURE;
276}
277
278#include <thread>
279
280int computeHostNumHardwareThreads() {
281#ifdef __linux__
282  cpu_set_t Set;
283  if (sched_getaffinity(0, sizeof(Set), &Set) == 0)
284    return CPU_COUNT(&Set);
285#endif
286  // Guard against std::thread::hardware_concurrency() returning 0.
287  if (unsigned Val = std::thread::hardware_concurrency())
288    return Val;
289  return 1;
290}
291
292void llvm::ThreadPoolStrategy::apply_thread_strategy(
293    unsigned ThreadPoolNum) const {}
294
295llvm::BitVector llvm::get_thread_affinity_mask() {
296  // FIXME: Implement
297  llvm_unreachable("Not implemented!");
298}
299
300unsigned llvm::get_cpus() { return 1; }
301