1 //===-- xray_buffer_queue.cc -----------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is a part of XRay, a dynamic runtime instruementation system. 11 // 12 // Defines the interface for a buffer queue implementation. 13 // 14 //===----------------------------------------------------------------------===// 15 #include "xray_buffer_queue.h" 16 #include "sanitizer_common/sanitizer_common.h" 17 #include "sanitizer_common/sanitizer_libc.h" 18 19 #include <cstdlib> 20 #include <tuple> 21 22 using namespace __xray; 23 using namespace __sanitizer; 24 25 BufferQueue::BufferQueue(std::size_t B, std::size_t N, bool &Success) 26 : BufferSize(B), Buffers(N), Mutex(), OwnedBuffers(), Finalizing{0} { 27 for (auto &T : Buffers) { 28 void *Tmp = malloc(BufferSize); 29 if (Tmp == nullptr) { 30 Success = false; 31 return; 32 } 33 34 auto &Buf = std::get<0>(T); 35 Buf.Buffer = Tmp; 36 Buf.Size = B; 37 OwnedBuffers.emplace(Tmp); 38 } 39 Success = true; 40 } 41 42 BufferQueue::ErrorCode BufferQueue::getBuffer(Buffer &Buf) { 43 if (__sanitizer::atomic_load(&Finalizing, __sanitizer::memory_order_acquire)) 44 return ErrorCode::QueueFinalizing; 45 __sanitizer::BlockingMutexLock Guard(&Mutex); 46 if (Buffers.empty()) 47 return ErrorCode::NotEnoughMemory; 48 auto &T = Buffers.front(); 49 auto &B = std::get<0>(T); 50 Buf = B; 51 B.Buffer = nullptr; 52 B.Size = 0; 53 Buffers.pop_front(); 54 return ErrorCode::Ok; 55 } 56 57 BufferQueue::ErrorCode BufferQueue::releaseBuffer(Buffer &Buf) { 58 if (OwnedBuffers.count(Buf.Buffer) == 0) 59 return ErrorCode::UnrecognizedBuffer; 60 __sanitizer::BlockingMutexLock Guard(&Mutex); 61 62 // Now that the buffer has been released, we mark it as "used". 63 Buffers.emplace(Buffers.end(), Buf, true /* used */); 64 Buf.Buffer = nullptr; 65 Buf.Size = 0; 66 return ErrorCode::Ok; 67 } 68 69 BufferQueue::ErrorCode BufferQueue::finalize() { 70 if (__sanitizer::atomic_exchange(&Finalizing, 1, 71 __sanitizer::memory_order_acq_rel)) 72 return ErrorCode::QueueFinalizing; 73 return ErrorCode::Ok; 74 } 75 76 BufferQueue::~BufferQueue() { 77 for (auto &T : Buffers) { 78 auto &Buf = std::get<0>(T); 79 free(Buf.Buffer); 80 } 81 } 82