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; |