Imported Upstream version 5.18.0.167

Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-10-20 08:25:10 +00:00
parent e19d552987
commit b084638f15
28489 changed files with 184 additions and 3866856 deletions

View File

@ -1,27 +0,0 @@
//===- llvm/Support/Unix/COM.inc - Unix COM 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 implements the Unix portion of COM support.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only generic UNIX code that
//=== is guaranteed to work on *all* UNIX variants.
//===----------------------------------------------------------------------===//
namespace llvm {
namespace sys {
InitializeCOMRAII::InitializeCOMRAII(COMThreadingMode Threading,
bool SpeedOverMemory) {}
InitializeCOMRAII::~InitializeCOMRAII() {}
}
}

View File

@ -1,135 +0,0 @@
//===- Unix/DynamicLibrary.cpp - Unix DL 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 DynamicLibrary.
//
//===----------------------------------------------------------------------===//
#if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
#include <dlfcn.h>
DynamicLibrary::HandleSet::~HandleSet() {
// Close the libraries in reverse order.
for (void *Handle : llvm::reverse(Handles))
::dlclose(Handle);
if (Process)
::dlclose(Process);
// llvm_shutdown called, Return to default
DynamicLibrary::SearchOrder = DynamicLibrary::SO_Linker;
}
void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
void *Handle = ::dlopen(File, RTLD_LAZY|RTLD_GLOBAL);
if (!Handle) {
if (Err) *Err = ::dlerror();
return &DynamicLibrary::Invalid;
}
#ifdef __CYGWIN__
// Cygwin searches symbols only in the main
// with the handle of dlopen(NULL, RTLD_GLOBAL).
if (!File)
Handle = RTLD_DEFAULT;
#endif
return Handle;
}
void DynamicLibrary::HandleSet::DLClose(void *Handle) {
::dlclose(Handle);
}
void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
return ::dlsym(Handle, Symbol);
}
#else // !HAVE_DLOPEN
DynamicLibrary::HandleSet::~HandleSet() {}
void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
if (Err) *Err = "dlopen() not supported on this platform";
return &Invalid;
}
void DynamicLibrary::HandleSet::DLClose(void *Handle) {
}
void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
return nullptr;
}
#endif
// Must declare the symbols in the global namespace.
static void *DoSearch(const char* SymbolName) {
#define EXPLICIT_SYMBOL(SYM) \
extern void *SYM; if (!strcmp(SymbolName, #SYM)) return (void*)&SYM
// If this is darwin, it has some funky issues, try to solve them here. Some
// important symbols are marked 'private external' which doesn't allow
// SearchForAddressOfSymbol to find them. As such, we special case them here,
// there is only a small handful of them.
#ifdef __APPLE__
{
// __eprintf is sometimes used for assert() handling on x86.
//
// FIXME: Currently disabled when using Clang, as we don't always have our
// runtime support libraries available.
#ifndef __clang__
#ifdef __i386__
EXPLICIT_SYMBOL(__eprintf);
#endif
#endif
}
#endif
#ifdef __CYGWIN__
{
EXPLICIT_SYMBOL(_alloca);
EXPLICIT_SYMBOL(__main);
}
#endif
#undef EXPLICIT_SYMBOL
// This macro returns the address of a well-known, explicit symbol
#define EXPLICIT_SYMBOL(SYM) \
if (!strcmp(SymbolName, #SYM)) return &SYM
// Under glibc we have a weird situation. The stderr/out/in symbols are both
// macros and global variables because of standards requirements. So, we
// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
#if defined(__GLIBC__)
{
EXPLICIT_SYMBOL(stderr);
EXPLICIT_SYMBOL(stdout);
EXPLICIT_SYMBOL(stdin);
}
#else
// For everything else, we want to check to make sure the symbol isn't defined
// as a macro before using EXPLICIT_SYMBOL.
{
#ifndef stdin
EXPLICIT_SYMBOL(stdin);
#endif
#ifndef stdout
EXPLICIT_SYMBOL(stdout);
#endif
#ifndef stderr
EXPLICIT_SYMBOL(stderr);
#endif
}
#endif
#undef EXPLICIT_SYMBOL
return nullptr;
}

View File

@ -1,68 +0,0 @@
//===- llvm/Support/Unix/Host.inc -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the UNIX Host support.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only generic UNIX code that
//=== is guaranteed to work on *all* UNIX variants.
//===----------------------------------------------------------------------===//
#include "Unix.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Config/config.h"
#include <cctype>
#include <string>
#include <sys/utsname.h>
using namespace llvm;
static std::string getOSVersion() {
struct utsname info;
if (uname(&info))
return "";
return info.release;
}
static std::string updateTripleOSVersion(std::string TargetTripleString) {
// On darwin, we want to update the version to match that of the target.
std::string::size_type DarwinDashIdx = TargetTripleString.find("-darwin");
if (DarwinDashIdx != std::string::npos) {
TargetTripleString.resize(DarwinDashIdx + strlen("-darwin"));
TargetTripleString += getOSVersion();
return TargetTripleString;
}
std::string::size_type MacOSDashIdx = TargetTripleString.find("-macos");
if (MacOSDashIdx != std::string::npos) {
TargetTripleString.resize(MacOSDashIdx);
// Reset the OS to darwin as the OS version from `uname` doesn't use the
// macOS version scheme.
TargetTripleString += "-darwin";
TargetTripleString += getOSVersion();
}
return TargetTripleString;
}
std::string sys::getDefaultTargetTriple() {
std::string TargetTripleString =
updateTripleOSVersion(LLVM_DEFAULT_TARGET_TRIPLE);
// Override the default target with an environment variable named by
// LLVM_TARGET_TRIPLE_ENV.
#if defined(LLVM_TARGET_TRIPLE_ENV)
if (const char *EnvTriple = std::getenv(LLVM_TARGET_TRIPLE_ENV))
TargetTripleString = EnvTriple;
#endif
return Triple::normalize(TargetTripleString);
}

View File

@ -1,239 +0,0 @@
//===- Unix/Memory.cpp - Generic UNIX System Configuration ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines some functions for various memory management utilities.
//
//===----------------------------------------------------------------------===//
#include "Unix.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Process.h"
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#ifdef __APPLE__
#include <mach/mach.h>
#endif
#if defined(__mips__)
# if defined(__OpenBSD__)
# include <mips64/sysarch.h>
# elif !defined(__FreeBSD__)
# include <sys/cachectl.h>
# endif
#endif
#ifdef __APPLE__
extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
#else
extern "C" void __clear_cache(void *, void*);
#endif
namespace {
int getPosixProtectionFlags(unsigned Flags) {
switch (Flags) {
case llvm::sys::Memory::MF_READ:
return PROT_READ;
case llvm::sys::Memory::MF_WRITE:
return PROT_WRITE;
case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_WRITE:
return PROT_READ | PROT_WRITE;
case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_EXEC:
return PROT_READ | PROT_EXEC;
case llvm::sys::Memory::MF_READ | llvm::sys::Memory::MF_WRITE |
llvm::sys::Memory::MF_EXEC:
return PROT_READ | PROT_WRITE | PROT_EXEC;
case llvm::sys::Memory::MF_EXEC:
#if defined(__FreeBSD__)
// On PowerPC, having an executable page that has no read permission
// can have unintended consequences. The function InvalidateInstruction-
// Cache uses instructions dcbf and icbi, both of which are treated by
// the processor as loads. If the page has no read permissions,
// executing these instructions will result in a segmentation fault.
// Somehow, this problem is not present on Linux, but it does happen
// on FreeBSD.
return PROT_READ | PROT_EXEC;
#else
return PROT_EXEC;
#endif
default:
llvm_unreachable("Illegal memory protection flag specified!");
}
// Provide a default return value as required by some compilers.
return PROT_NONE;
}
} // anonymous namespace
namespace llvm {
namespace sys {
MemoryBlock
Memory::allocateMappedMemory(size_t NumBytes,
const MemoryBlock *const NearBlock,
unsigned PFlags,
std::error_code &EC) {
EC = std::error_code();
if (NumBytes == 0)
return MemoryBlock();
static const size_t PageSize = Process::getPageSize();
const size_t NumPages = (NumBytes+PageSize-1)/PageSize;
int fd = -1;
int MMFlags = MAP_PRIVATE |
#ifdef MAP_ANONYMOUS
MAP_ANONYMOUS
#else
MAP_ANON
#endif
; // Ends statement above
int Protect = getPosixProtectionFlags(PFlags);
#if defined(__NetBSD__) && defined(PROT_MPROTECT)
Protect |= PROT_MPROTECT(PROT_READ | PROT_WRITE | PROT_EXEC);
#endif
// Use any near hint and the page size to set a page-aligned starting address
uintptr_t Start = NearBlock ? reinterpret_cast<uintptr_t>(NearBlock->base()) +
NearBlock->size() : 0;
if (Start && Start % PageSize)
Start += PageSize - Start % PageSize;
void *Addr = ::mmap(reinterpret_cast<void*>(Start), PageSize*NumPages,
Protect, MMFlags, fd, 0);
if (Addr == MAP_FAILED) {
if (NearBlock) //Try again without a near hint
return allocateMappedMemory(NumBytes, nullptr, PFlags, EC);
EC = std::error_code(errno, std::generic_category());
return MemoryBlock();
}
MemoryBlock Result;
Result.Address = Addr;
Result.Size = NumPages*PageSize;
// Rely on protectMappedMemory to invalidate instruction cache.
if (PFlags & MF_EXEC) {
EC = Memory::protectMappedMemory (Result, PFlags);
if (EC != std::error_code())
return MemoryBlock();
}
return Result;
}
std::error_code
Memory::releaseMappedMemory(MemoryBlock &M) {
if (M.Address == nullptr || M.Size == 0)
return std::error_code();
if (0 != ::munmap(M.Address, M.Size))
return std::error_code(errno, std::generic_category());
M.Address = nullptr;
M.Size = 0;
return std::error_code();
}
std::error_code
Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) {
static const size_t PageSize = Process::getPageSize();
if (M.Address == nullptr || M.Size == 0)
return std::error_code();
if (!Flags)
return std::error_code(EINVAL, std::generic_category());
int Protect = getPosixProtectionFlags(Flags);
uintptr_t Start = alignAddr((uint8_t *)M.Address - PageSize + 1, PageSize);
uintptr_t End = alignAddr((uint8_t *)M.Address + M.Size, PageSize);
bool InvalidateCache = (Flags & MF_EXEC);
#if defined(__arm__) || defined(__aarch64__)
// Certain ARM implementations treat icache clear instruction as a memory read,
// and CPU segfaults on trying to clear cache on !PROT_READ page. Therefore we need
// to temporarily add PROT_READ for the sake of flushing the instruction caches.
if (InvalidateCache && !(Protect & PROT_READ)) {
int Result = ::mprotect((void *)Start, End - Start, Protect | PROT_READ);
if (Result != 0)
return std::error_code(errno, std::generic_category());
Memory::InvalidateInstructionCache(M.Address, M.Size);
InvalidateCache = false;
}
#endif
int Result = ::mprotect((void *)Start, End - Start, Protect);
if (Result != 0)
return std::error_code(errno, std::generic_category());
if (InvalidateCache)
Memory::InvalidateInstructionCache(M.Address, M.Size);
return std::error_code();
}
/// InvalidateInstructionCache - Before the JIT can run a block of code
/// that has been emitted it must invalidate the instruction cache on some
/// platforms.
void Memory::InvalidateInstructionCache(const void *Addr,
size_t Len) {
// icache invalidation for PPC and ARM.
#if defined(__APPLE__)
# if (defined(__POWERPC__) || defined (__ppc__) || \
defined(_POWER) || defined(_ARCH_PPC) || defined(__arm__) || \
defined(__arm64__))
sys_icache_invalidate(const_cast<void *>(Addr), Len);
# endif
#else
# if (defined(__POWERPC__) || defined (__ppc__) || \
defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__)
const size_t LineSize = 32;
const intptr_t Mask = ~(LineSize - 1);
const intptr_t StartLine = ((intptr_t) Addr) & Mask;
const intptr_t EndLine = ((intptr_t) Addr + Len + LineSize - 1) & Mask;
for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
asm volatile("dcbf 0, %0" : : "r"(Line));
asm volatile("sync");
for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
asm volatile("icbi 0, %0" : : "r"(Line));
asm volatile("isync");
# elif (defined(__arm__) || defined(__aarch64__) || defined(__mips__)) && \
defined(__GNUC__)
// FIXME: Can we safely always call this for __GNUC__ everywhere?
const char *Start = static_cast<const char *>(Addr);
const char *End = Start + Len;
__clear_cache(const_cast<char *>(Start), const_cast<char *>(End));
# endif
#endif // end apple
ValgrindDiscardTranslations(Addr, Len);
}
} // namespace sys
} // namespace llvm

View File

@ -1,43 +0,0 @@
//===- llvm/Support/Unix/Mutex.inc - Unix Mutex 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 implements the Unix specific (non-pthread) Mutex class.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only generic UNIX code that
//=== is guaranteed to work on *all* UNIX variants.
//===----------------------------------------------------------------------===//
namespace llvm
{
using namespace sys;
MutexImpl::MutexImpl( bool recursive)
{
}
MutexImpl::~MutexImpl()
{
}
bool
MutexImpl::release()
{
return true;
}
bool
MutexImpl::tryacquire( void )
{
return true;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,450 +0,0 @@
//===- Unix/Process.cpp - Unix Process 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 generic Unix implementation of the Process class.
//
//===----------------------------------------------------------------------===//
#include "Unix.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/MutexGuard.h"
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SIGNAL_H
#include <signal.h>
#endif
// DragonFlyBSD, and OpenBSD have deprecated <malloc.h> for
// <stdlib.h> instead. Unix.h includes this for us already.
#if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \
!defined(__OpenBSD__)
#include <malloc.h>
#endif
#if defined(HAVE_MALLCTL)
#include <malloc_np.h>
#endif
#ifdef HAVE_MALLOC_MALLOC_H
#include <malloc/malloc.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#ifdef HAVE_TERMIOS_H
# include <termios.h>
#endif
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only generic UNIX code that
//=== is guaranteed to work on *all* UNIX variants.
//===----------------------------------------------------------------------===//
using namespace llvm;
using namespace sys;
static std::pair<std::chrono::microseconds, std::chrono::microseconds> getRUsageTimes() {
#if defined(HAVE_GETRUSAGE)
struct rusage RU;
::getrusage(RUSAGE_SELF, &RU);
return { toDuration(RU.ru_utime), toDuration(RU.ru_stime) };
#else
#warning Cannot get usage times on this platform
return { std::chrono::microseconds::zero(), std::chrono::microseconds::zero() };
#endif
}
// On Cygwin, getpagesize() returns 64k(AllocationGranularity) and
// offset in mmap(3) should be aligned to the AllocationGranularity.
unsigned Process::getPageSize() {
#if defined(HAVE_GETPAGESIZE)
static const int page_size = ::getpagesize();
#elif defined(HAVE_SYSCONF)
static long page_size = ::sysconf(_SC_PAGE_SIZE);
#else
#warning Cannot get the page size on this machine
#endif
return static_cast<unsigned>(page_size);
}
size_t Process::GetMallocUsage() {
#if defined(HAVE_MALLINFO)
struct mallinfo mi;
mi = ::mallinfo();
return mi.uordblks;
#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
malloc_statistics_t Stats;
malloc_zone_statistics(malloc_default_zone(), &Stats);
return Stats.size_in_use; // darwin
#elif defined(HAVE_MALLCTL)
size_t alloc, sz;
sz = sizeof(size_t);
if (mallctl("stats.allocated", &alloc, &sz, NULL, 0) == 0)
return alloc;
return 0;
#elif defined(HAVE_SBRK)
// Note this is only an approximation and more closely resembles
// the value returned by mallinfo in the arena field.
static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
char *EndOfMemory = (char*)sbrk(0);
if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
return EndOfMemory - StartOfMemory;
return 0;
#else
#warning Cannot get malloc info on this platform
return 0;
#endif
}
void Process::GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time,
std::chrono::nanoseconds &sys_time) {
elapsed = std::chrono::system_clock::now();
std::tie(user_time, sys_time) = getRUsageTimes();
}
#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
#include <mach/mach.h>
#endif
// Some LLVM programs such as bugpoint produce core files as a normal part of
// their operation. To prevent the disk from filling up, this function
// does what's necessary to prevent their generation.
void Process::PreventCoreFiles() {
#if HAVE_SETRLIMIT
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max = 0;
setrlimit(RLIMIT_CORE, &rlim);
#endif
#if defined(HAVE_MACH_MACH_H) && !defined(__GNU__)
// Disable crash reporting on Mac OS X 10.0-10.4
// get information about the original set of exception ports for the task
mach_msg_type_number_t Count = 0;
exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
exception_port_t OriginalPorts[EXC_TYPES_COUNT];
exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
kern_return_t err =
task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
&Count, OriginalPorts, OriginalBehaviors,
OriginalFlavors);
if (err == KERN_SUCCESS) {
// replace each with MACH_PORT_NULL.
for (unsigned i = 0; i != Count; ++i)
task_set_exception_ports(mach_task_self(), OriginalMasks[i],
MACH_PORT_NULL, OriginalBehaviors[i],
OriginalFlavors[i]);
}
// Disable crash reporting on Mac OS X 10.5
signal(SIGABRT, _exit);
signal(SIGILL, _exit);
signal(SIGFPE, _exit);
signal(SIGSEGV, _exit);
signal(SIGBUS, _exit);
#endif
coreFilesPrevented = true;
}
Optional<std::string> Process::GetEnv(StringRef Name) {
std::string NameStr = Name.str();
const char *Val = ::getenv(NameStr.c_str());
if (!Val)
return None;
return std::string(Val);
}
std::error_code
Process::GetArgumentVector(SmallVectorImpl<const char *> &ArgsOut,
ArrayRef<const char *> ArgsIn,
SpecificBumpPtrAllocator<char> &) {
ArgsOut.append(ArgsIn.begin(), ArgsIn.end());
return std::error_code();
}
namespace {
class FDCloser {
public:
FDCloser(int &FD) : FD(FD), KeepOpen(false) {}
void keepOpen() { KeepOpen = true; }
~FDCloser() {
if (!KeepOpen && FD >= 0)
::close(FD);
}
private:
FDCloser(const FDCloser &) = delete;
void operator=(const FDCloser &) = delete;
int &FD;
bool KeepOpen;
};
}
std::error_code Process::FixupStandardFileDescriptors() {
int NullFD = -1;
FDCloser FDC(NullFD);
const int StandardFDs[] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
for (int StandardFD : StandardFDs) {
struct stat st;
errno = 0;
if (RetryAfterSignal(-1, fstat, StandardFD, &st) < 0) {
assert(errno && "expected errno to be set if fstat failed!");
// fstat should return EBADF if the file descriptor is closed.
if (errno != EBADF)
return std::error_code(errno, std::generic_category());
}
// if fstat succeeds, move on to the next FD.
if (!errno)
continue;
assert(errno == EBADF && "expected errno to have EBADF at this point!");
if (NullFD < 0) {
if ((NullFD = RetryAfterSignal(-1, open, "/dev/null", O_RDWR)) < 0)
return std::error_code(errno, std::generic_category());
}
if (NullFD == StandardFD)
FDC.keepOpen();
else if (dup2(NullFD, StandardFD) < 0)
return std::error_code(errno, std::generic_category());
}
return std::error_code();
}
std::error_code Process::SafelyCloseFileDescriptor(int FD) {
// Create a signal set filled with *all* signals.
sigset_t FullSet;
if (sigfillset(&FullSet) < 0)
return std::error_code(errno, std::generic_category());
// Atomically swap our current signal mask with a full mask.
sigset_t SavedSet;
#if LLVM_ENABLE_THREADS
if (int EC = pthread_sigmask(SIG_SETMASK, &FullSet, &SavedSet))
return std::error_code(EC, std::generic_category());
#else
if (sigprocmask(SIG_SETMASK, &FullSet, &SavedSet) < 0)
return std::error_code(errno, std::generic_category());
#endif
// Attempt to close the file descriptor.
// We need to save the error, if one occurs, because our subsequent call to
// pthread_sigmask might tamper with errno.
int ErrnoFromClose = 0;
if (::close(FD) < 0)
ErrnoFromClose = errno;
// Restore the signal mask back to what we saved earlier.
int EC = 0;
#if LLVM_ENABLE_THREADS
EC = pthread_sigmask(SIG_SETMASK, &SavedSet, nullptr);
#else
if (sigprocmask(SIG_SETMASK, &SavedSet, nullptr) < 0)
EC = errno;
#endif
// The error code from close takes precedence over the one from
// pthread_sigmask.
if (ErrnoFromClose)
return std::error_code(ErrnoFromClose, std::generic_category());
return std::error_code(EC, std::generic_category());
}
bool Process::StandardInIsUserInput() {
return FileDescriptorIsDisplayed(STDIN_FILENO);
}
bool Process::StandardOutIsDisplayed() {
return FileDescriptorIsDisplayed(STDOUT_FILENO);
}
bool Process::StandardErrIsDisplayed() {
return FileDescriptorIsDisplayed(STDERR_FILENO);
}
bool Process::FileDescriptorIsDisplayed(int fd) {
#if HAVE_ISATTY
return isatty(fd);
#else
// If we don't have isatty, just return false.
return false;
#endif
}
static unsigned getColumns(int FileID) {
// If COLUMNS is defined in the environment, wrap to that many columns.
if (const char *ColumnsStr = std::getenv("COLUMNS")) {
int Columns = std::atoi(ColumnsStr);
if (Columns > 0)
return Columns;
}
unsigned Columns = 0;
#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
// Try to determine the width of the terminal.
struct winsize ws;
if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
Columns = ws.ws_col;
#endif
return Columns;
}
unsigned Process::StandardOutColumns() {
if (!StandardOutIsDisplayed())
return 0;
return getColumns(1);
}
unsigned Process::StandardErrColumns() {
if (!StandardErrIsDisplayed())
return 0;
return getColumns(2);
}
#ifdef HAVE_TERMINFO
// We manually declare these extern functions because finding the correct
// headers from various terminfo, curses, or other sources is harder than
// writing their specs down.
extern "C" int setupterm(char *term, int filedes, int *errret);
extern "C" struct term *set_curterm(struct term *termp);
extern "C" int del_curterm(struct term *termp);
extern "C" int tigetnum(char *capname);
#endif
#ifdef HAVE_TERMINFO
static ManagedStatic<sys::Mutex> TermColorMutex;
#endif
static bool terminalHasColors(int fd) {
#ifdef HAVE_TERMINFO
// First, acquire a global lock because these C routines are thread hostile.
MutexGuard G(*TermColorMutex);
int errret = 0;
if (setupterm(nullptr, fd, &errret) != 0)
// Regardless of why, if we can't get terminfo, we shouldn't try to print
// colors.
return false;
// Test whether the terminal as set up supports color output. How to do this
// isn't entirely obvious. We can use the curses routine 'has_colors' but it
// would be nice to avoid a dependency on curses proper when we can make do
// with a minimal terminfo parsing library. Also, we don't really care whether
// the terminal supports the curses-specific color changing routines, merely
// if it will interpret ANSI color escape codes in a reasonable way. Thus, the
// strategy here is just to query the baseline colors capability and if it
// supports colors at all to assume it will translate the escape codes into
// whatever range of colors it does support. We can add more detailed tests
// here if users report them as necessary.
//
// The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
// the terminfo says that no colors are supported.
bool HasColors = tigetnum(const_cast<char *>("colors")) > 0;
// Now extract the structure allocated by setupterm and free its memory
// through a really silly dance.
struct term *termp = set_curterm(nullptr);
(void)del_curterm(termp); // Drop any errors here.
// Return true if we found a color capabilities for the current terminal.
if (HasColors)
return true;
#endif
// Otherwise, be conservative.
return false;
}
bool Process::FileDescriptorHasColors(int fd) {
// A file descriptor has colors if it is displayed and the terminal has
// colors.
return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd);
}
bool Process::StandardOutHasColors() {
return FileDescriptorHasColors(STDOUT_FILENO);
}
bool Process::StandardErrHasColors() {
return FileDescriptorHasColors(STDERR_FILENO);
}
void Process::UseANSIEscapeCodes(bool /*enable*/) {
// No effect.
}
bool Process::ColorNeedsFlush() {
// No, we use ANSI escape sequences.
return false;
}
const char *Process::OutputColor(char code, bool bold, bool bg) {
return colorcodes[bg?1:0][bold?1:0][code&7];
}
const char *Process::OutputBold(bool bg) {
return "\033[1m";
}
const char *Process::OutputReverse() {
return "\033[7m";
}
const char *Process::ResetColor() {
return "\033[0m";
}
#if !HAVE_DECL_ARC4RANDOM
static unsigned GetRandomNumberSeed() {
// Attempt to get the initial seed from /dev/urandom, if possible.
int urandomFD = open("/dev/urandom", O_RDONLY);
if (urandomFD != -1) {
unsigned seed;
// Don't use a buffered read to avoid reading more data
// from /dev/urandom than we need.
int count = read(urandomFD, (void *)&seed, sizeof(seed));
close(urandomFD);
// Return the seed if the read was successful.
if (count == sizeof(seed))
return seed;
}
// Otherwise, swizzle the current time and the process ID to form a reasonable
// seed.
const auto Now = std::chrono::high_resolution_clock::now();
return hash_combine(Now.time_since_epoch().count(), ::getpid());
}
#endif
unsigned llvm::sys::Process::GetRandomNumber() {
#if HAVE_DECL_ARC4RANDOM
return arc4random();
#else
static int x = (static_cast<void>(::srand(GetRandomNumberSeed())), 0);
(void)x;
return ::rand();
#endif
}

