mirror of
https://github.com/RPCSX/llvm.git
synced 2025-04-07 18:51:48 +00:00

I did this a long time ago with a janky python script, but now clang-format has built-in support for this. I fed clang-format every line with a #include and let it re-sort things according to the precise LLVM rules for include ordering baked into clang-format these days. I've reverted a number of files where the results of sorting includes isn't healthy. Either places where we have legacy code relying on particular include ordering (where possible, I'll fix these separately) or where we have particular formatting around #include lines that I didn't want to disturb in this patch. This patch is *entirely* mechanical. If you get merge conflicts or anything, just ignore the changes in this patch and run clang-format over your #include lines in the files. Sorry for any noise here, but it is important to keep these things stable. I was seeing an increasing number of patches with irrelevant re-ordering of #include lines because clang-format was used. This patch at least isolates that churn, makes it easy to skip when resolving conflicts, and gets us to a clean baseline (again). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@304787 91177308-0d34-0410-b5e6-96231b3b80d8
216 lines
5.7 KiB
C++
216 lines
5.7 KiB
C++
//===- Unix/Threading.inc - Unix Threading Implementation ----- -*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file provides the Unix specific implementation of Threading functions.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/ADT/Twine.h"
|
|
|
|
#if defined(__APPLE__)
|
|
#include <mach/mach_init.h>
|
|
#include <mach/mach_port.h>
|
|
#endif
|
|
|
|
#include <pthread.h>
|
|
|
|
#if defined(__FreeBSD__)
|
|
#include <pthread_np.h> // For pthread_getthreadid_np()
|
|
#endif
|
|
|
|
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
|
#include <errno.h>
|
|
#include <sys/sysctl.h>
|
|
#include <sys/user.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#if defined(__NetBSD__)
|
|
#include <lwp.h> // For _lwp_self()
|
|
#endif
|
|
|
|
#if defined(__linux__)
|
|
#include <sys/syscall.h> // For syscall codes
|
|
#include <unistd.h> // For syscall()
|
|
#endif
|
|
|
|
namespace {
|
|
struct ThreadInfo {
|
|
void(*UserFn)(void *);
|
|
void *UserData;
|
|
};
|
|
}
|
|
|
|
static void *ExecuteOnThread_Dispatch(void *Arg) {
|
|
ThreadInfo *TI = reinterpret_cast<ThreadInfo*>(Arg);
|
|
TI->UserFn(TI->UserData);
|
|
return nullptr;
|
|
}
|
|
|
|
void llvm::llvm_execute_on_thread(void(*Fn)(void*), void *UserData,
|
|
unsigned RequestedStackSize) {
|
|
ThreadInfo Info = { Fn, UserData };
|
|
pthread_attr_t Attr;
|
|
pthread_t Thread;
|
|
|
|
// Construct the attributes object.
|
|
if (::pthread_attr_init(&Attr) != 0)
|
|
return;
|
|
|
|
// Set the requested stack size, if given.
|
|
if (RequestedStackSize != 0) {
|
|
if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0)
|
|
goto error;
|
|
}
|
|
|
|
// Construct and execute the thread.
|
|
if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0)
|
|
goto error;
|
|
|
|
// Wait for the thread and clean up.
|
|
::pthread_join(Thread, nullptr);
|
|
|
|
error:
|
|
::pthread_attr_destroy(&Attr);
|
|
}
|
|
|
|
|
|
uint64_t llvm::get_threadid() {
|
|
#if defined(__APPLE__)
|
|
// Calling "mach_thread_self()" bumps the reference count on the thread
|
|
// port, so we need to deallocate it. mach_task_self() doesn't bump the ref
|
|
// count.
|
|
thread_port_t Self = mach_thread_self();
|
|
mach_port_deallocate(mach_task_self(), Self);
|
|
return Self;
|
|
#elif defined(__FreeBSD__)
|
|
return uint64_t(pthread_getthreadid_np());
|
|
#elif defined(__NetBSD__)
|
|
return uint64_t(_lwp_self());
|
|
#elif defined(__ANDROID__)
|
|
return uint64_t(gettid());
|
|
#elif defined(__linux__)
|
|
return uint64_t(syscall(SYS_gettid));
|
|
#elif defined(LLVM_ON_WIN32)
|
|
return uint64_t(::GetCurrentThreadId());
|
|
#else
|
|
return uint64_t(pthread_self());
|
|
#endif
|
|
}
|
|
|
|
|
|
static constexpr uint32_t get_max_thread_name_length_impl() {
|
|
#if defined(__NetBSD__)
|
|
return PTHREAD_MAX_NAMELEN_NP;
|
|
#elif defined(__APPLE__)
|
|
return 64;
|
|
#elif defined(__linux__)
|
|
#if HAVE_PTHREAD_SETNAME_NP
|
|
return 16;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
|
return 16;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
uint32_t llvm::get_max_thread_name_length() {
|
|
return get_max_thread_name_length_impl();
|
|
}
|
|
|
|
void llvm::set_thread_name(const Twine &Name) {
|
|
// Make sure the input is null terminated.
|
|
SmallString<64> Storage;
|
|
StringRef NameStr = Name.toNullTerminatedStringRef(Storage);
|
|
|
|
// Truncate from the beginning, not the end, if the specified name is too
|
|
// long. For one, this ensures that the resulting string is still null
|
|
// terminated, but additionally the end of a long thread name will usually
|
|
// be more unique than the beginning, since a common pattern is for similar
|
|
// threads to share a common prefix.
|
|
if (get_max_thread_name_length() > 0)
|
|
NameStr = NameStr.take_back(get_max_thread_name_length());
|
|
(void)NameStr;
|
|
#if defined(__linux__)
|
|
#if (defined(__GLIBC__) && defined(_GNU_SOURCE)) || defined(__ANDROID__)
|
|
#if HAVE_PTHREAD_SETNAME_NP
|
|
::pthread_setname_np(::pthread_self(), NameStr.data());
|
|
#endif
|
|
#endif
|
|
#elif defined(__FreeBSD__)
|
|
::pthread_set_name_np(::pthread_self(), NameStr.data());
|
|
#elif defined(__NetBSD__)
|
|
::pthread_setname_np(::pthread_self(), "%s",
|
|
const_cast<char *>(NameStr.data()));
|
|
#elif defined(__APPLE__)
|
|
::pthread_setname_np(NameStr.data());
|
|
#endif
|
|
}
|
|
|
|
void llvm::get_thread_name(SmallVectorImpl<char> &Name) {
|
|
Name.clear();
|
|
|
|
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
|
int pid = ::getpid();
|
|
uint64_t tid = get_threadid();
|
|
|
|
struct kinfo_proc *kp = nullptr, *nkp;
|
|
size_t len = 0;
|
|
int error;
|
|
int ctl[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD,
|
|
(int)pid };
|
|
|
|
while (1) {
|
|
error = sysctl(ctl, 4, kp, &len, nullptr, 0);
|
|
if (kp == nullptr || (error != 0 && errno == ENOMEM)) {
|
|
// Add extra space in case threads are added before next call.
|
|
len += sizeof(*kp) + len / 10;
|
|
nkp = (struct kinfo_proc *)realloc(kp, len);
|
|
if (nkp == nullptr) {
|
|
free(kp);
|
|
return;
|
|
}
|
|
kp = nkp;
|
|
continue;
|
|
}
|
|
if (error != 0)
|
|
len = 0;
|
|
break;
|
|
}
|
|
|
|
for (size_t i = 0; i < len / sizeof(*kp); i++) {
|
|
if (kp[i].ki_tid == (lwpid_t)tid) {
|
|
Name.append(kp[i].ki_tdname, kp[i].ki_tdname + strlen(kp[i].ki_tdname));
|
|
break;
|
|
}
|
|
}
|
|
free(kp);
|
|
return;
|
|
#elif defined(__NetBSD__)
|
|
constexpr uint32_t len = get_max_thread_name_length_impl();
|
|
char buf[len];
|
|
::pthread_getname_np(::pthread_self(), buf, len);
|
|
|
|
Name.append(buf, buf + strlen(buf));
|
|
#elif defined(__linux__)
|
|
#if (defined(__GLIBC__) && defined(_GNU_SOURCE)) || defined(__ANDROID__)
|
|
#if HAVE_PTHREAD_GETNAME_NP
|
|
constexpr uint32_t len = get_max_thread_name_length_impl();
|
|
char Buffer[len];
|
|
if (0 == ::pthread_getname_np(::pthread_self(), Buffer, len))
|
|
Name.append(Buffer, Buffer + strlen(Buffer));
|
|
#endif
|
|
#endif
|
|
#endif
|
|
}
|