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