View File

@ -1,465 +0,0 @@
//===- llvm/Support/Unix/Program.cpp -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Unix specific portion of the Program class.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only generic UNIX code that
//=== is guaranteed to work on *all* UNIX variants.
//===----------------------------------------------------------------------===//
#include "Unix.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#if HAVE_SIGNAL_H
#include <signal.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_POSIX_SPAWN
#include <spawn.h>
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
#if defined(__APPLE__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
#define USE_NSGETENVIRON 1
#else
#define USE_NSGETENVIRON 0
#endif
#if !USE_NSGETENVIRON
extern char **environ;
#else
#include <crt_externs.h> // _NSGetEnviron
#endif
#endif
namespace llvm {
using namespace sys;
ProcessInfo::ProcessInfo() : Pid(0), ReturnCode(0) {}
ErrorOr<std::string> sys::findProgramByName(StringRef Name,
ArrayRef<StringRef> Paths) {
assert(!Name.empty() && "Must have a name!");
// Use the given path verbatim if it contains any slashes; this matches
// the behavior of sh(1) and friends.
if (Name.find('/') != StringRef::npos)
return std::string(Name);
SmallVector<StringRef, 16> EnvironmentPaths;
if (Paths.empty())
if (const char *PathEnv = std::getenv("PATH")) {
SplitString(PathEnv, EnvironmentPaths, ":");
Paths = EnvironmentPaths;
}
for (auto Path : Paths) {
if (Path.empty())
continue;
// Check to see if this first directory contains the executable...
SmallString<128> FilePath(Path);
sys::path::append(FilePath, Name);
if (sys::fs::can_execute(FilePath.c_str()))
return std::string(FilePath.str()); // Found the executable!
}
return errc::no_such_file_or_directory;
}
static bool RedirectIO(Optional<StringRef> Path, int FD, std::string* ErrMsg) {
if (!Path) // Noop
return false;
std::string File;
if (Path->empty())
// Redirect empty paths to /dev/null
File = "/dev/null";
else
File = *Path;
// Open the file
int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666);
if (InFD == -1) {
MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for "
+ (FD == 0 ? "input" : "output"));
return true;
}
// Install it as the requested FD
if (dup2(InFD, FD) == -1) {
MakeErrMsg(ErrMsg, "Cannot dup2");
close(InFD);
return true;
}
close(InFD); // Close the original FD
return false;
}
#ifdef HAVE_POSIX_SPAWN
static bool RedirectIO_PS(const std::string *Path, int FD, std::string *ErrMsg,
posix_spawn_file_actions_t *FileActions) {
if (!Path) // Noop
return false;
const char *File;
if (Path->empty())
// Redirect empty paths to /dev/null
File = "/dev/null";
else
File = Path->c_str();
if (int Err = posix_spawn_file_actions_addopen(
FileActions, FD, File,
FD == 0 ? O_RDONLY : O_WRONLY | O_CREAT, 0666))
return MakeErrMsg(ErrMsg, "Cannot dup2", Err);
return false;
}
#endif
static void TimeOutHandler(int Sig) {
}
static void SetMemoryLimits(unsigned size) {
#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT
struct rlimit r;
__typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576;
// Heap size
getrlimit (RLIMIT_DATA, &r);
r.rlim_cur = limit;
setrlimit (RLIMIT_DATA, &r);
#ifdef RLIMIT_RSS
// Resident set size.
getrlimit (RLIMIT_RSS, &r);
r.rlim_cur = limit;
setrlimit (RLIMIT_RSS, &r);
#endif
#endif
}
}
static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args,
const char **Envp, ArrayRef<Optional<StringRef>> Redirects,
unsigned MemoryLimit, std::string *ErrMsg) {
if (!llvm::sys::fs::exists(Program)) {
if (ErrMsg)
*ErrMsg = std::string("Executable \"") + Program.str() +
std::string("\" doesn't exist!");
return false;
}
// If this OS has posix_spawn and there is no memory limit being implied, use
// posix_spawn. It is more efficient than fork/exec.
#ifdef HAVE_POSIX_SPAWN
if (MemoryLimit == 0) {
posix_spawn_file_actions_t FileActionsStore;
posix_spawn_file_actions_t *FileActions = nullptr;
// If we call posix_spawn_file_actions_addopen we have to make sure the
// c strings we pass to it stay alive until the call to posix_spawn,
// so we copy any StringRefs into this variable.
std::string RedirectsStorage[3];
if (!Redirects.empty()) {
assert(Redirects.size() == 3);
std::string *RedirectsStr[3] = {nullptr, nullptr, nullptr};
for (int I = 0; I < 3; ++I) {
if (Redirects[I]) {
RedirectsStorage[I] = *Redirects[I];
RedirectsStr[I] = &RedirectsStorage[I];
}
}
FileActions = &FileActionsStore;
posix_spawn_file_actions_init(FileActions);
// Redirect stdin/stdout.
if (RedirectIO_PS(RedirectsStr[0], 0, ErrMsg, FileActions) ||
RedirectIO_PS(RedirectsStr[1], 1, ErrMsg, FileActions))
return false;
if (!Redirects[1] || !Redirects[2] || *Redirects[1] != *Redirects[2]) {
// Just redirect stderr
if (RedirectIO_PS(RedirectsStr[2], 2, ErrMsg, FileActions))
return false;
} else {
// If stdout and stderr should go to the same place, redirect stderr
// to the FD already open for stdout.
if (int Err = posix_spawn_file_actions_adddup2(FileActions, 1, 2))
return !MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout", Err);
}
}
if (!Envp)
#if !USE_NSGETENVIRON
Envp = const_cast<const char **>(environ);
#else
// environ is missing in dylibs.
Envp = const_cast<const char **>(*_NSGetEnviron());
#endif
// Explicitly initialized to prevent what appears to be a valgrind false
// positive.
pid_t PID = 0;
int Err = posix_spawn(&PID, Program.str().c_str(), FileActions,
/*attrp*/nullptr, const_cast<char **>(Args),
const_cast<char **>(Envp));
if (FileActions)
posix_spawn_file_actions_destroy(FileActions);
if (Err)
return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err);
PI.Pid = PID;
return true;
}
#endif
// Create a child process.
int child = fork();
switch (child) {
// An error occurred: Return to the caller.
case -1:
MakeErrMsg(ErrMsg, "Couldn't fork");
return false;
// Child process: Execute the program.
case 0: {
// Redirect file descriptors...
if (!Redirects.empty()) {
// Redirect stdin
if (RedirectIO(Redirects[0], 0, ErrMsg)) { return false; }
// Redirect stdout
if (RedirectIO(Redirects[1], 1, ErrMsg)) { return false; }
if (Redirects[1] && Redirects[2] && *Redirects[1] == *Redirects[2]) {
// If stdout and stderr should go to the same place, redirect stderr
// to the FD already open for stdout.
if (-1 == dup2(1,2)) {
MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout");
return false;
}
} else {
// Just redirect stderr
if (RedirectIO(Redirects[2], 2, ErrMsg)) { return false; }
}
}
// Set memory limits
if (MemoryLimit!=0) {
SetMemoryLimits(MemoryLimit);
}
// Execute!
std::string PathStr = Program;
if (Envp != nullptr)
execve(PathStr.c_str(),
const_cast<char **>(Args),
const_cast<char **>(Envp));
else
execv(PathStr.c_str(),
const_cast<char **>(Args));
// If the execve() failed, we should exit. Follow Unix protocol and
// return 127 if the executable was not found, and 126 otherwise.
// Use _exit rather than exit so that atexit functions and static
// object destructors cloned from the parent process aren't
// redundantly run, and so that any data buffered in stdio buffers
// cloned from the parent aren't redundantly written out.
_exit(errno == ENOENT ? 127 : 126);
}
// Parent process: Break out of the switch to do our processing.
default:
break;
}
PI.Pid = child;
return true;
}
namespace llvm {
ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait,
bool WaitUntilTerminates, std::string *ErrMsg) {
struct sigaction Act, Old;
assert(PI.Pid && "invalid pid to wait on, process not started?");
int WaitPidOptions = 0;
pid_t ChildPid = PI.Pid;
if (WaitUntilTerminates) {
SecondsToWait = 0;
} else if (SecondsToWait) {
// Install a timeout handler. The handler itself does nothing, but the
// simple fact of having a handler at all causes the wait below to return
// with EINTR, unlike if we used SIG_IGN.
memset(&Act, 0, sizeof(Act));
Act.sa_handler = TimeOutHandler;
sigemptyset(&Act.sa_mask);
sigaction(SIGALRM, &Act, &Old);
alarm(SecondsToWait);
} else if (SecondsToWait == 0)
WaitPidOptions = WNOHANG;
// Parent process: Wait for the child process to terminate.
int status;
ProcessInfo WaitResult;
do {
WaitResult.Pid = waitpid(ChildPid, &status, WaitPidOptions);
} while (WaitUntilTerminates && WaitResult.Pid == -1 && errno == EINTR);
if (WaitResult.Pid != PI.Pid) {
if (WaitResult.Pid == 0) {
// Non-blocking wait.
return WaitResult;
} else {
if (SecondsToWait && errno == EINTR) {
// Kill the child.
kill(PI.Pid, SIGKILL);
// Turn off the alarm and restore the signal handler
alarm(0);
sigaction(SIGALRM, &Old, nullptr);
// Wait for child to die
if (wait(&status) != ChildPid)
MakeErrMsg(ErrMsg, "Child timed out but wouldn't die");
else
MakeErrMsg(ErrMsg, "Child timed out", 0);
WaitResult.ReturnCode = -2; // Timeout detected
return WaitResult;
} else if (errno != EINTR) {
MakeErrMsg(ErrMsg, "Error waiting for child process");
WaitResult.ReturnCode = -1;
return WaitResult;
}
}
}
// We exited normally without timeout, so turn off the timer.
if (SecondsToWait && !WaitUntilTerminates) {
alarm(0);
sigaction(SIGALRM, &Old, nullptr);
}
// Return the proper exit status. Detect error conditions
// so we can return -1 for them and set ErrMsg informatively.
int result = 0;
if (WIFEXITED(status)) {
result = WEXITSTATUS(status);
WaitResult.ReturnCode = result;
if (result == 127) {
if (ErrMsg)
*ErrMsg = llvm::sys::StrError(ENOENT);
WaitResult.ReturnCode = -1;
return WaitResult;
}
if (result == 126) {
if (ErrMsg)
*ErrMsg = "Program could not be executed";
WaitResult.ReturnCode = -1;
return WaitResult;
}
} else if (WIFSIGNALED(status)) {
if (ErrMsg) {
*ErrMsg = strsignal(WTERMSIG(status));
#ifdef WCOREDUMP
if (WCOREDUMP(status))
*ErrMsg += " (core dumped)";
#endif
}
// Return a special value to indicate that the process received an unhandled
// signal during execution as opposed to failing to execute.
WaitResult.ReturnCode = -2;
}
return WaitResult;
}
std::error_code sys::ChangeStdinToBinary(){
// Do nothing, as Unix doesn't differentiate between text and binary.
return std::error_code();
}
std::error_code sys::ChangeStdoutToBinary(){
// Do nothing, as Unix doesn't differentiate between text and binary.
return std::error_code();
}
std::error_code
llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents,
WindowsEncodingMethod Encoding /*unused*/) {
std::error_code EC;
llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text);
if (EC)
return EC;
OS << Contents;
if (OS.has_error())
return make_error_code(errc::io_error);
return EC;
}
bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program,
ArrayRef<const char *> Args) {
static long ArgMax = sysconf(_SC_ARG_MAX);
// System says no practical limit.
if (ArgMax == -1)
return true;
// Conservatively account for space required by environment variables.
long HalfArgMax = ArgMax / 2;
size_t ArgLength = Program.size() + 1;
for (const char* Arg : Args) {
size_t length = strlen(Arg);
// Ensure that we do not exceed the MAX_ARG_STRLEN constant on Linux, which
// does not have a constant unlike what the man pages would have you
// believe. Since this limit is pretty high, perform the check
// unconditionally rather than trying to be aggressive and limiting it to
// Linux only.
if (length >= (32 * 4096))
return false;
ArgLength += length + 1;
if (ArgLength > size_t(HalfArgMax)) {
return false;
}
}
return true;
}
}

