You've already forked linux-packaging-mono
acceptance-tests
data
debian
docs
external
Newtonsoft.Json
api-doc-tools
api-snapshot
aspnetwebstack
binary-reference-assemblies
bockbuild
boringssl
cecil
cecil-legacy
corefx
corert
helix-binaries
ikdasm
ikvm
linker
llvm
bindings
cmake
docs
examples
include
lib
Analysis
AsmParser
BinaryFormat
Bitcode
CodeGen
DebugInfo
Demangle
ExecutionEngine
FuzzMutate
Fuzzer
IR
IRReader
LTO
LineEditor
Linker
MC
Object
ObjectYAML
Option
Passes
ProfileData
Support
Unix
COM.inc
DynamicLibrary.inc
Host.inc
Memory.inc
Mutex.inc
Path.inc
Process.inc
Program.inc
README.txt
RWMutex.inc
Signals.inc
ThreadLocal.inc
Threading.inc
Unix.h
Watchdog.inc
Windows
AMDGPUMetadata.cpp
APFloat.cpp.REMOVED.git-id
APInt.cpp
APSInt.cpp
ARMAttributeParser.cpp
ARMBuildAttrs.cpp
ARMWinEH.cpp
Allocator.cpp
Atomic.cpp
BinaryStreamError.cpp
BinaryStreamReader.cpp
BinaryStreamRef.cpp
BinaryStreamWriter.cpp
BlockFrequency.cpp
BranchProbability.cpp
CMakeLists.txt
COM.cpp
COPYRIGHT.regex
CachePruning.cpp
Chrono.cpp
CodeGenCoverage.cpp
CommandLine.cpp
Compression.cpp
ConvertUTF.cpp
ConvertUTFWrapper.cpp
CrashRecoveryContext.cpp
DAGDeltaAlgorithm.cpp
DataExtractor.cpp
Debug.cpp
DebugCounter.cpp
DeltaAlgorithm.cpp
DynamicLibrary.cpp
Errno.cpp
Error.cpp
ErrorHandling.cpp
FileOutputBuffer.cpp
FileUtilities.cpp
FoldingSet.cpp
FormatVariadic.cpp
FormattedStream.cpp
GlobPattern.cpp
GraphWriter.cpp
Hashing.cpp
Host.cpp
IntEqClasses.cpp
IntervalMap.cpp
JamCRC.cpp
KnownBits.cpp
LEB128.cpp
LLVMBuild.txt
LineIterator.cpp
Locale.cpp
LockFileManager.cpp
LowLevelType.cpp
MD5.cpp
ManagedStatic.cpp
MathExtras.cpp
Memory.cpp
MemoryBuffer.cpp
Mutex.cpp
NativeFormatting.cpp
Options.cpp
Parallel.cpp
Path.cpp
PluginLoader.cpp
PrettyStackTrace.cpp
Process.cpp
Program.cpp
README.txt.system
RWMutex.cpp
RandomNumberGenerator.cpp
Regex.cpp
SHA1.cpp
ScaledNumber.cpp
ScopedPrinter.cpp
Signals.cpp
SmallPtrSet.cpp
SmallVector.cpp
SourceMgr.cpp
SpecialCaseList.cpp
Statistic.cpp
StringExtras.cpp
StringMap.cpp
StringPool.cpp
StringRef.cpp
StringSaver.cpp
SystemUtils.cpp
TarWriter.cpp
TargetParser.cpp
TargetRegistry.cpp
ThreadLocal.cpp
ThreadPool.cpp
Threading.cpp
Timer.cpp
ToolOutputFile.cpp
TrigramIndex.cpp
Triple.cpp
Twine.cpp
Unicode.cpp
Valgrind.cpp
Watchdog.cpp
YAMLParser.cpp
YAMLTraits.cpp
circular_raw_ostream.cpp
raw_os_ostream.cpp
raw_ostream.cpp
regcomp.c
regengine.inc
regerror.c
regex2.h
regex_impl.h
regexec.c
regfree.c
regstrlcpy.c
regutils.h
xxhash.cpp
TableGen
Target
Testing
ToolDrivers
Transforms
WindowsManifest
XRay
CMakeLists.txt
LLVMBuild.txt
projects
resources
runtimes
scripts
test
tools
unittests
utils
.arcconfig
.clang-format
.clang-tidy
.gitattributes
.gitignore
CMakeLists.txt
CODE_OWNERS.TXT
CREDITS.TXT
LICENSE.TXT
LLVMBuild.txt
README.txt
RELEASE_TESTERS.TXT
configure
llvm.spec.in
nuget-buildtasks
nunit-lite
roslyn-binaries
rx
xunit-binaries
ikvm-native
libgc
llvm
m4
man
mcs
mk
mono
msvc
po
runtime
samples
scripts
support
tools
COPYING.LIB
LICENSE
Makefile.am
Makefile.in
NEWS
README.md
acinclude.m4
aclocal.m4
autogen.sh
code_of_conduct.md
compile
config.guess
config.h.in
config.rpath
config.sub
configure.REMOVED.git-id
configure.ac.REMOVED.git-id
depcomp
install-sh
ltmain.sh.REMOVED.git-id
missing
mkinstalldirs
mono-uninstalled.pc.in
test-driver
winconfig.h
216 lines
5.8 KiB
PHP
216 lines
5.8 KiB
PHP
![]() |
//===- 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] = {'\0'}; // FIXME: working around MSan false positive.
|
||
|
if (0 == ::pthread_getname_np(::pthread_self(), Buffer, len))
|
||
|
Name.append(Buffer, Buffer + strlen(Buffer));
|
||
|
#endif
|
||
|
#endif
|
||
|
#endif
|
||
|
}
|