diff options
Diffstat (limited to 'llvm/lib/Support/Unix')
-rw-r--r-- | llvm/lib/Support/Unix/COM.inc | 4 | ||||
-rw-r--r-- | llvm/lib/Support/Unix/DynamicLibrary.inc | 28 | ||||
-rw-r--r-- | llvm/lib/Support/Unix/Host.inc | 84 | ||||
-rw-r--r-- | llvm/lib/Support/Unix/Memory.inc | 76 | ||||
-rw-r--r-- | llvm/lib/Support/Unix/Path.inc | 118 | ||||
-rw-r--r-- | llvm/lib/Support/Unix/Process.inc | 79 | ||||
-rw-r--r-- | llvm/lib/Support/Unix/Program.inc | 180 | ||||
-rw-r--r-- | llvm/lib/Support/Unix/Signals.inc | 113 | ||||
-rw-r--r-- | llvm/lib/Support/Unix/ThreadLocal.inc | 58 | ||||
-rw-r--r-- | llvm/lib/Support/Unix/Threading.inc | 170 | ||||
-rw-r--r-- | llvm/lib/Support/Unix/Watchdog.inc | 16 |
11 files changed, 459 insertions, 467 deletions
diff --git a/llvm/lib/Support/Unix/COM.inc b/llvm/lib/Support/Unix/COM.inc index d97b59ac02cf..846d4b68a7eb 100644 --- a/llvm/lib/Support/Unix/COM.inc +++ b/llvm/lib/Support/Unix/COM.inc @@ -22,5 +22,5 @@ InitializeCOMRAII::InitializeCOMRAII(COMThreadingMode Threading, bool SpeedOverMemory) {} InitializeCOMRAII::~InitializeCOMRAII() = default; -} -} +} // namespace sys +} // namespace llvm diff --git a/llvm/lib/Support/Unix/DynamicLibrary.inc b/llvm/lib/Support/Unix/DynamicLibrary.inc index a2a379963de0..7b77da5e0c6b 100644 --- a/llvm/lib/Support/Unix/DynamicLibrary.inc +++ b/llvm/lib/Support/Unix/DynamicLibrary.inc @@ -25,9 +25,10 @@ DynamicLibrary::HandleSet::~HandleSet() { } void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) { - void *Handle = ::dlopen(File, RTLD_LAZY|RTLD_GLOBAL); + void *Handle = ::dlopen(File, RTLD_LAZY | RTLD_GLOBAL); if (!Handle) { - if (Err) *Err = ::dlerror(); + if (Err) + *Err = ::dlerror(); return &DynamicLibrary::Invalid; } @@ -41,9 +42,7 @@ void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) { return Handle; } -void DynamicLibrary::HandleSet::DLClose(void *Handle) { - ::dlclose(Handle); -} +void DynamicLibrary::HandleSet::DLClose(void *Handle) { ::dlclose(Handle); } void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) { return ::dlsym(Handle, Symbol); @@ -54,12 +53,12 @@ void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) { DynamicLibrary::HandleSet::~HandleSet() {} void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) { - if (Err) *Err = "dlopen() not supported on this platform"; + if (Err) + *Err = "dlopen() not supported on this platform"; return &Invalid; } -void DynamicLibrary::HandleSet::DLClose(void *Handle) { -} +void DynamicLibrary::HandleSet::DLClose(void *Handle) {} void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) { return nullptr; @@ -68,9 +67,11 @@ void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) { #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 +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 @@ -101,8 +102,9 @@ static void *DoSearch(const char* SymbolName) { #undef EXPLICIT_SYMBOL // This macro returns the address of a well-known, explicit symbol -#define EXPLICIT_SYMBOL(SYM) \ - if (!strcmp(SymbolName, #SYM)) return &SYM +#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 diff --git a/llvm/lib/Support/Unix/Host.inc b/llvm/lib/Support/Unix/Host.inc deleted file mode 100644 index dfcfdd0dee68..000000000000 --- a/llvm/lib/Support/Unix/Host.inc +++ /dev/null @@ -1,84 +0,0 @@ -//===- llvm/Support/Unix/Host.inc -------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// 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(); - } - // On AIX, the AIX version and release should be that of the current host - // unless if the version has already been specified. - if (Triple(LLVM_HOST_TRIPLE).getOS() == Triple::AIX) { - Triple TT(TargetTripleString); - if (TT.getOS() == Triple::AIX && !TT.getOSMajorVersion()) { - struct utsname name; - if (uname(&name) != -1) { - std::string NewOSName = std::string(Triple::getOSTypeName(Triple::AIX)); - NewOSName += name.version; - NewOSName += '.'; - NewOSName += name.release; - NewOSName += ".0.0"; - TT.setOSName(NewOSName); - return TT.str(); - } - } - } - 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 TargetTripleString; -} diff --git a/llvm/lib/Support/Unix/Memory.inc b/llvm/lib/Support/Unix/Memory.inc index 5e008069dd98..4c8f6b2ea7d3 100644 --- a/llvm/lib/Support/Unix/Memory.inc +++ b/llvm/lib/Support/Unix/Memory.inc @@ -33,7 +33,7 @@ #if defined(__APPLE__) extern "C" void sys_icache_invalidate(const void *Addr, size_t len); #else -extern "C" void __clear_cache(void *, void*); +extern "C" void __clear_cache(void *, void *); #endif static int getPosixProtectionFlags(unsigned Flags) { @@ -42,16 +42,15 @@ static int getPosixProtectionFlags(unsigned Flags) { return PROT_READ; case llvm::sys::Memory::MF_WRITE: return PROT_WRITE; - case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_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: + 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__) || defined(__POWERPC__) || defined (__ppc__) || \ - defined(_POWER) || defined(_ARCH_PPC)) +#if defined(__FreeBSD__) || defined(__powerpc__) // 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 @@ -71,11 +70,9 @@ static int getPosixProtectionFlags(unsigned Flags) { namespace llvm { namespace sys { -MemoryBlock -Memory::allocateMappedMemory(size_t NumBytes, - const MemoryBlock *const NearBlock, - unsigned PFlags, - std::error_code &EC) { +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(); @@ -106,18 +103,19 @@ Memory::allocateMappedMemory(size_t NumBytes, // 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->allocatedSize() : 0; + NearBlock->allocatedSize() + : 0; static const size_t PageSize = Process::getPageSizeEstimate(); - const size_t NumPages = (NumBytes+PageSize-1)/PageSize; + const size_t NumPages = (NumBytes + PageSize - 1) / PageSize; if (Start && Start % PageSize) Start += PageSize - Start % PageSize; // FIXME: Handle huge page requests (MF_HUGE_HINT). - void *Addr = ::mmap(reinterpret_cast<void *>(Start), PageSize*NumPages, Protect, - MMFlags, fd, 0); + 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 + if (NearBlock) { // Try again without a near hint #if !defined(MAP_ANON) close(fd); #endif @@ -137,12 +135,12 @@ Memory::allocateMappedMemory(size_t NumBytes, MemoryBlock Result; Result.Address = Addr; - Result.AllocatedSize = PageSize*NumPages; + Result.AllocatedSize = PageSize * NumPages; Result.Flags = PFlags; // Rely on protectMappedMemory to invalidate instruction cache. if (PFlags & MF_EXEC) { - EC = Memory::protectMappedMemory (Result, PFlags); + EC = Memory::protectMappedMemory(Result, PFlags); if (EC != std::error_code()) return MemoryBlock(); } @@ -150,8 +148,7 @@ Memory::allocateMappedMemory(size_t NumBytes, return Result; } -std::error_code -Memory::releaseMappedMemory(MemoryBlock &M) { +std::error_code Memory::releaseMappedMemory(MemoryBlock &M) { if (M.Address == nullptr || M.AllocatedSize == 0) return std::error_code(); @@ -164,8 +161,8 @@ Memory::releaseMappedMemory(MemoryBlock &M) { return std::error_code(); } -std::error_code -Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) { +std::error_code Memory::protectMappedMemory(const MemoryBlock &M, + unsigned Flags) { static const Align PageSize = Align(Process::getPageSizeEstimate()); if (M.Address == nullptr || M.AllocatedSize == 0) return std::error_code(); @@ -174,15 +171,18 @@ Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) { return std::error_code(EINVAL, std::generic_category()); int Protect = getPosixProtectionFlags(Flags); - uintptr_t Start = alignAddr((const uint8_t *)M.Address - PageSize.value() + 1, PageSize); - uintptr_t End = alignAddr((const uint8_t *)M.Address + M.AllocatedSize, PageSize); + uintptr_t Start = + alignAddr((const uint8_t *)M.Address - PageSize.value() + 1, PageSize); + uintptr_t End = + alignAddr((const uint8_t *)M.Address + M.AllocatedSize, 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. + // 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) @@ -207,17 +207,14 @@ Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) { /// 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) { +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__)) +#if (defined(__powerpc__) || defined(__arm__) || defined(__arm64__)) sys_icache_invalidate(const_cast<void *>(Addr), Len); -# endif +#endif #elif defined(__Fuchsia__) @@ -226,13 +223,12 @@ void Memory::InvalidateInstructionCache(const void *Addr, #else -# if (defined(__POWERPC__) || defined (__ppc__) || \ - defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__) +#if defined(__powerpc__) && 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; + 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)); @@ -241,15 +237,15 @@ void Memory::InvalidateInstructionCache(const void *Addr, 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__) +#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 -#endif // end apple +#endif // end apple ValgrindDiscardTranslations(Addr, Len); } diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc index 2ae7c6dc47e0..3efcad4f2bed 100644 --- a/llvm/lib/Support/Unix/Path.inc +++ b/llvm/lib/Support/Unix/Path.inc @@ -36,9 +36,9 @@ #include <sys/file.h> #ifdef __APPLE__ +#include <copyfile.h> #include <mach-o/dyld.h> #include <sys/attr.h> -#include <copyfile.h> #if __has_include(<sys/clonefile.h>) #include <sys/clonefile.h> #endif @@ -111,7 +111,7 @@ typedef uint_t uint; #define STATVFS_F_FRSIZE(vfs) static_cast<uint64_t>(vfs.f_bsize) #endif -#if defined(__NetBSD__) || defined(__DragonFly__) || defined(__GNU__) || \ +#if defined(__NetBSD__) || defined(__DragonFly__) || defined(__GNU__) || \ defined(__MVS__) #define STATVFS_F_FLAG(vfs) (vfs).f_flag #else @@ -121,18 +121,16 @@ typedef uint_t uint; using namespace llvm; namespace llvm { -namespace sys { +namespace sys { namespace fs { const file_t kInvalidFile = -1; #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ defined(__minix) || defined(__FreeBSD_kernel__) || defined(__linux__) || \ - defined(__CYGWIN__) || defined(__DragonFly__) || defined(_AIX) || defined(__GNU__) || \ - (defined(__sun__) && defined(__svr4__)) -static int -test_dir(char ret[PATH_MAX], const char *dir, const char *bin) -{ + defined(__CYGWIN__) || defined(__DragonFly__) || defined(_AIX) || \ + defined(__GNU__) || (defined(__sun__) && defined(__svr4__)) +static int test_dir(char ret[PATH_MAX], const char *dir, const char *bin) { struct stat sb; char fullpath[PATH_MAX]; @@ -149,9 +147,7 @@ test_dir(char ret[PATH_MAX], const char *dir, const char *bin) return 0; } -static char * -getprogpath(char ret[PATH_MAX], const char *bin) -{ +static char *getprogpath(char ret[PATH_MAX], const char *bin) { if (bin == nullptr) return nullptr; @@ -319,7 +315,7 @@ std::string getMainExecutableImpl(const char *argv0, void *MainAddr) { char real_path[PATH_MAX]; if (realpath(exe_path, real_path)) return std::string(real_path); - break; // Found entry, but realpath failed. + break; // Found entry, but realpath failed. } #elif defined(HAVE_DLFCN_H) && defined(HAVE_DLADDR) // Use dladdr to get executable path if available. @@ -351,9 +347,7 @@ UniqueID file_status::getUniqueID() const { return UniqueID(fs_st_dev, fs_st_ino); } -uint32_t file_status::getLinkCount() const { - return fs_st_nlinks; -} +uint32_t file_status::getLinkCount() const { return fs_st_nlinks; } ErrorOr<space_info> disk_space(const Twine &Path) { struct STATVFS Vfs; @@ -513,7 +507,8 @@ static bool is_local_impl(struct STATVFS &Vfs) { // Haiku doesn't expose this information. return false; #elif defined(__sun) - // statvfs::f_basetype contains a null-terminated FSType name of the mounted target + // statvfs::f_basetype contains a null-terminated FSType name of the mounted + // target StringRef fstype(Vfs.f_basetype); // NFS is the only non-local fstype?? return !fstype.equals("nfs"); @@ -637,8 +632,7 @@ bool can_execute(const Twine &Path) { bool equivalent(file_status A, file_status B) { assert(status_known(A) && status_known(B)); - return A.fs_st_dev == B.fs_st_dev && - A.fs_st_ino == B.fs_st_ino; + return A.fs_st_dev == B.fs_st_dev && A.fs_st_ino == B.fs_st_ino; } std::error_code equivalent(const Twine &A, const Twine &B, bool &result) { @@ -676,11 +670,17 @@ static void expandTildeExpr(SmallVectorImpl<char> &Path) { // This is a string of the form ~username/, look up this user's entry in the // password database. - struct passwd *Entry = nullptr; + std::unique_ptr<char[]> Buf; + long BufSize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (BufSize <= 0) + BufSize = 16384; + Buf = std::make_unique<char[]>(BufSize); + struct passwd Pwd; std::string User = Expr.str(); - Entry = ::getpwnam(User.c_str()); + struct passwd *Entry = nullptr; + getpwnam_r(User.c_str(), &Pwd, Buf.get(), BufSize, &Entry); - if (!Entry) { + if (!Entry || !Entry->pw_dir) { // Unable to look up the entry, just return back the original path. return; } @@ -691,7 +691,6 @@ static void expandTildeExpr(SmallVectorImpl<char> &Path) { llvm::sys::path::append(Path, Storage); } - void expand_tilde(const Twine &path, SmallVectorImpl<char> &dest) { dest.clear(); if (path.isTriviallyEmpty()) @@ -743,9 +742,9 @@ static std::error_code fillStatus(int StatRet, const struct stat &Status, perms Perms = static_cast<perms>(Status.st_mode) & all_perms; Result = file_status(typeForMode(Status.st_mode), Perms, Status.st_dev, - Status.st_nlink, Status.st_ino, - Status.st_atime, atime_nsec, Status.st_mtime, mtime_nsec, - Status.st_uid, Status.st_gid, Status.st_size); + Status.st_nlink, Status.st_ino, Status.st_atime, + atime_nsec, Status.st_mtime, mtime_nsec, Status.st_uid, + Status.st_gid, Status.st_size); return std::error_code(); } @@ -769,7 +768,7 @@ unsigned getUmask() { // Chose arbitary new mask and reset the umask to the old mask. // umask(2) never fails so ignore the return of the second call. unsigned Mask = ::umask(0); - (void) ::umask(Mask); + (void)::umask(Mask); return Mask; } @@ -875,9 +874,9 @@ void mapped_file_region::unmapImpl() { void mapped_file_region::dontNeedImpl() { assert(Mode == mapped_file_region::readonly); if (!Mapping) - return; + return; #if defined(__MVS__) || defined(_AIX) - // If we don't have madvise, or it isn't beneficial, treat this as a no-op. + // If we don't have madvise, or it isn't beneficial, treat this as a no-op. #elif defined(POSIX_MADV_DONTNEED) ::posix_madvise(Mapping, Size, POSIX_MADV_DONTNEED); #else @@ -885,9 +884,7 @@ void mapped_file_region::dontNeedImpl() { #endif } -int mapped_file_region::alignment() { - return Process::getPageSizeEstimate(); -} +int mapped_file_region::alignment() { return Process::getPageSizeEstimate(); } std::error_code detail::directory_iterator_construct(detail::DirIterState &it, StringRef path, @@ -912,7 +909,7 @@ std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) { return std::error_code(); } -static file_type direntType(dirent* Entry) { +static file_type direntType(dirent *Entry) { // Most platforms provide the file type in the dirent: Linux/BSD/Mac. // The DTTOIF macro lets us reuse our status -> type conversion. // Note that while glibc provides a macro to see if this is supported, @@ -1134,7 +1131,7 @@ std::error_code openFileForRead(const Twine &Name, int &ResultFD, return EC; // Attempt to get the real name of the file, if the user asked - if(!RealPath) + if (!RealPath) return std::error_code(); RealPath->clear(); #if defined(F_GETPATH) @@ -1186,8 +1183,7 @@ Expected<size_t> readNativeFile(file_t FD, MutableArrayRef<char> Buf) { #else size_t Size = Buf.size(); #endif - ssize_t NumRead = - sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Size); + ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Size); if (ssize_t(NumRead) == -1) return errorCodeToError(std::error_code(errno, std::generic_category())); return NumRead; @@ -1206,8 +1202,7 @@ Expected<size_t> readNativeFileSlice(file_t FD, MutableArrayRef<char> Buf, #else if (lseek(FD, Offset, SEEK_SET) == -1) return errorCodeToError(std::error_code(errno, std::generic_category())); - ssize_t NumRead = - sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Size); + ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Size); #endif if (NumRead == -1) return errorCodeToError(std::error_code(errno, std::generic_category())); @@ -1273,19 +1268,20 @@ static std::error_code remove_directories_impl(const T &Entry, while (Begin != End) { auto &Item = *Begin; ErrorOr<basic_file_status> st = Item.status(); - if (!st && !IgnoreErrors) - return st.getError(); + if (st) { + if (is_directory(*st)) { + EC = remove_directories_impl(Item, IgnoreErrors); + if (EC && !IgnoreErrors) + return EC; + } - if (is_directory(*st)) { - EC = remove_directories_impl(Item, IgnoreErrors); + EC = fs::remove(Item.path(), true); if (EC && !IgnoreErrors) return EC; + } else if (!IgnoreErrors) { + return st.getError(); } - EC = fs::remove(Item.path(), true); - if (EC && !IgnoreErrors) - return EC; - Begin.increment(EC); if (EC && !IgnoreErrors) return EC; @@ -1338,9 +1334,16 @@ std::error_code changeFileOwnership(int FD, uint32_t Owner, uint32_t Group) { namespace path { bool home_directory(SmallVectorImpl<char> &result) { + std::unique_ptr<char[]> Buf; char *RequestedDir = getenv("HOME"); if (!RequestedDir) { - struct passwd *pw = getpwuid(getuid()); + long BufSize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (BufSize <= 0) + BufSize = 16384; + Buf = std::make_unique<char[]>(BufSize); + struct passwd Pwd; + struct passwd *pw = nullptr; + getpwuid_r(getuid(), &Pwd, Buf.get(), BufSize, &pw); if (pw && pw->pw_dir) RequestedDir = pw->pw_dir; } @@ -1353,11 +1356,10 @@ bool home_directory(SmallVectorImpl<char> &result) { } static bool getDarwinConfDir(bool TempDir, SmallVectorImpl<char> &Result) { - #if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR) +#if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR) // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR. // macros defined in <unistd.h> on darwin >= 9 - int ConfName = TempDir ? _CS_DARWIN_USER_TEMP_DIR - : _CS_DARWIN_USER_CACHE_DIR; + int ConfName = TempDir ? _CS_DARWIN_USER_TEMP_DIR : _CS_DARWIN_USER_CACHE_DIR; size_t ConfLen = confstr(ConfName, nullptr, 0); if (ConfLen > 0) { do { @@ -1373,7 +1375,7 @@ static bool getDarwinConfDir(bool TempDir, SmallVectorImpl<char> &Result) { Result.clear(); } - #endif +#endif return false; } @@ -1403,7 +1405,7 @@ bool user_config_directory(SmallVectorImpl<char> &result) { bool cache_directory(SmallVectorImpl<char> &result) { #ifdef __APPLE__ - if (getDarwinConfDir(false/*tempDir*/, result)) { + if (getDarwinConfDir(false /*tempDir*/, result)) { return true; } #else @@ -1489,13 +1491,13 @@ std::error_code copy_file(const Twine &From, const Twine &To) { auto Errno = errno; switch (Errno) { - case EEXIST: // To already exists. - case ENOTSUP: // Device does not support cloning. - case EXDEV: // From and To are on different devices. - break; - default: - // Anything else will also break copyfile(). - return std::error_code(Errno, std::generic_category()); + case EEXIST: // To already exists. + case ENOTSUP: // Device does not support cloning. + case EXDEV: // From and To are on different devices. + break; + default: + // Anything else will also break copyfile(). + return std::error_code(Errno, std::generic_category()); } // TODO: For EEXIST, profile calling fs::generateUniqueName() and diff --git a/llvm/lib/Support/Unix/Process.inc b/llvm/lib/Support/Unix/Process.inc index c1959b5cc2ae..2babf07944bf 100644 --- a/llvm/lib/Support/Unix/Process.inc +++ b/llvm/lib/Support/Unix/Process.inc @@ -15,6 +15,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Config/config.h" #include <mutex> +#include <optional> #if HAVE_FCNTL_H #include <fcntl.h> #endif @@ -40,10 +41,10 @@ #include <malloc/malloc.h> #endif #ifdef HAVE_SYS_IOCTL_H -# include <sys/ioctl.h> +#include <sys/ioctl.h> #endif #ifdef HAVE_TERMIOS_H -# include <termios.h> +#include <termios.h> #endif //===----------------------------------------------------------------------===// @@ -54,14 +55,15 @@ using namespace llvm; using namespace sys; -static std::pair<std::chrono::microseconds, std::chrono::microseconds> getRUsageTimes() { +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) }; + 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() }; + return {std::chrono::microseconds::zero(), std::chrono::microseconds::zero()}; #endif } @@ -99,7 +101,7 @@ size_t Process::GetMallocUsage() { #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 + return Stats.size_in_use; // darwin #elif defined(HAVE_MALLCTL) size_t alloc, sz; sz = sizeof(size_t); @@ -109,9 +111,9 @@ size_t Process::GetMallocUsage() { #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)) + 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 @@ -120,7 +122,8 @@ size_t Process::GetMallocUsage() { #endif } -void Process::GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time, +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(); @@ -149,10 +152,9 @@ void Process::PreventCoreFiles() { 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); + 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) @@ -163,20 +165,20 @@ void Process::PreventCoreFiles() { // Disable crash reporting on Mac OS X 10.5 signal(SIGABRT, _exit); - signal(SIGILL, _exit); - signal(SIGFPE, _exit); + signal(SIGILL, _exit); + signal(SIGFPE, _exit); signal(SIGSEGV, _exit); - signal(SIGBUS, _exit); + signal(SIGBUS, _exit); #endif coreFilesPrevented = true; } -Optional<std::string> Process::GetEnv(StringRef Name) { +std::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::nullopt; return std::string(Val); } @@ -197,7 +199,7 @@ private: int &FD; bool KeepOpen; }; -} +} // namespace std::error_code Process::FixupStandardFileDescriptors() { int NullFD = -1; @@ -239,7 +241,7 @@ std::error_code Process::SafelyCloseFileDescriptor(int FD) { if (sigfillset(&FullSet) < 0 || sigfillset(&SavedSet) < 0) return std::error_code(errno, std::generic_category()); - // Atomically swap our current signal mask with a full mask. + // Atomically swap our current signal mask with a full mask. #if LLVM_ENABLE_THREADS if (int EC = pthread_sigmask(SIG_SETMASK, &FullSet, &SavedSet)) return std::error_code(EC, std::generic_category()); @@ -329,15 +331,15 @@ extern "C" int tigetnum(char *capname); bool checkTerminalEnvironmentForColors() { if (const char *TermStr = std::getenv("TERM")) { return StringSwitch<bool>(TermStr) - .Case("ansi", true) - .Case("cygwin", true) - .Case("linux", true) - .StartsWith("screen", true) - .StartsWith("xterm", true) - .StartsWith("vt100", true) - .StartsWith("rxvt", true) - .EndsWith("color", true) - .Default(false); + .Case("ansi", true) + .Case("cygwin", true) + .Case("linux", true) + .StartsWith("screen", true) + .StartsWith("xterm", true) + .StartsWith("vt100", true) + .StartsWith("rxvt", true) + .EndsWith("color", true) + .Default(false); } return false; @@ -370,7 +372,8 @@ static bool terminalHasColors(int fd) { // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if // the terminfo says that no colors are supported. int colors_ti = tigetnum(const_cast<char *>("colors")); - bool HasColors = colors_ti >= 0 ? colors_ti : checkTerminalEnvironmentForColors(); + bool HasColors = + colors_ti >= 0 ? colors_ti : checkTerminalEnvironmentForColors(); // Now extract the structure allocated by setupterm and free its memory // through a really silly dance. @@ -410,20 +413,14 @@ bool Process::ColorNeedsFlush() { } const char *Process::OutputColor(char code, bool bold, bool bg) { - return colorcodes[bg?1:0][bold?1:0][code&7]; + return colorcodes[bg ? 1 : 0][bold ? 1 : 0][code & 7]; } -const char *Process::OutputBold(bool bg) { - return "\033[1m"; -} +const char *Process::OutputBold(bool bg) { return "\033[1m"; } -const char *Process::OutputReverse() { - return "\033[7m"; -} +const char *Process::OutputReverse() { return "\033[7m"; } -const char *Process::ResetColor() { - return "\033[0m"; -} +const char *Process::ResetColor() { return "\033[0m"; } #if !HAVE_DECL_ARC4RANDOM static unsigned GetRandomNumberSeed() { diff --git a/llvm/lib/Support/Unix/Program.inc b/llvm/lib/Support/Unix/Program.inc index 089342030b97..897e22711ae2 100644 --- a/llvm/lib/Support/Unix/Program.inc +++ b/llvm/lib/Support/Unix/Program.inc @@ -1,4 +1,4 @@ -//===- llvm/Support/Unix/Program.cpp -----------------------------*- C++ -*-===// +//===- llvm/Support/Unix/Program.inc ----------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -11,8 +11,8 @@ //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// -//=== WARNING: Implementation here must contain only generic UNIX code that -//=== is guaranteed to work on *all* UNIX variants. +//=== WARNING: Implementation here must contain only generic UNIX +//=== code that is guaranteed to work on *all* UNIX variants. //===----------------------------------------------------------------------===// #include "llvm/Support/Program.h" @@ -55,7 +55,7 @@ #endif #if !USE_NSGETENVIRON - extern char **environ; +extern char **environ; #else #include <crt_externs.h> // _NSGetEnviron #endif @@ -89,12 +89,12 @@ ErrorOr<std::string> sys::findProgramByName(StringRef Name, 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 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) { +static bool RedirectIO(std::optional<StringRef> Path, int FD, std::string *ErrMsg) { if (!Path) // Noop return false; std::string File; @@ -105,10 +105,10 @@ static bool RedirectIO(Optional<StringRef> Path, int FD, std::string* ErrMsg) { File = std::string(*Path); // Open the file - int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); + 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")); + MakeErrMsg(ErrMsg, "Cannot open file '" + File + "' for " + + (FD == 0 ? "input" : "output")); return true; } @@ -118,7 +118,7 @@ static bool RedirectIO(Optional<StringRef> Path, int FD, std::string* ErrMsg) { close(InFD); return true; } - close(InFD); // Close the original FD + close(InFD); // Close the original FD return false; } @@ -135,30 +135,28 @@ static bool RedirectIO_PS(const std::string *Path, int FD, std::string *ErrMsg, File = Path->c_str(); if (int Err = posix_spawn_file_actions_addopen( - FileActions, FD, File, - FD == 0 ? O_RDONLY : O_WRONLY | O_CREAT, 0666)) + FileActions, FD, File, FD == 0 ? O_RDONLY : O_WRONLY | O_CREAT, 0666)) return MakeErrMsg(ErrMsg, "Cannot posix_spawn_file_actions_addopen", Err); return false; } #endif -static void TimeOutHandler(int Sig) { -} +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; + __typeof__(r.rlim_cur) limit = (__typeof__(r.rlim_cur))(size)*1048576; // Heap size - getrlimit (RLIMIT_DATA, &r); + getrlimit(RLIMIT_DATA, &r); r.rlim_cur = limit; - setrlimit (RLIMIT_DATA, &r); + setrlimit(RLIMIT_DATA, &r); #ifdef RLIMIT_RSS // Resident set size. - getrlimit (RLIMIT_RSS, &r); + getrlimit(RLIMIT_RSS, &r); r.rlim_cur = limit; - setrlimit (RLIMIT_RSS, &r); + setrlimit(RLIMIT_RSS, &r); #endif #endif } @@ -173,8 +171,8 @@ toNullTerminatedCStringArray(ArrayRef<StringRef> Strings, StringSaver &Saver) { } static bool Execute(ProcessInfo &PI, StringRef Program, - ArrayRef<StringRef> Args, Optional<ArrayRef<StringRef>> Env, - ArrayRef<Optional<StringRef>> Redirects, + ArrayRef<StringRef> Args, std::optional<ArrayRef<StringRef>> Env, + ArrayRef<std::optional<StringRef>> Redirects, unsigned MemoryLimit, std::string *ErrMsg, BitVector *AffinityMask) { if (!llvm::sys::fs::exists(Program)) { @@ -263,7 +261,7 @@ static bool Execute(ProcessInfo &PI, StringRef Program, posix_spawn_file_actions_destroy(FileActions); if (Err) - return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err); + return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err); PI.Pid = PID; PI.Process = PID; @@ -275,56 +273,62 @@ static bool Execute(ProcessInfo &PI, StringRef Program, // 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; + // 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; } - } + // Child process: Execute the program. + case 0: { + // Redirect file descriptors... + if (!Redirects.empty()) { + // Redirect stdin + if (RedirectIO(Redirects[0], 0, ErrMsg)) { + return false; } - - // Set memory limits - if (MemoryLimit!=0) { - SetMemoryLimits(MemoryLimit); + // 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; + } } + } - // Execute! - std::string PathStr = std::string(Program); - if (Envp != nullptr) - execve(PathStr.c_str(), const_cast<char **>(Argv), - const_cast<char **>(Envp)); - else - execv(PathStr.c_str(), const_cast<char **>(Argv)); - // 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); + // Set memory limits + if (MemoryLimit != 0) { + SetMemoryLimits(MemoryLimit); } - // Parent process: Break out of the switch to do our processing. - default: - break; + // Execute! + std::string PathStr = std::string(Program); + if (Envp != nullptr) + execve(PathStr.c_str(), const_cast<char **>(Argv), + const_cast<char **>(Envp)); + else + execv(PathStr.c_str(), const_cast<char **>(Argv)); + // 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; @@ -339,7 +343,7 @@ namespace sys { #ifndef _AIX using ::wait4; #else -static pid_t (wait4)(pid_t pid, int *status, int options, struct rusage *usage); +static pid_t(wait4)(pid_t pid, int *status, int options, struct rusage *usage); #endif } // namespace sys @@ -347,11 +351,11 @@ static pid_t (wait4)(pid_t pid, int *status, int options, struct rusage *usage); #ifdef _AIX #ifndef _ALL_SOURCE -extern "C" pid_t (wait4)(pid_t pid, int *status, int options, - struct rusage *usage); +extern "C" pid_t(wait4)(pid_t pid, int *status, int options, + struct rusage *usage); #endif -pid_t (llvm::sys::wait4)(pid_t pid, int *status, int options, - struct rusage *usage) { +pid_t(llvm::sys::wait4)(pid_t pid, int *status, int options, + struct rusage *usage) { assert(pid > 0 && "Only expecting to handle actual PID values!"); assert((options & ~WNOHANG) == 0 && "Expecting WNOHANG at most!"); assert(usage && "Expecting usage collection!"); @@ -379,17 +383,23 @@ pid_t (llvm::sys::wait4)(pid_t pid, int *status, int options, } #endif -ProcessInfo llvm::sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, - bool WaitUntilTerminates, std::string *ErrMsg, - Optional<ProcessStatistics> *ProcStat) { +ProcessInfo llvm::sys::Wait(const ProcessInfo &PI, + std::optional<unsigned> SecondsToWait, + std::string *ErrMsg, + std::optional<ProcessStatistics> *ProcStat, + bool Polling) { 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) { + bool WaitUntilTerminates = false; + if (!SecondsToWait) { + WaitUntilTerminates = true; + } else { + if (*SecondsToWait == 0) + WaitPidOptions = WNOHANG; + // 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. @@ -398,12 +408,11 @@ ProcessInfo llvm::sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, sigemptyset(&Act.sa_mask); sigaction(SIGALRM, &Act, &Old); // FIXME The alarm signal may be delivered to another thread. - alarm(SecondsToWait); - } else if (SecondsToWait == 0) - WaitPidOptions = WNOHANG; + alarm(*SecondsToWait); + } // Parent process: Wait for the child process to terminate. - int status; + int status = 0; ProcessInfo WaitResult; rusage Info; if (ProcStat) @@ -418,7 +427,7 @@ ProcessInfo llvm::sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, // Non-blocking wait. return WaitResult; } else { - if (SecondsToWait && errno == EINTR) { + if (SecondsToWait && errno == EINTR && !Polling) { // Kill the child. kill(PI.Pid, SIGKILL); @@ -494,13 +503,13 @@ ProcessInfo llvm::sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, return WaitResult; } -std::error_code llvm::sys::ChangeStdinMode(fs::OpenFlags Flags){ +std::error_code llvm::sys::ChangeStdinMode(fs::OpenFlags Flags) { if (!(Flags & fs::OF_Text)) return ChangeStdinToBinary(); return std::error_code(); } -std::error_code llvm::sys::ChangeStdoutMode(fs::OpenFlags Flags){ +std::error_code llvm::sys::ChangeStdoutMode(fs::OpenFlags Flags) { if (!(Flags & fs::OF_Text)) return ChangeStdoutToBinary(); return std::error_code(); @@ -520,7 +529,8 @@ 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::OF_TextWithCRLF); + llvm::raw_fd_ostream OS(FileName, EC, + llvm::sys::fs::OpenFlags::OF_TextWithCRLF); if (EC) return EC; diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc index bf145bffe8bf..05a7335216f4 100644 --- a/llvm/lib/Support/Unix/Signals.inc +++ b/llvm/lib/Support/Unix/Signals.inc @@ -48,7 +48,7 @@ #include <algorithm> #include <string> #ifdef HAVE_BACKTRACE -# include BACKTRACE_HEADER // For backtrace(). +#include BACKTRACE_HEADER // For backtrace(). #endif #if HAVE_SIGNAL_H #include <signal.h> @@ -79,8 +79,8 @@ using namespace llvm; -static void SignalHandler(int Sig); // defined below. -static void InfoSignalHandler(int Sig); // defined below. +static void SignalHandler(int Sig); // defined below. +static void InfoSignalHandler(int Sig); // defined below. using SignalHandlerFunctionType = void (*)(); /// The function to call if ctrl-c is pressed. @@ -208,40 +208,45 @@ static StringRef Argv0; /// 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, SIGTERM, SIGUSR2 -}; +static const int IntSigs[] = {SIGHUP, SIGINT, SIGTERM, SIGUSR2}; /// 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 +static const int KillSigs[] = {SIGILL, + SIGTRAP, + SIGABRT, + SIGFPE, + SIGBUS, + SIGSEGV, + SIGQUIT #ifdef SIGSYS - , SIGSYS + , + SIGSYS #endif #ifdef SIGXCPU - , SIGXCPU + , + SIGXCPU #endif #ifdef SIGXFSZ - , SIGXFSZ + , + SIGXFSZ #endif #ifdef SIGEMT - , SIGEMT + , + SIGEMT #endif }; /// Signals that represent requests for status. -static const int InfoSigs[] = { - SIGUSR1 +static const int InfoSigs[] = {SIGUSR1 #ifdef SIGINFO - , SIGINFO + , + SIGINFO #endif }; -static const size_t NumSigs = - array_lengthof(IntSigs) + array_lengthof(KillSigs) + - array_lengthof(InfoSigs) + 1 /* SIGPIPE */; - +static const size_t NumSigs = std::size(IntSigs) + std::size(KillSigs) + + std::size(InfoSigs) + 1 /* SIGPIPE */; static std::atomic<unsigned> NumRegisteredSignals = ATOMIC_VAR_INIT(0); static struct { @@ -298,7 +303,7 @@ static void RegisterHandlers() { // Not signal-safe. enum class SignalKind { IsKill, IsInfo }; auto registerHandler = [&](int Signal, SignalKind Kind) { unsigned Index = NumRegisteredSignals.load(); - assert(Index < array_lengthof(RegisteredSignalInfo) && + assert(Index < std::size(RegisteredSignalInfo) && "Out of space for signal handlers!"); struct sigaction NewHandler; @@ -334,8 +339,8 @@ static void RegisterHandlers() { // Not signal-safe. void sys::unregisterHandlers() { // Restore all of the signal handlers to how they were before we showed up. for (unsigned i = 0, e = NumRegisteredSignals.load(); i != e; ++i) { - sigaction(RegisteredSignalInfo[i].SigNo, - &RegisteredSignalInfo[i].SA, nullptr); + sigaction(RegisteredSignalInfo[i].SigNo, &RegisteredSignalInfo[i].SA, + nullptr); --NumRegisteredSignals; } } @@ -407,14 +412,12 @@ static void SignalHandler(int Sig) { } static void InfoSignalHandler(int Sig) { - SaveAndRestore<int> SaveErrnoDuringASignalHandler(errno); + SaveAndRestore SaveErrnoDuringASignalHandler(errno); if (SignalHandlerFunctionType CurrentInfoFunction = InfoSignalFunction) CurrentInfoFunction(); } -void llvm::sys::RunInterruptHandlers() { - RemoveFilesToRemove(); -} +void llvm::sys::RunInterruptHandlers() { RemoveFilesToRemove(); } void llvm::sys::SetInterruptFunction(void (*IF)()) { InterruptFunction.exchange(IF); @@ -432,17 +435,12 @@ void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) { } void llvm::sys::DefaultOneShotPipeSignalHandler() { - // UNIX03 conformance requires a non-zero exit code and an error message - // to stderr when writing to a closed stdout fails. - errs() << "error: write on a pipe with no reader\n"; - // Send a special return code that drivers can check for, from sysexits.h. exit(EX_IOERR); } // The public API -bool llvm::sys::RemoveFileOnSignal(StringRef Filename, - std::string* ErrMsg) { +bool llvm::sys::RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg) { // Ensure that cleanup will occur as soon as one file is added. static ManagedStatic<FilesToRemoveCleanup> FilesToRemoveCleanup; *FilesToRemoveCleanup; @@ -465,7 +463,7 @@ void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr, RegisterHandlers(); } -#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES && HAVE_LINK_H && \ +#if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES && HAVE_LINK_H && \ (defined(__linux__) || defined(__FreeBSD__) || \ defined(__FreeBSD_kernel__) || defined(__NetBSD__)) struct DlIteratePhdrData { @@ -478,7 +476,7 @@ struct DlIteratePhdrData { }; static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { - DlIteratePhdrData *data = (DlIteratePhdrData*)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++) { @@ -566,13 +564,13 @@ void llvm::sys::PrintStackTrace(raw_ostream &OS, int Depth) { #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))); + depth = backtrace(StackTrace, static_cast<int>(std::size(StackTrace))); #endif #if defined(HAVE__UNWIND_BACKTRACE) // Try _Unwind_Backtrace() if backtrace() failed. if (!depth) - depth = unwindBacktrace(StackTrace, - static_cast<int>(array_lengthof(StackTrace))); + depth = + unwindBacktrace(StackTrace, static_cast<int>(std::size(StackTrace))); #endif if (!depth) return; @@ -590,13 +588,16 @@ void llvm::sys::PrintStackTrace(raw_ostream &OS, int Depth) { for (int i = 0; i < depth; ++i) { Dl_info dlinfo; dladdr(StackTrace[i], &dlinfo); - const char* name = strrchr(dlinfo.dli_fname, '/'); + const char *name = strrchr(dlinfo.dli_fname, '/'); int nwidth; - if (!name) nwidth = strlen(dlinfo.dli_fname); - else nwidth = strlen(name) - 1; + if (!name) + nwidth = strlen(dlinfo.dli_fname); + else + nwidth = strlen(name) - 1; - if (nwidth > width) width = nwidth; + if (nwidth > width) + width = nwidth; } for (int i = 0; i < depth; ++i) { @@ -605,23 +606,27 @@ void llvm::sys::PrintStackTrace(raw_ostream &OS, int Depth) { 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); + 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, + 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; + char *d = itaniumDemangle(dlinfo.dli_sname, nullptr, nullptr, &res); + if (!d) + OS << dlinfo.dli_sname; + else + OS << d; free(d); - OS << format(" + %tu", (static_cast<const char*>(StackTrace[i])- - static_cast<const char*>(dlinfo.dli_saddr))); + OS << format(" + %tu", (static_cast<const char *>(StackTrace[i]) - + static_cast<const char *>(dlinfo.dli_saddr))); } OS << '\n'; } @@ -652,11 +657,9 @@ void llvm::sys::PrintStackTraceOnErrorSignal(StringRef Argv0, 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); + 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 diff --git a/llvm/lib/Support/Unix/ThreadLocal.inc b/llvm/lib/Support/Unix/ThreadLocal.inc deleted file mode 100644 index 0a958a2b952f..000000000000 --- a/llvm/lib/Support/Unix/ThreadLocal.inc +++ /dev/null @@ -1,58 +0,0 @@ -//=== llvm/Support/Unix/ThreadLocal.inc - Unix Thread Local Data -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// 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. -//===----------------------------------------------------------------------===// - -#include "llvm/Config/config.h" - -#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); -} - -} diff --git a/llvm/lib/Support/Unix/Threading.inc b/llvm/lib/Support/Unix/Threading.inc index 99f64b4f553d..819748db4ec2 100644 --- a/llvm/lib/Support/Unix/Threading.inc +++ b/llvm/lib/Support/Unix/Threading.inc @@ -13,12 +13,18 @@ #include "Unix.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" #if defined(__APPLE__) #include <mach/mach_init.h> #include <mach/mach_port.h> #include <pthread/qos.h> +#include <sys/sysctl.h> +#include <sys/types.h> #endif #include <pthread.h> @@ -52,7 +58,7 @@ namespace llvm { pthread_t llvm_execute_on_thread_impl(void *(*ThreadFunc)(void *), void *Arg, - llvm::Optional<unsigned> StackSizeInBytes) { + std::optional<unsigned> StackSizeInBytes) { int errnum; // Construct the attributes object. @@ -98,13 +104,9 @@ void llvm_thread_join_impl(pthread_t Thread) { } } -pthread_t llvm_thread_get_id_impl(pthread_t Thread) { - return Thread; -} +pthread_t llvm_thread_get_id_impl(pthread_t Thread) { return Thread; } -pthread_t llvm_thread_get_current_id_impl() { - return ::pthread_self(); -} +pthread_t llvm_thread_get_current_id_impl() { return ::pthread_self(); } } // namespace llvm @@ -131,7 +133,6 @@ uint64_t llvm::get_threadid() { #endif } - static constexpr uint32_t get_max_thread_name_length_impl() { #if defined(__NetBSD__) return PTHREAD_MAX_NAMELEN_NP; @@ -180,7 +181,7 @@ void llvm::set_thread_name(const Twine &Name) { ::pthread_set_name_np(::pthread_self(), NameStr.data()); #elif defined(__NetBSD__) ::pthread_setname_np(::pthread_self(), "%s", - const_cast<char *>(NameStr.data())); + const_cast<char *>(NameStr.data())); #elif defined(__APPLE__) ::pthread_setname_np(NameStr.data()); #endif @@ -196,8 +197,8 @@ void llvm::get_thread_name(SmallVectorImpl<char> &Name) { 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 }; + 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); @@ -240,7 +241,7 @@ void llvm::get_thread_name(SmallVectorImpl<char> &Name) { #elif defined(__linux__) #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. + 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 @@ -267,18 +268,22 @@ SetThreadPriorityResult llvm::set_thread_priority(ThreadPriority Priority) { #elif defined(__APPLE__) // https://developer.apple.com/documentation/apple-silicon/tuning-your-code-s-performance-for-apple-silicon // - // Background - Applies to work that isn’t visible to the user and may take significant - // time to complete. Examples include indexing, backing up, or synchronizing data. This - // class emphasizes energy efficiency. + // Background - Applies to work that isn’t visible to the user and may take + // significant time to complete. Examples include indexing, backing up, or + // synchronizing data. This class emphasizes energy efficiency. // - // Utility - Applies to work that takes anywhere from a few seconds to a few minutes to - // complete. Examples include downloading a document or importing data. This class - // offers a balance between responsiveness, performance, and energy efficiency. - const auto qosClass = [&](){ + // Utility - Applies to work that takes anywhere from a few seconds to a few + // minutes to complete. Examples include downloading a document or importing + // data. This class offers a balance between responsiveness, performance, and + // energy efficiency. + const auto qosClass = [&]() { switch (Priority) { - case ThreadPriority::Background: return QOS_CLASS_BACKGROUND; - case ThreadPriority::Low: return QOS_CLASS_UTILITY; - case ThreadPriority::Default: return QOS_CLASS_DEFAULT; + case ThreadPriority::Background: + return QOS_CLASS_BACKGROUND; + case ThreadPriority::Low: + return QOS_CLASS_UTILITY; + case ThreadPriority::Default: + return QOS_CLASS_DEFAULT; } }(); return !pthread_set_qos_class_self_np(qosClass, 0) @@ -290,7 +295,7 @@ SetThreadPriorityResult llvm::set_thread_priority(ThreadPriority Priority) { #include <thread> -int computeHostNumHardwareThreads() { +static int computeHostNumHardwareThreads() { #if defined(__FreeBSD__) cpuset_t mask; CPU_ZERO(&mask); @@ -317,3 +322,122 @@ llvm::BitVector llvm::get_thread_affinity_mask() { } unsigned llvm::get_cpus() { return 1; } + +#if defined(__linux__) && (defined(__i386__) || defined(__x86_64__)) +// On Linux, the number of physical cores can be computed from /proc/cpuinfo, +// using the number of unique physical/core id pairs. The following +// implementation reads the /proc/cpuinfo format on an x86_64 system. +static int computeHostNumPhysicalCores() { + // Enabled represents the number of physical id/core id pairs with at least + // one processor id enabled by the CPU affinity mask. + cpu_set_t Affinity, Enabled; + if (sched_getaffinity(0, sizeof(Affinity), &Affinity) != 0) + return -1; + CPU_ZERO(&Enabled); + + // Read /proc/cpuinfo as a stream (until EOF reached). It cannot be + // mmapped because it appears to have 0 size. + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = + llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo"); + if (std::error_code EC = Text.getError()) { + llvm::errs() << "Can't read " + << "/proc/cpuinfo: " << EC.message() << "\n"; + return -1; + } + SmallVector<StringRef, 8> strs; + (*Text)->getBuffer().split(strs, "\n", /*MaxSplit=*/-1, + /*KeepEmpty=*/false); + int CurProcessor = -1; + int CurPhysicalId = -1; + int CurSiblings = -1; + int CurCoreId = -1; + for (StringRef Line : strs) { + std::pair<StringRef, StringRef> Data = Line.split(':'); + auto Name = Data.first.trim(); + auto Val = Data.second.trim(); + // These fields are available if the kernel is configured with CONFIG_SMP. + if (Name == "processor") + Val.getAsInteger(10, CurProcessor); + else if (Name == "physical id") + Val.getAsInteger(10, CurPhysicalId); + else if (Name == "siblings") + Val.getAsInteger(10, CurSiblings); + else if (Name == "core id") { + Val.getAsInteger(10, CurCoreId); + // The processor id corresponds to an index into cpu_set_t. + if (CPU_ISSET(CurProcessor, &Affinity)) + CPU_SET(CurPhysicalId * CurSiblings + CurCoreId, &Enabled); + } + } + return CPU_COUNT(&Enabled); +} +#elif defined(__linux__) && defined(__s390x__) +static int computeHostNumPhysicalCores() { + return sysconf(_SC_NPROCESSORS_ONLN); +} +#elif defined(__linux__) && !defined(__ANDROID__) +static int computeHostNumPhysicalCores() { + cpu_set_t Affinity; + if (sched_getaffinity(0, sizeof(Affinity), &Affinity) == 0) + return CPU_COUNT(&Affinity); + + // The call to sched_getaffinity() may have failed because the Affinity + // mask is too small for the number of CPU's on the system (i.e. the + // system has more than 1024 CPUs). Allocate a mask large enough for + // twice as many CPUs. + cpu_set_t *DynAffinity; + DynAffinity = CPU_ALLOC(2048); + if (sched_getaffinity(0, CPU_ALLOC_SIZE(2048), DynAffinity) == 0) { + int NumCPUs = CPU_COUNT(DynAffinity); + CPU_FREE(DynAffinity); + return NumCPUs; + } + return -1; +} +#elif defined(__APPLE__) +// Gets the number of *physical cores* on the machine. +static int computeHostNumPhysicalCores() { + uint32_t count; + size_t len = sizeof(count); + sysctlbyname("hw.physicalcpu", &count, &len, NULL, 0); + if (count < 1) { + int nm[2]; + nm[0] = CTL_HW; + nm[1] = HW_AVAILCPU; + sysctl(nm, 2, &count, &len, NULL, 0); + if (count < 1) + return -1; + } + return count; +} +#elif defined(__MVS__) +static int computeHostNumPhysicalCores() { + enum { + // Byte offset of the pointer to the Communications Vector Table (CVT) in + // the Prefixed Save Area (PSA). The table entry is a 31-bit pointer and + // will be zero-extended to uintptr_t. + FLCCVT = 16, + // Byte offset of the pointer to the Common System Data Area (CSD) in the + // CVT. The table entry is a 31-bit pointer and will be zero-extended to + // uintptr_t. + CVTCSD = 660, + // Byte offset to the number of live CPs in the LPAR, stored as a signed + // 32-bit value in the table. + CSD_NUMBER_ONLINE_STANDARD_CPS = 264, + }; + char *PSA = 0; + char *CVT = reinterpret_cast<char *>( + static_cast<uintptr_t>(reinterpret_cast<unsigned int &>(PSA[FLCCVT]))); + char *CSD = reinterpret_cast<char *>( + static_cast<uintptr_t>(reinterpret_cast<unsigned int &>(CVT[CVTCSD]))); + return reinterpret_cast<int &>(CSD[CSD_NUMBER_ONLINE_STANDARD_CPS]); +} +#else +// On other systems, return -1 to indicate unknown. +static int computeHostNumPhysicalCores() { return -1; } +#endif + +int llvm::get_physical_cores() { + static int NumCores = computeHostNumPhysicalCores(); + return NumCores; +} diff --git a/llvm/lib/Support/Unix/Watchdog.inc b/llvm/lib/Support/Unix/Watchdog.inc index b363ef779560..b33e52d88500 100644 --- a/llvm/lib/Support/Unix/Watchdog.inc +++ b/llvm/lib/Support/Unix/Watchdog.inc @@ -17,17 +17,17 @@ #endif namespace llvm { - namespace sys { - Watchdog::Watchdog(unsigned int seconds) { +namespace sys { +Watchdog::Watchdog(unsigned int seconds) { #ifdef HAVE_UNISTD_H - alarm(seconds); + alarm(seconds); #endif - } +} - Watchdog::~Watchdog() { +Watchdog::~Watchdog() { #ifdef HAVE_UNISTD_H - alarm(0); + alarm(0); #endif - } - } } +} // namespace sys +} // namespace llvm |