View File

@ -1,16 +0,0 @@
llvm/lib/Support/Unix README
===========================
This directory provides implementations of the lib/System classes that
are common to two or more variants of UNIX. For example, the directory
structure underneath this directory could look like this:
Unix - only code that is truly generic to all UNIX platforms
Posix - code that is specific to Posix variants of UNIX
SUS - code that is specific to the Single Unix Specification
SysV - code that is specific to System V variants of UNIX
As a rule, only those directories actually needing to be created should be
created. Also, further subdirectories could be created to reflect versions of
the various standards. For example, under SUS there could be v1, v2, and v3
subdirectories to reflect the three major versions of SUS.

View File

@ -1,51 +0,0 @@
//= llvm/Support/Unix/RWMutex.inc - Unix Reader/Writer Mutual Exclusion Lock =//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Unix specific (non-pthread) RWMutex class.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only generic UNIX code that
//=== is guaranteed to work on *all* UNIX variants.
//===----------------------------------------------------------------------===//
#include "llvm/Support/Mutex.h"
namespace llvm {
using namespace sys;
// This naive implementation treats readers the same as writers. This
// will therefore deadlock if a thread tries to acquire a read lock
// multiple times.
RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { }
RWMutexImpl::~RWMutexImpl() {
delete static_cast<MutexImpl *>(data_);
}
bool RWMutexImpl::reader_acquire() {
return static_cast<MutexImpl *>(data_)->acquire();
}
bool RWMutexImpl::reader_release() {
return static_cast<MutexImpl *>(data_)->release();
}
bool RWMutexImpl::writer_acquire() {
return static_cast<MutexImpl *>(data_)->acquire();
}
bool RWMutexImpl::writer_release() {
return static_cast<MutexImpl *>(data_)->release();
}
}

