From: Daniel Dunbar Date: Thu, 3 Feb 2011 03:32:32 +0000 (+0000) Subject: raw_fd_ostream: Add a SetUseAtomicWrites() method (uses writev). X-Git-Tag: android-x86-6.0-r1~1002^2~758 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=b0cfa6cab85ce19c8ecaf9cdd3e34a3593d0b001;p=android-x86%2Fexternal-llvm.git raw_fd_ostream: Add a SetUseAtomicWrites() method (uses writev). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@124771 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index 95904ea2f31..6bfae5e2982 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -301,6 +301,10 @@ class raw_fd_ostream : public raw_ostream { /// bool Error; + /// Controls whether the stream should attempt to use atomic writes, when + /// possible. + bool UseAtomicWrites; + uint64_t pos; /// write_impl - See raw_ostream::write_impl. @@ -361,6 +365,16 @@ public: /// position to the offset specified from the beginning of the file. uint64_t seek(uint64_t off); + /// SetUseAtomicWrite - Set the stream to attempt to use atomic writes for + /// individual output routines where possible. + /// + /// Note that because raw_ostream's are typically buffered, this flag is only + /// sensible when used on unbuffered streams which will flush their output + /// immediately. + void SetUseAtomicWrites(bool Value) { + UseAtomicWrites = Value; + } + virtual raw_ostream &changeColor(enum Colors colors, bool bold=false, bool bg=false); virtual raw_ostream &resetColor(); diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp index e7d75e71286..80ea7407b44 100644 --- a/lib/Support/raw_ostream.cpp +++ b/lib/Support/raw_ostream.cpp @@ -32,6 +32,9 @@ #if defined(HAVE_FCNTL_H) # include #endif +#if defined(HAVE_SYS_UIO_H) && defined(HAVE_WRITEV) +# include +#endif #if defined(__CYGWIN__) #include @@ -375,7 +378,9 @@ void format_object_base::home() { /// stream should be immediately destroyed; the string will be empty /// if no error occurred. raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo, - unsigned Flags) : Error(false), pos(0) { + unsigned Flags) + : Error(false), UseAtomicWrites(false), pos(0) +{ assert(Filename != 0 && "Filename is null"); // Verify that we don't have both "append" and "excl". assert((!(Flags & F_Excl) || !(Flags & F_Append)) && @@ -426,7 +431,7 @@ raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo, /// ShouldClose is true, this closes the file when the stream is destroyed. raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered) : raw_ostream(unbuffered), FD(fd), - ShouldClose(shouldClose), Error(false) { + ShouldClose(shouldClose), Error(false), UseAtomicWrites(false) { #ifdef O_BINARY // Setting STDOUT and STDERR to binary mode is necessary in Win32 // to avoid undesirable linefeed conversion. @@ -467,7 +472,20 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) { pos += Size; do { - ssize_t ret = ::write(FD, Ptr, Size); + ssize_t ret; + + // Check whether we should attempt to use atomic writes. + if (BUILTIN_EXPECT(!UseAtomicWrites, true)) { + ret = ::write(FD, Ptr, Size); + } else { + // Use ::writev() where available. +#if defined(HAVE_WRITEV) + struct iovec IOV = { (void*) Ptr, Size }; + ret = ::writev(FD, &IOV, 1); +#else + ret = ::write(FD, Ptr, Size); +#endif + } if (ret < 0) { // If it's a recoverable error, swallow it and retry the write.