Index: compiler-rt/trunk/lib/xray/tests/unit/buffer_queue_test.cc =================================================================== --- compiler-rt/trunk/lib/xray/tests/unit/buffer_queue_test.cc +++ compiler-rt/trunk/lib/xray/tests/unit/buffer_queue_test.cc @@ -14,7 +14,6 @@ #include "gtest/gtest.h" #include -#include #include namespace __xray { @@ -32,9 +31,9 @@ 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 @@ 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 @@ BufferQueue::Buffer Buf; Buf.Buffer = reinterpret_cast(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 @@ 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 @@ 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 @@ 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); Index: compiler-rt/trunk/lib/xray/xray_buffer_queue.h =================================================================== --- compiler-rt/trunk/lib/xray/xray_buffer_queue.h +++ compiler-rt/trunk/lib/xray/xray_buffer_queue.h @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -34,11 +33,11 @@ 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 @@ std::atomic 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 @@ /// - 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 @@ /// /// 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 Index: compiler-rt/trunk/lib/xray/xray_buffer_queue.cc =================================================================== --- compiler-rt/trunk/lib/xray/xray_buffer_queue.cc +++ compiler-rt/trunk/lib/xray/xray_buffer_queue.cc @@ -13,10 +13,14 @@ // //===----------------------------------------------------------------------===// #include "xray_buffer_queue.h" -#include +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_libc.h" + #include +#include 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 @@ 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 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 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() { Index: compiler-rt/trunk/lib/xray/xray_fdr_logging_impl.h =================================================================== --- compiler-rt/trunk/lib/xray/xray_fdr_logging_impl.h +++ compiler-rt/trunk/lib/xray/xray_fdr_logging_impl.h @@ -133,9 +133,10 @@ static_cast(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 @@ 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 @@ 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 @@ if ((RecordPtr + (MetadataRecSize + FunctionRecSize)) - BufferStart < static_cast(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 @@ // 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;