View File

@ -1,489 +0,0 @@
//===- Signals.cpp - Generic Unix Signals 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 defines some helpful functions for dealing with the possibility of
// Unix signals occurring while your program is running.
//
//===----------------------------------------------------------------------===//
#include "Unix.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/UniqueLock.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <string>
#ifdef HAVE_BACKTRACE
# include BACKTRACE_HEADER // For backtrace().
#endif
#if HAVE_SIGNAL_H
#include <signal.h>
#endif
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_DLFCN_H
#include <dlfcn.h>
#endif
#if HAVE_MACH_MACH_H
#include <mach/mach.h>
#endif
#if HAVE_LINK_H
#include <link.h>
#endif
#ifdef HAVE__UNWIND_BACKTRACE
// FIXME: We should be able to use <unwind.h> for any target that has an
// _Unwind_Backtrace function, but on FreeBSD the configure test passes
// despite the function not existing, and on Android, <unwind.h> conflicts
// with <link.h>.
#ifdef __GLIBC__
#include <unwind.h>
#else
#undef HAVE__UNWIND_BACKTRACE
#endif
#endif
using namespace llvm;
static RETSIGTYPE SignalHandler(int Sig); // defined below.
static ManagedStatic<sys::SmartMutex<true> > SignalsMutex;
/// InterruptFunction - The function to call if ctrl-c is pressed.
static void (*InterruptFunction)() = nullptr;
static ManagedStatic<std::vector<std::string>> FilesToRemove;
static StringRef Argv0;
// IntSigs - Signals that represent requested termination. There's no bug
// or failure, or if there is, it's not our direct responsibility. For whatever
// reason, our continued execution is no longer desirable.
static const int IntSigs[] = {
SIGHUP, SIGINT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2
};
// KillSigs - Signals that represent that we have a bug, and our prompt
// termination has been ordered.
static const int KillSigs[] = {
SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV, SIGQUIT
#ifdef SIGSYS
, SIGSYS
#endif
#ifdef SIGXCPU
, SIGXCPU
#endif
#ifdef SIGXFSZ
, SIGXFSZ
#endif
#ifdef SIGEMT
, SIGEMT
#endif
};
static unsigned NumRegisteredSignals = 0;
static struct {
struct sigaction SA;
int SigNo;
} RegisteredSignalInfo[array_lengthof(IntSigs) + array_lengthof(KillSigs)];
static void RegisterHandler(int Signal) {
assert(NumRegisteredSignals < array_lengthof(RegisteredSignalInfo) &&
"Out of space for signal handlers!");
struct sigaction NewHandler;
NewHandler.sa_handler = SignalHandler;
NewHandler.sa_flags = SA_NODEFER | SA_RESETHAND | SA_ONSTACK;
sigemptyset(&NewHandler.sa_mask);
// Install the new handler, save the old one in RegisteredSignalInfo.
sigaction(Signal, &NewHandler,
&RegisteredSignalInfo[NumRegisteredSignals].SA);
RegisteredSignalInfo[NumRegisteredSignals].SigNo = Signal;
++NumRegisteredSignals;
}
#if defined(HAVE_SIGALTSTACK)
// Hold onto both the old and new alternate signal stack so that it's not
// reported as a leak. We don't make any attempt to remove our alt signal
// stack if we remove our signal handlers; that can't be done reliably if
// someone else is also trying to do the same thing.
static stack_t OldAltStack;
static void* NewAltStackPointer;
static void CreateSigAltStack() {
const size_t AltStackSize = MINSIGSTKSZ + 64 * 1024;
// If we're executing on the alternate stack, or we already have an alternate
// signal stack that we're happy with, there's nothing for us to do. Don't
// reduce the size, some other part of the process might need a larger stack
// than we do.
if (sigaltstack(nullptr, &OldAltStack) != 0 ||
OldAltStack.ss_flags & SS_ONSTACK ||
(OldAltStack.ss_sp && OldAltStack.ss_size >= AltStackSize))
return;
stack_t AltStack = {};
AltStack.ss_sp = reinterpret_cast<char *>(malloc(AltStackSize));
NewAltStackPointer = AltStack.ss_sp; // Save to avoid reporting a leak.
AltStack.ss_size = AltStackSize;
if (sigaltstack(&AltStack, &OldAltStack) != 0)
free(AltStack.ss_sp);
}
#else
static void CreateSigAltStack() {}
#endif
static void RegisterHandlers() {
sys::SmartScopedLock<true> Guard(*SignalsMutex);
// If the handlers are already registered, we're done.
if (NumRegisteredSignals != 0) return;
// Create an alternate stack for signal handling. This is necessary for us to
// be able to reliably handle signals due to stack overflow.
CreateSigAltStack();
for (auto S : IntSigs) RegisterHandler(S);
for (auto S : KillSigs) RegisterHandler(S);
}
static void UnregisterHandlers() {
// Restore all of the signal handlers to how they were before we showed up.
for (unsigned i = 0, e = NumRegisteredSignals; i != e; ++i)
sigaction(RegisteredSignalInfo[i].SigNo,
&RegisteredSignalInfo[i].SA, nullptr);
NumRegisteredSignals = 0;
}
/// RemoveFilesToRemove - Process the FilesToRemove list. This function
/// should be called with the SignalsMutex lock held.
/// NB: This must be an async signal safe function. It cannot allocate or free
/// memory, even in debug builds.
static void RemoveFilesToRemove() {
// Avoid constructing ManagedStatic in the signal handler.
// If FilesToRemove is not constructed, there are no files to remove.
if (!FilesToRemove.isConstructed())
return;
// We avoid iterators in case of debug iterators that allocate or release
// memory.
std::vector<std::string>& FilesToRemoveRef = *FilesToRemove;
for (unsigned i = 0, e = FilesToRemoveRef.size(); i != e; ++i) {
const char *path = FilesToRemoveRef[i].c_str();
// Get the status so we can determine if it's a file or directory. If we
// can't stat the file, ignore it.
struct stat buf;
if (stat(path, &buf) != 0)
continue;
// If this is not a regular file, ignore it. We want to prevent removal of
// special files like /dev/null, even if the compiler is being run with the
// super-user permissions.
if (!S_ISREG(buf.st_mode))
continue;
// Otherwise, remove the file. We ignore any errors here as there is nothing
// else we can do.
unlink(path);
}
}
// SignalHandler - The signal handler that runs.
static RETSIGTYPE SignalHandler(int Sig) {
// Restore the signal behavior to default, so that the program actually
// crashes when we return and the signal reissues. This also ensures that if
// we crash in our signal handler that the program will terminate immediately
// instead of recursing in the signal handler.
UnregisterHandlers();
// Unmask all potentially blocked kill signals.
sigset_t SigMask;
sigfillset(&SigMask);
sigprocmask(SIG_UNBLOCK, &SigMask, nullptr);
{
unique_lock<sys::SmartMutex<true>> Guard(*SignalsMutex);
RemoveFilesToRemove();
if (std::find(std::begin(IntSigs), std::end(IntSigs), Sig)
!= std::end(IntSigs)) {
if (InterruptFunction) {
void (*IF)() = InterruptFunction;
Guard.unlock();
InterruptFunction = nullptr;
IF(); // run the interrupt function.
return;
}
Guard.unlock();
raise(Sig); // Execute the default handler.
return;
}
}
// Otherwise if it is a fault (like SEGV) run any handler.
llvm::sys::RunSignalHandlers();
#ifdef __s390__
// On S/390, certain signals are delivered with PSW Address pointing to
// *after* the faulting instruction. Simply returning from the signal
// handler would continue execution after that point, instead of
// re-raising the signal. Raise the signal manually in those cases.
if (Sig == SIGILL || Sig == SIGFPE || Sig == SIGTRAP)
raise(Sig);
#endif
}
void llvm::sys::RunInterruptHandlers() {
sys::SmartScopedLock<true> Guard(*SignalsMutex);
RemoveFilesToRemove();
}
void llvm::sys::SetInterruptFunction(void (*IF)()) {
{
sys::SmartScopedLock<true> Guard(*SignalsMutex);
InterruptFunction = IF;
}
RegisterHandlers();
}
// RemoveFileOnSignal - The public API
bool llvm::sys::RemoveFileOnSignal(StringRef Filename,
std::string* ErrMsg) {
{
sys::SmartScopedLock<true> Guard(*SignalsMutex);
FilesToRemove->push_back(Filename);
}
RegisterHandlers();
return false;
}
// DontRemoveFileOnSignal - The public API
void llvm::sys::DontRemoveFileOnSignal(StringRef Filename) {
sys::SmartScopedLock<true> Guard(*SignalsMutex);
std::vector<std::string>::reverse_iterator RI =
find(reverse(*FilesToRemove), Filename);
std::vector<std::string>::iterator I = FilesToRemove->end();
if (RI != FilesToRemove->rend())
I = FilesToRemove->erase(RI.base()-1);
}
/// AddSignalHandler - Add a function to be called when a signal is delivered
/// to the process. The handler can have a cookie passed to it to identify
/// what instance of the handler it is.
void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) {
CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie));
RegisterHandlers();
}
#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES && HAVE_LINK_H && \
(defined(__linux__) || defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || defined(__NetBSD__))
struct DlIteratePhdrData {
void **StackTrace;
int depth;
bool first;
const char **modules;
intptr_t *offsets;
const char *main_exec_name;
};
static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
DlIteratePhdrData *data = (DlIteratePhdrData*)arg;
const char *name = data->first ? data->main_exec_name : info->dlpi_name;
data->first = false;
for (int i = 0; i < info->dlpi_phnum; i++) {
const auto *phdr = &info->dlpi_phdr[i];
if (phdr->p_type != PT_LOAD)
continue;
intptr_t beg = info->dlpi_addr + phdr->p_vaddr;
intptr_t end = beg + phdr->p_memsz;
for (int j = 0; j < data->depth; j++) {
if (data->modules[j])
continue;
intptr_t addr = (intptr_t)data->StackTrace[j];
if (beg <= addr && addr < end) {
data->modules[j] = name;
data->offsets[j] = addr - info->dlpi_addr;
}
}
}
return 0;
}
/// If this is an ELF platform, we can find all loaded modules and their virtual
/// addresses with dl_iterate_phdr.
static bool findModulesAndOffsets(void **StackTrace, int Depth,
const char **Modules, intptr_t *Offsets,
const char *MainExecutableName,
StringSaver &StrPool) {
DlIteratePhdrData data = {StackTrace, Depth, true,
Modules, Offsets, MainExecutableName};
dl_iterate_phdr(dl_iterate_phdr_cb, &data);
return true;
}
#else
/// This platform does not have dl_iterate_phdr, so we do not yet know how to
/// find all loaded DSOs.
static bool findModulesAndOffsets(void **StackTrace, int Depth,
const char **Modules, intptr_t *Offsets,
const char *MainExecutableName,
StringSaver &StrPool) {
return false;
}
#endif // defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES && ...
#if ENABLE_BACKTRACES && defined(HAVE__UNWIND_BACKTRACE)
static int unwindBacktrace(void **StackTrace, int MaxEntries) {
if (MaxEntries < 0)
return 0;
// Skip the first frame ('unwindBacktrace' itself).
int Entries = -1;
auto HandleFrame = [&](_Unwind_Context *Context) -> _Unwind_Reason_Code {
// Apparently we need to detect reaching the end of the stack ourselves.
void *IP = (void *)_Unwind_GetIP(Context);
if (!IP)
return _URC_END_OF_STACK;
assert(Entries < MaxEntries && "recursively called after END_OF_STACK?");
if (Entries >= 0)
StackTrace[Entries] = IP;
if (++Entries == MaxEntries)
return _URC_END_OF_STACK;
return _URC_NO_REASON;
};
_Unwind_Backtrace(
[](_Unwind_Context *Context, void *Handler) {
return (*static_cast<decltype(HandleFrame) *>(Handler))(Context);
},
static_cast<void *>(&HandleFrame));
return std::max(Entries, 0);
}
#endif
// PrintStackTrace - In the case of a program crash or fault, print out a stack
// trace so that the user has an indication of why and where we died.
//
// On glibc systems we have the 'backtrace' function, which works nicely, but
// doesn't demangle symbols.
void llvm::sys::PrintStackTrace(raw_ostream &OS) {
#if ENABLE_BACKTRACES
static void *StackTrace[256];
int depth = 0;
#if defined(HAVE_BACKTRACE)
// Use backtrace() to output a backtrace on Linux systems with glibc.
if (!depth)
depth = backtrace(StackTrace, static_cast<int>(array_lengthof(StackTrace)));
#endif
#if defined(HAVE__UNWIND_BACKTRACE)
// Try _Unwind_Backtrace() if backtrace() failed.
if (!depth)
depth = unwindBacktrace(StackTrace,
static_cast<int>(array_lengthof(StackTrace)));
#endif
if (!depth)
return;
if (printSymbolizedStackTrace(Argv0, StackTrace, depth, OS))
return;
#if HAVE_DLFCN_H && HAVE_DLADDR
int width = 0;
for (int i = 0; i < depth; ++i) {
Dl_info dlinfo;
dladdr(StackTrace[i], &dlinfo);
const char* name = strrchr(dlinfo.dli_fname, '/');
int nwidth;
if (!name) nwidth = strlen(dlinfo.dli_fname);
else nwidth = strlen(name) - 1;
if (nwidth > width) width = nwidth;
}
for (int i = 0; i < depth; ++i) {
Dl_info dlinfo;
dladdr(StackTrace[i], &dlinfo);
OS << format("%-2d", i);
const char* name = strrchr(dlinfo.dli_fname, '/');
if (!name) OS << format(" %-*s", width, dlinfo.dli_fname);
else OS << format(" %-*s", width, name+1);
OS << format(" %#0*lx", (int)(sizeof(void*) * 2) + 2,
(unsigned long)StackTrace[i]);
if (dlinfo.dli_sname != nullptr) {
OS << ' ';
int res;
char* d = itaniumDemangle(dlinfo.dli_sname, nullptr, nullptr, &res);
if (!d) OS << dlinfo.dli_sname;
else OS << d;
free(d);
// FIXME: When we move to C++11, use %t length modifier. It's not in
// C++03 and causes gcc to issue warnings. Losing the upper 32 bits of
// the stack offset for a stack dump isn't likely to cause any problems.
OS << format(" + %u",(unsigned)((char*)StackTrace[i]-
(char*)dlinfo.dli_saddr));
}
OS << '\n';
}
#elif defined(HAVE_BACKTRACE)
backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO);
#endif
#endif
}
static void PrintStackTraceSignalHandler(void *) {
sys::PrintStackTrace(llvm::errs());
}
void llvm::sys::DisableSystemDialogsOnCrash() {}
/// PrintStackTraceOnErrorSignal - When an error signal (such as SIGABRT or
/// SIGSEGV) is delivered to the process, print a stack trace and then exit.
void llvm::sys::PrintStackTraceOnErrorSignal(StringRef Argv0,
bool DisableCrashReporting) {
::Argv0 = Argv0;
AddSignalHandler(PrintStackTraceSignalHandler, nullptr);
#if defined(__APPLE__) && ENABLE_CRASH_OVERRIDES
// Environment variable to disable any kind of crash dialog.
if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT")) {
mach_port_t self = mach_task_self();
exception_mask_t mask = EXC_MASK_CRASH;
kern_return_t ret = task_set_exception_ports(self,
mask,
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES,
THREAD_STATE_NONE);
(void)ret;
}
#endif
}

