aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/Support/Unix
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Support/Unix')
-rw-r--r--contrib/llvm/lib/Support/Unix/COM.inc7
-rw-r--r--contrib/llvm/lib/Support/Unix/DynamicLibrary.inc7
-rw-r--r--contrib/llvm/lib/Support/Unix/Host.inc24
-rw-r--r--contrib/llvm/lib/Support/Unix/Memory.inc81
-rw-r--r--contrib/llvm/lib/Support/Unix/Mutex.inc7
-rw-r--r--contrib/llvm/lib/Support/Unix/Path.inc219
-rw-r--r--contrib/llvm/lib/Support/Unix/Process.inc20
-rw-r--r--contrib/llvm/lib/Support/Unix/Program.inc23
-rw-r--r--contrib/llvm/lib/Support/Unix/RWMutex.inc7
-rw-r--r--contrib/llvm/lib/Support/Unix/Signals.inc81
-rw-r--r--contrib/llvm/lib/Support/Unix/ThreadLocal.inc7
-rw-r--r--contrib/llvm/lib/Support/Unix/Threading.inc46
-rw-r--r--contrib/llvm/lib/Support/Unix/Unix.h9
-rw-r--r--contrib/llvm/lib/Support/Unix/Watchdog.inc7
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
//
//===----------------------------------------------------------------------===//
//