diff options
| -rw-r--r-- | compiler-rt/lib/xray/tests/unit/buffer_queue_test.cc | 35 | ||||
| -rw-r--r-- | compiler-rt/lib/xray/xray_buffer_queue.cc | 26 | ||||
| -rw-r--r-- | compiler-rt/lib/xray/xray_buffer_queue.h | 37 | ||||
| -rw-r--r-- | compiler-rt/lib/xray/xray_fdr_logging_impl.h | 34 | 
4 files changed, 84 insertions, 48 deletions
diff --git a/compiler-rt/lib/xray/tests/unit/buffer_queue_test.cc b/compiler-rt/lib/xray/tests/unit/buffer_queue_test.cc index 4db762dc72c..ac89a8dbc50 100644 --- a/compiler-rt/lib/xray/tests/unit/buffer_queue_test.cc +++ b/compiler-rt/lib/xray/tests/unit/buffer_queue_test.cc @@ -14,7 +14,6 @@  #include "gtest/gtest.h"  #include <future> -#include <system_error>  #include <unistd.h>  namespace __xray { @@ -32,9 +31,9 @@ TEST(BufferQueueTest, GetAndRelease) {    BufferQueue Buffers(kSize, 1, Success);    ASSERT_TRUE(Success);    BufferQueue::Buffer Buf; -  ASSERT_EQ(Buffers.getBuffer(Buf), std::error_code()); +  ASSERT_EQ(Buffers.getBuffer(Buf), BufferQueue::ErrorCode::Ok);    ASSERT_NE(nullptr, Buf.Buffer); -  ASSERT_EQ(Buffers.releaseBuffer(Buf), std::error_code()); +  ASSERT_EQ(Buffers.releaseBuffer(Buf), BufferQueue::ErrorCode::Ok);    ASSERT_EQ(nullptr, Buf.Buffer);  } @@ -43,11 +42,10 @@ TEST(BufferQueueTest, GetUntilFailed) {    BufferQueue Buffers(kSize, 1, Success);    ASSERT_TRUE(Success);    BufferQueue::Buffer Buf0; -  EXPECT_EQ(Buffers.getBuffer(Buf0), std::error_code()); +  EXPECT_EQ(Buffers.getBuffer(Buf0), BufferQueue::ErrorCode::Ok);    BufferQueue::Buffer Buf1; -  EXPECT_EQ(std::make_error_code(std::errc::not_enough_memory), -            Buffers.getBuffer(Buf1)); -  EXPECT_EQ(Buffers.releaseBuffer(Buf0), std::error_code()); +  EXPECT_EQ(BufferQueue::ErrorCode::NotEnoughMemory, Buffers.getBuffer(Buf1)); +  EXPECT_EQ(Buffers.releaseBuffer(Buf0), BufferQueue::ErrorCode::Ok);  }  TEST(BufferQueueTest, ReleaseUnknown) { @@ -57,7 +55,7 @@ TEST(BufferQueueTest, ReleaseUnknown) {    BufferQueue::Buffer Buf;    Buf.Buffer = reinterpret_cast<void *>(0xdeadbeef);    Buf.Size = kSize; -  EXPECT_EQ(std::make_error_code(std::errc::argument_out_of_domain), +  EXPECT_EQ(BufferQueue::ErrorCode::UnrecognizedBuffer,              Buffers.releaseBuffer(Buf));  } @@ -66,15 +64,15 @@ TEST(BufferQueueTest, ErrorsWhenFinalising) {    BufferQueue Buffers(kSize, 2, Success);    ASSERT_TRUE(Success);    BufferQueue::Buffer Buf; -  ASSERT_EQ(Buffers.getBuffer(Buf), std::error_code()); +  ASSERT_EQ(Buffers.getBuffer(Buf), BufferQueue::ErrorCode::Ok);    ASSERT_NE(nullptr, Buf.Buffer); -  ASSERT_EQ(Buffers.finalize(), std::error_code()); +  ASSERT_EQ(Buffers.finalize(), BufferQueue::ErrorCode::Ok);    BufferQueue::Buffer OtherBuf; -  ASSERT_EQ(std::make_error_code(std::errc::state_not_recoverable), +  ASSERT_EQ(BufferQueue::ErrorCode::AlreadyFinalized,              Buffers.getBuffer(OtherBuf)); -  ASSERT_EQ(std::make_error_code(std::errc::state_not_recoverable), +  ASSERT_EQ(BufferQueue::ErrorCode::AlreadyFinalized,              Buffers.finalize()); -  ASSERT_EQ(Buffers.releaseBuffer(Buf), std::error_code()); +  ASSERT_EQ(Buffers.releaseBuffer(Buf), BufferQueue::ErrorCode::Ok);  }  TEST(BufferQueueTest, MultiThreaded) { @@ -83,14 +81,17 @@ TEST(BufferQueueTest, MultiThreaded) {    ASSERT_TRUE(Success);    auto F = [&] {      BufferQueue::Buffer B; -    while (!Buffers.getBuffer(B)) { +    while (true) { +      auto EC = Buffers.getBuffer(B); +      if (EC != BufferQueue::ErrorCode::Ok) +        return;        Buffers.releaseBuffer(B);      }    };    auto T0 = std::async(std::launch::async, F);    auto T1 = std::async(std::launch::async, F);    auto T2 = std::async(std::launch::async, [&] { -    while (!Buffers.finalize()) +    while (Buffers.finalize() != BufferQueue::ErrorCode::Ok)        ;    });    F(); @@ -103,8 +104,8 @@ TEST(BufferQueueTest, Apply) {    auto Count = 0;    BufferQueue::Buffer B;    for (int I = 0; I < 10; ++I) { -    ASSERT_FALSE(Buffers.getBuffer(B)); -    ASSERT_FALSE(Buffers.releaseBuffer(B)); +    ASSERT_EQ(Buffers.getBuffer(B), BufferQueue::ErrorCode::Ok); +    ASSERT_EQ(Buffers.releaseBuffer(B), BufferQueue::ErrorCode::Ok);    }    Buffers.apply([&](const BufferQueue::Buffer &B) { ++Count; });    ASSERT_EQ(Count, 10); diff --git a/compiler-rt/lib/xray/xray_buffer_queue.cc b/compiler-rt/lib/xray/xray_buffer_queue.cc index bd8f4961e7a..13d17537edf 100644 --- a/compiler-rt/lib/xray/xray_buffer_queue.cc +++ b/compiler-rt/lib/xray/xray_buffer_queue.cc @@ -13,10 +13,14 @@  //  //===----------------------------------------------------------------------===//  #include "xray_buffer_queue.h" -#include <cassert> +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_libc.h" +  #include <cstdlib> +#include <tuple>  using namespace __xray; +using namespace __sanitizer;  BufferQueue::BufferQueue(std::size_t B, std::size_t N, bool &Success)      : BufferSize(B), Buffers(N), Mutex(), OwnedBuffers(), Finalizing(false) { @@ -35,37 +39,37 @@ BufferQueue::BufferQueue(std::size_t B, std::size_t N, bool &Success)    Success = true;  } -std::error_code BufferQueue::getBuffer(Buffer &Buf) { +BufferQueue::ErrorCode BufferQueue::getBuffer(Buffer &Buf) {    if (Finalizing.load(std::memory_order_acquire)) -    return std::make_error_code(std::errc::state_not_recoverable); +    return ErrorCode::QueueFinalizing;    std::lock_guard<std::mutex> Guard(Mutex);    if (Buffers.empty()) -    return std::make_error_code(std::errc::not_enough_memory); +    return ErrorCode::NotEnoughMemory;    auto &T = Buffers.front();    auto &B = std::get<0>(T);    Buf = B;    B.Buffer = nullptr;    B.Size = 0;    Buffers.pop_front(); -  return {}; +  return ErrorCode::Ok;  } -std::error_code BufferQueue::releaseBuffer(Buffer &Buf) { +BufferQueue::ErrorCode BufferQueue::releaseBuffer(Buffer &Buf) {    if (OwnedBuffers.count(Buf.Buffer) == 0) -    return std::make_error_code(std::errc::argument_out_of_domain); +    return ErrorCode::UnrecognizedBuffer;    std::lock_guard<std::mutex> Guard(Mutex);    // Now that the buffer has been released, we mark it as "used".    Buffers.emplace(Buffers.end(), Buf, true /* used */);    Buf.Buffer = nullptr;    Buf.Size = 0; -  return {}; +  return ErrorCode::Ok;  } -std::error_code BufferQueue::finalize() { +BufferQueue::ErrorCode BufferQueue::finalize() {    if (Finalizing.exchange(true, std::memory_order_acq_rel)) -    return std::make_error_code(std::errc::state_not_recoverable); -  return {}; +    return ErrorCode::QueueFinalizing; +  return ErrorCode::Ok;  }  BufferQueue::~BufferQueue() { diff --git a/compiler-rt/lib/xray/xray_buffer_queue.h b/compiler-rt/lib/xray/xray_buffer_queue.h index 3898437e4ba..32f7ae96726 100644 --- a/compiler-rt/lib/xray/xray_buffer_queue.h +++ b/compiler-rt/lib/xray/xray_buffer_queue.h @@ -19,7 +19,6 @@  #include <cstdint>  #include <deque>  #include <mutex> -#include <system_error>  #include <unordered_set>  #include <utility> @@ -34,11 +33,11 @@ class BufferQueue {  public:    struct Buffer {      void *Buffer = nullptr; -    std::size_t Size = 0; +    size_t Size = 0;    };  private: -  std::size_t BufferSize; +  size_t BufferSize;    // We use a bool to indicate whether the Buffer has been used in this    // freelist implementation. @@ -48,9 +47,33 @@ private:    std::atomic<bool> Finalizing;  public: +  enum class ErrorCode : unsigned { +    Ok, +    NotEnoughMemory, +    QueueFinalizing, +    UnrecognizedBuffer, +    AlreadyFinalized, +  }; + +  static const char *getErrorString(ErrorCode E) { +    switch (E) { +    case ErrorCode::Ok: +      return "(none)"; +    case ErrorCode::NotEnoughMemory: +      return "no available buffers in the queue"; +    case ErrorCode::QueueFinalizing: +      return "queue already finalizing"; +    case ErrorCode::UnrecognizedBuffer: +      return "buffer being returned not owned by buffer queue"; +    case ErrorCode::AlreadyFinalized: +      return "queue already finalized"; +    } +    return "unknown error"; +  } +    /// Initialise a queue of size |N| with buffers of size |B|. We report success    /// through |Success|. -  BufferQueue(std::size_t B, std::size_t N, bool &Success); +  BufferQueue(size_t B, size_t N, bool &Success);    /// Updates |Buf| to contain the pointer to an appropriate buffer. Returns an    /// error in case there are no available buffers to return when we will run @@ -63,13 +86,13 @@ public:    ///   - std::errc::not_enough_memory on exceeding MaxSize.    ///   - no error when we find a Buffer.    ///   - std::errc::state_not_recoverable on finalising BufferQueue. -  std::error_code getBuffer(Buffer &Buf); +  ErrorCode getBuffer(Buffer &Buf);    /// Updates |Buf| to point to nullptr, with size 0.    ///    /// Returns:    ///   - ... -  std::error_code releaseBuffer(Buffer &Buf); +  ErrorCode releaseBuffer(Buffer &Buf);    bool finalizing() const { return Finalizing.load(std::memory_order_acquire); } @@ -80,7 +103,7 @@ public:    ///    /// After a call to finalize succeeds, all subsequent calls to finalize will    /// fail with std::errc::state_not_recoverable. -  std::error_code finalize(); +  ErrorCode finalize();    /// Applies the provided function F to each Buffer in the queue, only if the    /// Buffer is marked 'used' (i.e. has been the result of getBuffer(...) and a diff --git a/compiler-rt/lib/xray/xray_fdr_logging_impl.h b/compiler-rt/lib/xray/xray_fdr_logging_impl.h index 94e446bfc41..d65c0f4f415 100644 --- a/compiler-rt/lib/xray/xray_fdr_logging_impl.h +++ b/compiler-rt/lib/xray/xray_fdr_logging_impl.h @@ -133,9 +133,10 @@ public:             static_cast<ptrdiff_t>(MetadataRecSize));      if (auto BQ = Buffers.lock()) {        writeEOBMetadata(); -      if (auto EC = BQ->releaseBuffer(Buffer)) +      auto EC = BQ->releaseBuffer(Buffer); +      if (EC != BufferQueue::ErrorCode::Ok)          Report("Failed to release buffer at %p; error=%s\n", Buffer.Buffer, -               EC.message().c_str()); +               BufferQueue::getErrorString(EC));        return;      }    } @@ -170,7 +171,7 @@ static inline bool loggingInitialized(           XRayLogInitStatus::XRAY_LOG_INITIALIZED;  } -} // namespace anonymous +} // namespace  static inline void writeNewBufferPreamble(pid_t Tid, timespec TS,                                            char *&MemPtr) XRAY_NEVER_INSTRUMENT { @@ -339,20 +340,23 @@ static inline void processFunctionHook(    if (!loggingInitialized(LoggingStatus) || LocalBQ->finalizing()) {      writeEOBMetadata(); -    if (auto EC = BQ->releaseBuffer(Buffer)) { +    auto EC = BQ->releaseBuffer(Buffer); +    if (EC != BufferQueue::ErrorCode::Ok) {        Report("Failed to release buffer at %p; error=%s\n", Buffer.Buffer, -             EC.message().c_str()); +             BufferQueue::getErrorString(EC));        return;      }      RecordPtr = nullptr;    }    if (Buffer.Buffer == nullptr) { -    if (auto EC = LocalBQ->getBuffer(Buffer)) { +    auto EC = LocalBQ->getBuffer(Buffer); +    if (EC != BufferQueue::ErrorCode::Ok) {        auto LS = LoggingStatus.load(std::memory_order_acquire);        if (LS != XRayLogInitStatus::XRAY_LOG_FINALIZING &&            LS != XRayLogInitStatus::XRAY_LOG_FINALIZED) -        Report("Failed to acquire a buffer; error=%s\n", EC.message().c_str()); +        Report("Failed to acquire a buffer; error=%s\n", +               BufferQueue::getErrorString(EC));        return;      } @@ -406,13 +410,16 @@ static inline void processFunctionHook(    if ((RecordPtr + (MetadataRecSize + FunctionRecSize)) - BufferStart <        static_cast<ptrdiff_t>(MetadataRecSize)) {      writeEOBMetadata(); -    if (auto EC = LocalBQ->releaseBuffer(Buffer)) { +    auto EC = LocalBQ->releaseBuffer(Buffer); +    if (EC != BufferQueue::ErrorCode::Ok) {        Report("Failed to release buffer at %p; error=%s\n", Buffer.Buffer, -             EC.message().c_str()); +             BufferQueue::getErrorString(EC));        return;      } -    if (auto EC = LocalBQ->getBuffer(Buffer)) { -      Report("Failed to acquire a buffer; error=%s\n", EC.message().c_str()); +    EC = LocalBQ->getBuffer(Buffer); +    if (EC != BufferQueue::ErrorCode::Ok) { +      Report("Failed to acquire a buffer; error=%s\n", +             BufferQueue::getErrorString(EC));        return;      }      setupNewBuffer(Buffer, wall_clock_reader); @@ -471,9 +478,10 @@ static inline void processFunctionHook(    // make sure that other threads may start using this buffer.    if ((RecordPtr + MetadataRecSize) - BufferStart == MetadataRecSize) {      writeEOBMetadata(); -    if (auto EC = LocalBQ->releaseBuffer(Buffer)) { +    auto EC = LocalBQ->releaseBuffer(Buffer); +    if (EC != BufferQueue::ErrorCode::Ok) {        Report("Failed releasing buffer at %p; error=%s\n", Buffer.Buffer, -             EC.message().c_str()); +             BufferQueue::getErrorString(EC));        return;      }      RecordPtr = nullptr;  | 