View File

@ -1,69 +0,0 @@
//=== llvm/Support/Unix/ThreadLocal.inc - Unix Thread Local Data -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Unix specific (non-pthread) ThreadLocal class.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only generic UNIX code that
//=== is guaranteed to work on *all* UNIX variants.
//===----------------------------------------------------------------------===//
#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_GETSPECIFIC)
#include <cassert>
#include <pthread.h>
#include <stdlib.h>
namespace llvm {
using namespace sys;
ThreadLocalImpl::ThreadLocalImpl() : data() {
static_assert(sizeof(pthread_key_t) <= sizeof(data), "size too big");
pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
int errorcode = pthread_key_create(key, nullptr);
assert(errorcode == 0);
(void) errorcode;
}
ThreadLocalImpl::~ThreadLocalImpl() {
pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
int errorcode = pthread_key_delete(*key);
assert(errorcode == 0);
(void) errorcode;
}
void ThreadLocalImpl::setInstance(const void* d) {
pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
int errorcode = pthread_setspecific(*key, d);
assert(errorcode == 0);
(void) errorcode;
}
void *ThreadLocalImpl::getInstance() {
pthread_key_t* key = reinterpret_cast<pthread_key_t*>(&data);
return pthread_getspecific(*key);
}
void ThreadLocalImpl::removeInstance() {
setInstance(nullptr);
}
}
#else
namespace llvm {
using namespace sys;
ThreadLocalImpl::ThreadLocalImpl() : data() { }
ThreadLocalImpl::~ThreadLocalImpl() { }
void ThreadLocalImpl::setInstance(const void* d) { data = const_cast<void*>(d);}
void *ThreadLocalImpl::getInstance() { return data; }
void ThreadLocalImpl::removeInstance() { setInstance(0); }
}
#endif

