diff options
Diffstat (limited to 'contrib/llvm/lib/Support/Unix')
-rw-r--r-- | contrib/llvm/lib/Support/Unix/COM.inc | 7 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/DynamicLibrary.inc | 7 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Host.inc | 24 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Memory.inc | 81 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Mutex.inc | 7 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Path.inc | 219 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Process.inc | 20 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Program.inc | 23 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/RWMutex.inc | 7 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Signals.inc | 81 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/ThreadLocal.inc | 7 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Threading.inc | 46 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Unix.h | 9 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Watchdog.inc | 7 |
14 files changed, 404 insertions, 141 deletions
diff --git a/contrib/llvm/lib/Support/Unix/COM.inc b/contrib/llvm/lib/Support/Unix/COM.inc index 5b71de74ebf3..03a690ac3766 100644 --- a/contrib/llvm/lib/Support/Unix/COM.inc +++ b/contrib/llvm/lib/Support/Unix/COM.inc @@ -1,9 +1,8 @@ //===- 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. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/contrib/llvm/lib/Support/Unix/DynamicLibrary.inc b/contrib/llvm/lib/Support/Unix/DynamicLibrary.inc index 029451f347e8..a2a379963de0 100644 --- a/contrib/llvm/lib/Support/Unix/DynamicLibrary.inc +++ b/contrib/llvm/lib/Support/Unix/DynamicLibrary.inc @@ -1,9 +1,8 @@ //===- 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. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/contrib/llvm/lib/Support/Unix/Host.inc b/contrib/llvm/lib/Support/Unix/Host.inc index b65f84bf4444..17d78dc18be7 100644 --- a/contrib/llvm/lib/Support/Unix/Host.inc +++ b/contrib/llvm/lib/Support/Unix/Host.inc @@ -1,9 +1,8 @@ //===- 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. +// 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 // //===----------------------------------------------------------------------===// // @@ -50,6 +49,23 @@ static std::string updateTripleOSVersion(std::string TargetTripleString) { 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 = Triple::getOSTypeName(Triple::AIX); + NewOSName += name.version; + NewOSName += '.'; + NewOSName += name.release; + NewOSName += ".0.0"; + TT.setOSName(NewOSName); + return TT.str(); + } + } + } return TargetTripleString; } diff --git a/contrib/llvm/lib/Support/Unix/Memory.inc b/contrib/llvm/lib/Support/Unix/Memory.inc index adbfff2f59a5..a0927da50e48 100644 --- a/contrib/llvm/lib/Support/Unix/Memory.inc +++ b/contrib/llvm/lib/Support/Unix/Memory.inc @@ -1,9 +1,8 @@ //===- 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. +// 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 // //===----------------------------------------------------------------------===// // @@ -46,7 +45,7 @@ extern "C" void __clear_cache(void *, void*); namespace { int getPosixProtectionFlags(unsigned Flags) { - switch (Flags) { + switch (Flags & llvm::sys::Memory::MF_RWE_MASK) { case llvm::sys::Memory::MF_READ: return PROT_READ; case llvm::sys::Memory::MF_WRITE: @@ -59,14 +58,13 @@ int getPosixProtectionFlags(unsigned Flags) { llvm::sys::Memory::MF_EXEC: return PROT_READ | PROT_WRITE | PROT_EXEC; case llvm::sys::Memory::MF_EXEC: -#if defined(__FreeBSD__) +#if (defined(__FreeBSD__) || defined(__POWERPC__) || defined (__ppc__) || \ + defined(_POWER) || defined(_ARCH_PPC)) // 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; @@ -92,19 +90,24 @@ Memory::allocateMappedMemory(size_t NumBytes, 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 + // On platforms that have it, we can use MAP_ANON to get a memory-mapped + // page without file backing, but we need a fallback of opening /dev/zero + // for strictly POSIX platforms instead. + int fd; +#if defined(MAP_ANON) + fd = -1; #else - MAP_ANON + fd = open("/dev/zero", O_RDWR); + if (fd == -1) { + EC = std::error_code(errno, std::generic_category()); + return MemoryBlock(); + } #endif - ; // Ends statement above + int MMFlags = MAP_PRIVATE; +#if defined(MAP_ANON) + MMFlags |= MAP_ANON; +#endif int Protect = getPosixProtectionFlags(PFlags); #if defined(__NetBSD__) && defined(PROT_MPROTECT) @@ -113,23 +116,39 @@ 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->size() : 0; + NearBlock->allocatedSize() : 0; + static const size_t PageSize = Process::getPageSizeEstimate(); + const size_t NumPages = (NumBytes+PageSize-1)/PageSize; + if (Start && Start % PageSize) Start += PageSize - Start % PageSize; - void *Addr = ::mmap(reinterpret_cast<void*>(Start), PageSize*NumPages, - Protect, MMFlags, fd, 0); + // FIXME: Handle huge page requests (MF_HUGE_HINT). + 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 return allocateMappedMemory(NumBytes, nullptr, PFlags, EC); + } EC = std::error_code(errno, std::generic_category()); +#if !defined(MAP_ANON) + close(fd); +#endif return MemoryBlock(); } +#if !defined(MAP_ANON) + close(fd); +#endif + MemoryBlock Result; Result.Address = Addr; - Result.Size = NumPages*PageSize; + Result.AllocatedSize = PageSize*NumPages; + Result.Flags = PFlags; // Rely on protectMappedMemory to invalidate instruction cache. if (PFlags & MF_EXEC) { @@ -143,22 +162,22 @@ Memory::allocateMappedMemory(size_t NumBytes, std::error_code Memory::releaseMappedMemory(MemoryBlock &M) { - if (M.Address == nullptr || M.Size == 0) + if (M.Address == nullptr || M.AllocatedSize == 0) return std::error_code(); - if (0 != ::munmap(M.Address, M.Size)) + if (0 != ::munmap(M.Address, M.AllocatedSize)) return std::error_code(errno, std::generic_category()); M.Address = nullptr; - M.Size = 0; + M.AllocatedSize = 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) + static const size_t PageSize = Process::getPageSizeEstimate(); + if (M.Address == nullptr || M.AllocatedSize == 0) return std::error_code(); if (!Flags) @@ -166,7 +185,7 @@ Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) { 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); + uintptr_t End = alignAddr((uint8_t *)M.Address + M.AllocatedSize, PageSize); bool InvalidateCache = (Flags & MF_EXEC); @@ -179,7 +198,7 @@ Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) { if (Result != 0) return std::error_code(errno, std::generic_category()); - Memory::InvalidateInstructionCache(M.Address, M.Size); + Memory::InvalidateInstructionCache(M.Address, M.AllocatedSize); InvalidateCache = false; } #endif @@ -190,7 +209,7 @@ Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) { return std::error_code(errno, std::generic_category()); if (InvalidateCache) - Memory::InvalidateInstructionCache(M.Address, M.Size); + Memory::InvalidateInstructionCache(M.Address, M.AllocatedSize); return std::error_code(); } diff --git a/contrib/llvm/lib/Support/Unix/Mutex.inc b/contrib/llvm/lib/Support/Unix/Mutex.inc index fe6b17041457..2c982b38d6ff 100644 --- a/contrib/llvm/lib/Support/Unix/Mutex.inc +++ b/contrib/llvm/lib/Support/Unix/Mutex.inc @@ -1,9 +1,8 @@ //===- 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. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/contrib/llvm/lib/Support/Unix/Path.inc b/contrib/llvm/lib/Support/Unix/Path.inc index d7cc0d627d09..e80880c6b3cb 100644 --- a/contrib/llvm/lib/Support/Unix/Path.inc +++ b/contrib/llvm/lib/Support/Unix/Path.inc @@ -1,9 +1,8 @@ //===- llvm/Support/Unix/Path.inc - Unix Path Implementation ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -38,6 +37,7 @@ #ifdef __APPLE__ #include <mach-o/dyld.h> #include <sys/attr.h> +#include <copyfile.h> #elif defined(__DragonFly__) #include <sys/mount.h> #endif @@ -56,7 +56,7 @@ #include <sys/types.h> #if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && \ - !defined(__linux__) && !defined(__FreeBSD_kernel__) + !defined(__linux__) && !defined(__FreeBSD_kernel__) && !defined(_AIX) #include <sys/statvfs.h> #define STATVFS statvfs #define FSTATVFS fstatvfs @@ -77,6 +77,14 @@ #endif #endif #include <sys/vfs.h> +#elif defined(_AIX) +#include <sys/statfs.h> + +// <sys/vmount.h> depends on `uint` to be a typedef from <sys/types.h> to +// `uint_t`; however, <sys/types.h> does not always declare `uint`. We provide +// the typedef prior to including <sys/vmount.h> to work around this issue. +typedef uint_t uint; +#include <sys/vmount.h> #else #include <sys/mount.h> #endif @@ -108,7 +116,11 @@ test_dir(char ret[PATH_MAX], const char *dir, const char *bin) struct stat sb; char fullpath[PATH_MAX]; - snprintf(fullpath, PATH_MAX, "%s/%s", dir, bin); + int chars = snprintf(fullpath, PATH_MAX, "%s/%s", dir, bin); + // We cannot write PATH_MAX characters because the string will be terminated + // with a null character. Fail if truncation happened. + if (chars >= PATH_MAX) + return 1; if (!realpath(fullpath, ret)) return 1; if (stat(fullpath, &sb) != 0) @@ -120,8 +132,6 @@ test_dir(char ret[PATH_MAX], const char *dir, const char *bin) static char * getprogpath(char ret[PATH_MAX], const char *bin) { - char *pv, *s, *t; - /* First approach: absolute path. */ if (bin[0] == '/') { if (test_dir(ret, "/", bin) == 0) @@ -140,18 +150,21 @@ getprogpath(char ret[PATH_MAX], const char *bin) } /* Third approach: $PATH */ + char *pv; if ((pv = getenv("PATH")) == nullptr) return nullptr; - s = pv = strdup(pv); - if (!pv) + char *s = strdup(pv); + if (!s) return nullptr; - while ((t = strsep(&s, ":")) != nullptr) { + char *state; + for (char *t = strtok_r(s, ":", &state); t != nullptr; + t = strtok_r(nullptr, ":", &state)) { if (test_dir(ret, t, bin) == 0) { - free(pv); + free(s); return ret; } } - free(pv); + free(s); return nullptr; } #endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__ @@ -173,8 +186,21 @@ std::string getMainExecutable(const char *argv0, void *MainAddr) { #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ defined(__minix) || defined(__DragonFly__) || \ defined(__FreeBSD_kernel__) || defined(_AIX) + StringRef curproc("/proc/curproc/file"); char exe_path[PATH_MAX]; - + // /proc is not mounted by default under FreeBSD, but gives more accurate + // information than argv[0] when it is. + if (sys::fs::exists(curproc)) { + ssize_t len = readlink(curproc.str().c_str(), exe_path, sizeof(exe_path)); + if (len > 0) { + // Null terminate the string for realpath. readlink never null + // terminates its output. + len = std::min(len, ssize_t(sizeof(exe_path) - 1)); + exe_path[len] = '\0'; + return exe_path; + } + } + // If we don't have procfs mounted, fall back to argv[0] if (getprogpath(exe_path, argv0) != NULL) return exe_path; #elif defined(__linux__) || defined(__CYGWIN__) @@ -196,20 +222,20 @@ std::string getMainExecutable(const char *argv0, void *MainAddr) { // the program, and not the eventual binary file. Therefore, call realpath // so this behaves the same on all platforms. #if _POSIX_VERSION >= 200112 || defined(__GLIBC__) - char *real_path = realpath(exe_path, NULL); - std::string ret = std::string(real_path); - free(real_path); - return ret; + if (char *real_path = realpath(exe_path, NULL)) { + std::string ret = std::string(real_path); + free(real_path); + return ret; + } #else char real_path[MAXPATHLEN]; - realpath(exe_path, real_path); - return std::string(real_path); + if (realpath(exe_path, real_path)) + return std::string(real_path); #endif - } else { - // Fall back to the classical detection. - if (getprogpath(exe_path, argv0)) - return exe_path; } + // Fall back to the classical detection. + if (getprogpath(exe_path, argv0)) + return exe_path; #elif defined(HAVE_DLFCN_H) && defined(HAVE_DLADDR) // Use dladdr to get executable path if available. Dl_info DLInfo; @@ -246,7 +272,7 @@ uint32_t file_status::getLinkCount() const { ErrorOr<space_info> disk_space(const Twine &Path) { struct STATVFS Vfs; - if (::STATVFS(Path.str().c_str(), &Vfs)) + if (::STATVFS(const_cast<char *>(Path.str().c_str()), &Vfs)) return std::error_code(errno, std::generic_category()); auto FrSize = STATVFS_F_FRSIZE(Vfs); space_info SpaceInfo; @@ -398,6 +424,9 @@ static bool is_local_impl(struct STATVFS &Vfs) { #elif defined(__Fuchsia__) // Fuchsia doesn't yet support remote filesystem mounts. return true; +#elif defined(__EMSCRIPTEN__) + // Emscripten doesn't currently support remote filesystem mounts. + return true; #elif defined(__HAIKU__) // Haiku doesn't expose this information. return false; @@ -406,6 +435,40 @@ static bool is_local_impl(struct STATVFS &Vfs) { StringRef fstype(Vfs.f_basetype); // NFS is the only non-local fstype?? return !fstype.equals("nfs"); +#elif defined(_AIX) + // Call mntctl; try more than twice in case of timing issues with a concurrent + // mount. + int Ret; + size_t BufSize = 2048u; + std::unique_ptr<char[]> Buf; + int Tries = 3; + while (Tries--) { + Buf = llvm::make_unique<char[]>(BufSize); + Ret = mntctl(MCTL_QUERY, BufSize, Buf.get()); + if (Ret != 0) + break; + BufSize = *reinterpret_cast<unsigned int *>(Buf.get()); + Buf.reset(); + } + + if (Ret == -1) + // There was an error; "remote" is the conservative answer. + return false; + + // Look for the correct vmount entry. + char *CurObjPtr = Buf.get(); + while (Ret--) { + struct vmount *Vp = reinterpret_cast<struct vmount *>(CurObjPtr); + static_assert(sizeof(Vfs.f_fsid) == sizeof(Vp->vmt_fsid), + "fsid length mismatch"); + if (memcmp(&Vfs.f_fsid, &Vp->vmt_fsid, sizeof Vfs.f_fsid) == 0) + return (Vp->vmt_flags & MNT_REMOTE) == 0; + + CurObjPtr += Vp->vmt_length; + } + + // vmount entry not found; "remote" is the conservative answer. + return false; #else return !!(STATVFS_F_FLAG(Vfs) & MNT_LOCAL); #endif @@ -413,7 +476,7 @@ static bool is_local_impl(struct STATVFS &Vfs) { std::error_code is_local(const Twine &Path, bool &Result) { struct STATVFS Vfs; - if (::STATVFS(Path.str().c_str(), &Vfs)) + if (::STATVFS(const_cast<char *>(Path.str().c_str()), &Vfs)) return std::error_code(errno, std::generic_category()); Result = is_local_impl(Vfs); @@ -447,7 +510,12 @@ std::error_code resize_file(int FD, uint64_t Size) { // If we have posix_fallocate use it. Unlike ftruncate it always allocates // space, so we get an error if the disk is full. if (int Err = ::posix_fallocate(FD, 0, Size)) { - if (Err != EINVAL && Err != EOPNOTSUPP) +#ifdef _AIX + constexpr int NotSupportedError = ENOTSUP; +#else + constexpr int NotSupportedError = EOPNOTSUPP; +#endif + if (Err != EINVAL && Err != NotSupportedError) return std::error_code(Err, std::generic_category()); } #endif @@ -626,6 +694,14 @@ std::error_code status(int FD, file_status &Result) { return fillStatus(StatRet, Status, Result); } +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); + return Mask; +} + std::error_code setPermissions(const Twine &Path, perms Permissions) { SmallString<128> PathStorage; StringRef P = Path.toNullTerminatedStringRef(PathStorage); @@ -635,6 +711,12 @@ std::error_code setPermissions(const Twine &Path, perms Permissions) { return std::error_code(); } +std::error_code setPermissions(int FD, perms Permissions) { + if (::fchmod(FD, Permissions)) + return std::error_code(errno, std::generic_category()); + return std::error_code(); +} + std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime, TimePoint<> ModificationTime) { #if defined(HAVE_FUTIMENS) @@ -722,7 +804,7 @@ const char *mapped_file_region::const_data() const { } int mapped_file_region::alignment() { - return Process::getPageSize(); + return Process::getPageSizeEstimate(); } std::error_code detail::directory_iterator_construct(detail::DirIterState &it, @@ -910,9 +992,54 @@ Expected<file_t> openNativeFileForRead(const Twine &Name, OpenFlags Flags, return ResultFD; } -void closeFile(file_t &F) { - ::close(F); +file_t getStdinHandle() { return 0; } +file_t getStdoutHandle() { return 1; } +file_t getStderrHandle() { return 2; } + +std::error_code readNativeFile(file_t FD, MutableArrayRef<char> Buf, + size_t *BytesRead) { + *BytesRead = sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Buf.size()); + if (ssize_t(*BytesRead) == -1) + return std::error_code(errno, std::generic_category()); + return std::error_code(); +} + +std::error_code readNativeFileSlice(file_t FD, MutableArrayRef<char> Buf, + size_t Offset) { + char *BufPtr = Buf.data(); + size_t BytesLeft = Buf.size(); + +#ifndef HAVE_PREAD + // If we don't have pread, seek to Offset. + if (lseek(FD, Offset, SEEK_SET) == -1) + return std::error_code(errno, std::generic_category()); +#endif + + while (BytesLeft) { +#ifdef HAVE_PREAD + ssize_t NumRead = sys::RetryAfterSignal(-1, ::pread, FD, BufPtr, BytesLeft, + Buf.size() - BytesLeft + Offset); +#else + ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, BufPtr, BytesLeft); +#endif + if (NumRead == -1) { + // Error while reading. + return std::error_code(errno, std::generic_category()); + } + if (NumRead == 0) { + memset(BufPtr, 0, BytesLeft); // zero-initialize rest of the buffer. + break; + } + BytesLeft -= NumRead; + BufPtr += NumRead; + } + return std::error_code(); +} + +std::error_code closeFile(file_t &F) { + file_t TmpF = F; F = kInvalidFile; + return Process::SafelyCloseFileDescriptor(TmpF); } template <typename T> @@ -1063,5 +1190,37 @@ void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) { } // end namespace path +namespace fs { + +#ifdef __APPLE__ +/// This implementation tries to perform an APFS CoW clone of the file, +/// which can be much faster and uses less space. +/// Unfortunately fcopyfile(3) does not support COPYFILE_CLONE, so the +/// file descriptor variant of this function still uses the default +/// implementation. +std::error_code copy_file(const Twine &From, const Twine &To) { + uint32_t Flag = COPYFILE_DATA; +#if __has_builtin(__builtin_available) + if (__builtin_available(macos 10.12, *)) { + bool IsSymlink; + if (std::error_code Error = is_symlink_file(From, IsSymlink)) + return Error; + // COPYFILE_CLONE clones the symlink instead of following it + // and returns EEXISTS if the target file already exists. + if (!IsSymlink && !exists(To)) + Flag = COPYFILE_CLONE; + } +#endif + int Status = + copyfile(From.str().c_str(), To.str().c_str(), /* State */ NULL, Flag); + + if (Status == 0) + return std::error_code(); + return std::error_code(errno, std::generic_category()); +} +#endif // __APPLE__ + +} // end namespace fs + } // end namespace sys } // end namespace llvm diff --git a/contrib/llvm/lib/Support/Unix/Process.inc b/contrib/llvm/lib/Support/Unix/Process.inc index 3185f45a3a61..4115ee396582 100644 --- a/contrib/llvm/lib/Support/Unix/Process.inc +++ b/contrib/llvm/lib/Support/Unix/Process.inc @@ -1,9 +1,8 @@ //===- 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. +// 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 // //===----------------------------------------------------------------------===// // @@ -33,10 +32,7 @@ #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__) +#if defined(HAVE_MALLINFO) #include <malloc.h> #endif #if defined(HAVE_MALLCTL) @@ -73,7 +69,7 @@ static std::pair<std::chrono::microseconds, std::chrono::microseconds> getRUsage // On Cygwin, getpagesize() returns 64k(AllocationGranularity) and // offset in mmap(3) should be aligned to the AllocationGranularity. -unsigned Process::getPageSize() { +Expected<unsigned> Process::getPageSize() { #if defined(HAVE_GETPAGESIZE) static const int page_size = ::getpagesize(); #elif defined(HAVE_SYSCONF) @@ -81,6 +77,9 @@ unsigned Process::getPageSize() { #else #error Cannot get the page size on this machine #endif + if (page_size == -1) + return errorCodeToError(std::error_code(errno, std::generic_category())); + return static_cast<unsigned>(page_size); } @@ -292,7 +291,8 @@ static unsigned getColumns(int FileID) { unsigned Columns = 0; -#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H) +#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H) \ + && !(defined(_XOPEN_SOURCE) || defined(_POSIX_C_SOURCE)) // Try to determine the width of the terminal. struct winsize ws; if (ioctl(FileID, TIOCGWINSZ, &ws) == 0) diff --git a/contrib/llvm/lib/Support/Unix/Program.inc b/contrib/llvm/lib/Support/Unix/Program.inc index d0abc3763e82..c4123a64046f 100644 --- a/contrib/llvm/lib/Support/Unix/Program.inc +++ b/contrib/llvm/lib/Support/Unix/Program.inc @@ -1,9 +1,8 @@ //===- 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. +// 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 // //===----------------------------------------------------------------------===// // @@ -246,12 +245,16 @@ static bool Execute(ProcessInfo &PI, StringRef Program, 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 **>(Argv), - const_cast<char **>(Envp)); + constexpr int maxRetries = 8; + int retries = 0; + pid_t PID; + int Err; + do { + PID = 0; // Make Valgrind happy. + Err = posix_spawn(&PID, Program.str().c_str(), FileActions, + /*attrp*/ nullptr, const_cast<char **>(Argv), + const_cast<char **>(Envp)); + } while (Err == EINTR && ++retries < maxRetries); if (FileActions) posix_spawn_file_actions_destroy(FileActions); diff --git a/contrib/llvm/lib/Support/Unix/RWMutex.inc b/contrib/llvm/lib/Support/Unix/RWMutex.inc index 85a104334a27..8b47dfa0f85c 100644 --- a/contrib/llvm/lib/Support/Unix/RWMutex.inc +++ b/contrib/llvm/lib/Support/Unix/RWMutex.inc @@ -1,9 +1,8 @@ //= 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. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/contrib/llvm/lib/Support/Unix/Signals.inc b/contrib/llvm/lib/Support/Unix/Signals.inc index ad88d5e96906..634c16aa36c7 100644 --- a/contrib/llvm/lib/Support/Unix/Signals.inc +++ b/contrib/llvm/lib/Support/Unix/Signals.inc @@ -1,9 +1,8 @@ //===- 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. +// 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 // //===----------------------------------------------------------------------===// // @@ -43,6 +42,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/Program.h" +#include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/UniqueLock.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -81,10 +81,13 @@ using namespace llvm; static RETSIGTYPE SignalHandler(int Sig); // defined below. +static RETSIGTYPE InfoSignalHandler(int Sig); // defined below. +using SignalHandlerFunctionType = void (*)(); /// The function to call if ctrl-c is pressed. -using InterruptFunctionType = void (*)(); -static std::atomic<InterruptFunctionType> InterruptFunction = +static std::atomic<SignalHandlerFunctionType> InterruptFunction = + ATOMIC_VAR_INIT(nullptr); +static std::atomic<SignalHandlerFunctionType> InfoSignalFunction = ATOMIC_VAR_INIT(nullptr); namespace { @@ -200,15 +203,15 @@ struct FilesToRemoveCleanup { 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. +/// 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 + SIGHUP, SIGINT, SIGPIPE, SIGTERM, SIGUSR2 }; -// Signals that represent that we have a bug, and our prompt termination has -// been ordered. +/// 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 @@ -225,11 +228,24 @@ static const int KillSigs[] = { #endif }; +/// Signals that represent requests for status. +static const int InfoSigs[] = { + SIGUSR1 +#ifdef SIGINFO + , SIGINFO +#endif +}; + +static const size_t NumSigs = + array_lengthof(IntSigs) + array_lengthof(KillSigs) + + array_lengthof(InfoSigs); + + static std::atomic<unsigned> NumRegisteredSignals = ATOMIC_VAR_INIT(0); static struct { struct sigaction SA; int SigNo; -} RegisteredSignalInfo[array_lengthof(IntSigs) + array_lengthof(KillSigs)]; +} RegisteredSignalInfo[NumSigs]; #if defined(HAVE_SIGALTSTACK) // Hold onto both the old and new alternate signal stack so that it's not @@ -277,15 +293,24 @@ static void RegisterHandlers() { // Not signal-safe. // be able to reliably handle signals due to stack overflow. CreateSigAltStack(); - auto registerHandler = [&](int Signal) { + enum class SignalKind { IsKill, IsInfo }; + auto registerHandler = [&](int Signal, SignalKind Kind) { unsigned Index = NumRegisteredSignals.load(); assert(Index < 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; + switch (Kind) { + case SignalKind::IsKill: + NewHandler.sa_handler = SignalHandler; + NewHandler.sa_flags = SA_NODEFER | SA_RESETHAND | SA_ONSTACK; + break; + case SignalKind::IsInfo: + NewHandler.sa_handler = InfoSignalHandler; + NewHandler.sa_flags = SA_ONSTACK; + break; + } sigemptyset(&NewHandler.sa_mask); // Install the new handler, save the old one in RegisteredSignalInfo. @@ -295,9 +320,11 @@ static void RegisterHandlers() { // Not signal-safe. }; for (auto S : IntSigs) - registerHandler(S); + registerHandler(S, SignalKind::IsKill); for (auto S : KillSigs) - registerHandler(S); + registerHandler(S, SignalKind::IsKill); + for (auto S : InfoSigs) + registerHandler(S, SignalKind::IsInfo); } static void UnregisterHandlers() { @@ -357,6 +384,12 @@ static RETSIGTYPE SignalHandler(int Sig) { #endif } +static RETSIGTYPE InfoSignalHandler(int Sig) { + SaveAndRestore<int> SaveErrnoDuringASignalHandler(errno); + if (SignalHandlerFunctionType CurrentInfoFunction = InfoSignalFunction) + CurrentInfoFunction(); +} + void llvm::sys::RunInterruptHandlers() { RemoveFilesToRemove(); } @@ -366,6 +399,11 @@ void llvm::sys::SetInterruptFunction(void (*IF)()) { RegisterHandlers(); } +void llvm::sys::SetInfoSignalFunction(void (*Handler)()) { + InfoSignalFunction.exchange(Handler); + RegisterHandlers(); +} + // The public API bool llvm::sys::RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg) { @@ -540,11 +578,8 @@ void llvm::sys::PrintStackTrace(raw_ostream &OS) { 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 << format(" + %tu", (static_cast<const char*>(StackTrace[i])- + static_cast<const char*>(dlinfo.dli_saddr))); } OS << '\n'; } diff --git a/contrib/llvm/lib/Support/Unix/ThreadLocal.inc b/contrib/llvm/lib/Support/Unix/ThreadLocal.inc index a6564f0fa281..a402ae980424 100644 --- a/contrib/llvm/lib/Support/Unix/ThreadLocal.inc +++ b/contrib/llvm/lib/Support/Unix/ThreadLocal.inc @@ -1,9 +1,8 @@ //=== 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. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/contrib/llvm/lib/Support/Unix/Threading.inc b/contrib/llvm/lib/Support/Unix/Threading.inc index 92bec36d6a2d..ed9a96563055 100644 --- a/contrib/llvm/lib/Support/Unix/Threading.inc +++ b/contrib/llvm/lib/Support/Unix/Threading.inc @@ -1,9 +1,8 @@ //===- 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. +// 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 // //===----------------------------------------------------------------------===// // @@ -218,3 +217,42 @@ void llvm::get_thread_name(SmallVectorImpl<char> &Name) { #endif #endif } + +SetThreadPriorityResult llvm::set_thread_priority(ThreadPriority Priority) { +#if defined(__linux__) && defined(SCHED_IDLE) + // Some *really* old glibcs are missing SCHED_IDLE. + // http://man7.org/linux/man-pages/man3/pthread_setschedparam.3.html + // http://man7.org/linux/man-pages/man2/sched_setscheduler.2.html + sched_param priority; + // For each of the above policies, param->sched_priority must be 0. + priority.sched_priority = 0; + // SCHED_IDLE for running very low priority background jobs. + // SCHED_OTHER the standard round-robin time-sharing policy; + return !pthread_setschedparam( + pthread_self(), + Priority == ThreadPriority::Background ? SCHED_IDLE : SCHED_OTHER, + &priority) + ? SetThreadPriorityResult::SUCCESS + : SetThreadPriorityResult::FAILURE; +#elif defined(__APPLE__) + // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getpriority.2.html + // When setting a thread into background state the scheduling priority is set + // to lowest value, disk and network IO are throttled. Network IO will be + // throttled for any sockets the thread opens after going into background + // state. Any previously opened sockets are not affected. + + // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/getiopolicy_np.3.html + // I/Os with THROTTLE policy are called THROTTLE I/Os. If a THROTTLE I/O + // request occurs within a small time window (usually a fraction of a second) + // of another NORMAL I/O request, the thread that issues the THROTTLE I/O is + // forced to sleep for a certain interval. This slows down the thread that + // issues the THROTTLE I/O so that NORMAL I/Os can utilize most of the disk + // I/O bandwidth. + return !setpriority(PRIO_DARWIN_THREAD, 0, + Priority == ThreadPriority::Background ? PRIO_DARWIN_BG + : 0) + ? SetThreadPriorityResult::SUCCESS + : SetThreadPriorityResult::FAILURE; +#endif + return SetThreadPriorityResult::FAILURE; +} diff --git a/contrib/llvm/lib/Support/Unix/Unix.h b/contrib/llvm/lib/Support/Unix/Unix.h index 0c5d4de556d5..86309b0567f5 100644 --- a/contrib/llvm/lib/Support/Unix/Unix.h +++ b/contrib/llvm/lib/Support/Unix/Unix.h @@ -1,9 +1,8 @@ //===- 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. +// 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 // //===----------------------------------------------------------------------===// // @@ -19,7 +18,7 @@ //=== is guaranteed to work on all UNIX variants. //===----------------------------------------------------------------------===// -#include "llvm/Config/config.h" // Get autoconf configuration settings +#include "llvm/Config/config.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/Errno.h" #include <algorithm> diff --git a/contrib/llvm/lib/Support/Unix/Watchdog.inc b/contrib/llvm/lib/Support/Unix/Watchdog.inc index f4253391d952..b363ef779560 100644 --- a/contrib/llvm/lib/Support/Unix/Watchdog.inc +++ b/contrib/llvm/lib/Support/Unix/Watchdog.inc @@ -1,9 +1,8 @@ //===--- 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. +// 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 // //===----------------------------------------------------------------------===// // |