]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/xray/xray_buffer_queue.cc
Merge compiler-rt trunk r300890, and update build glue.
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / xray / xray_buffer_queue.cc
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 }