View File

@ -1,215 +0,0 @@
//===- 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
}

View File

@ -1,106 +0,0 @@
//===- llvm/Support/Unix/Unix.h - Common Unix Include File -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines things specific to Unix implementations.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_SUPPORT_UNIX_UNIX_H
#define LLVM_LIB_SUPPORT_UNIX_UNIX_H
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only generic UNIX code that
//=== is guaranteed to work on all UNIX variants.
//===----------------------------------------------------------------------===//
#include "llvm/Config/config.h" // Get autoconf configuration settings
#include "llvm/Support/Chrono.h"
#include "llvm/Support/Errno.h"
#include <algorithm>
#include <assert.h>
#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <time.h>
#ifdef HAVE_DLFCN_H
# include <dlfcn.h>
#endif
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
/// This function builds an error message into \p ErrMsg using the \p prefix
/// string and the Unix error number given by \p errnum. If errnum is -1, the
/// default then the value of errno is used.
/// @brief Make an error message
///
/// If the error number can be converted to a string, it will be
/// separated from prefix by ": ".
static inline bool MakeErrMsg(
std::string* ErrMsg, const std::string& prefix, int errnum = -1) {
if (!ErrMsg)
return true;
if (errnum == -1)
errnum = errno;
*ErrMsg = prefix + ": " + llvm::sys::StrError(errnum);
return true;
}
namespace llvm {
namespace sys {
/// Convert a struct timeval to a duration. Note that timeval can be used both
/// as a time point and a duration. Be sure to check what the input represents.
inline std::chrono::microseconds toDuration(const struct timeval &TV) {
return std::chrono::seconds(TV.tv_sec) +
std::chrono::microseconds(TV.tv_usec);
}
/// Convert a time point to struct timespec.
inline struct timespec toTimeSpec(TimePoint<> TP) {
using namespace std::chrono;
struct timespec RetVal;
RetVal.tv_sec = toTimeT(TP);
RetVal.tv_nsec = (TP.time_since_epoch() % seconds(1)).count();
return RetVal;
}
/// Convert a time point to struct timeval.
inline struct timeval toTimeVal(TimePoint<std::chrono::microseconds> TP) {
using namespace std::chrono;
struct timeval RetVal;
RetVal.tv_sec = toTimeT(TP);
RetVal.tv_usec = (TP.time_since_epoch() % seconds(1)).count();
return RetVal;
}
} // namespace sys
} // namespace llvm
#endif

View File

@ -1,32 +0,0 @@
//===--- Unix/Watchdog.inc - Unix Watchdog 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 generic Unix implementation of the Watchdog class.
//
//===----------------------------------------------------------------------===//
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
namespace llvm {
namespace sys {
Watchdog::Watchdog(unsigned int seconds) {
#ifdef HAVE_UNISTD_H
alarm(seconds);
#endif
}
Watchdog::~Watchdog() {
#ifdef HAVE_UNISTD_H
alarm(0);
#endif
}
}
}