Line data Source code
1 : // Copyright 2016 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/libplatform/tracing/trace-buffer.h"
6 :
7 : namespace v8 {
8 : namespace platform {
9 : namespace tracing {
10 :
11 41 : TraceBufferRingBuffer::TraceBufferRingBuffer(size_t max_chunks,
12 : TraceWriter* trace_writer)
13 82 : : max_chunks_(max_chunks) {
14 : trace_writer_.reset(trace_writer);
15 41 : chunks_.resize(max_chunks);
16 41 : }
17 :
18 164 : TraceBufferRingBuffer::~TraceBufferRingBuffer() {}
19 :
20 1091 : TraceObject* TraceBufferRingBuffer::AddTraceEvent(uint64_t* handle) {
21 1091 : base::LockGuard<base::Mutex> guard(&mutex_);
22 3287 : if (is_empty_ || chunks_[chunk_index_]->IsFull()) {
23 82 : chunk_index_ = is_empty_ ? 0 : NextChunkIndex(chunk_index_);
24 41 : is_empty_ = false;
25 : auto& chunk = chunks_[chunk_index_];
26 41 : if (chunk) {
27 7 : chunk->Reset(current_chunk_seq_++);
28 : } else {
29 34 : chunk.reset(new TraceBufferChunk(current_chunk_seq_++));
30 : }
31 : }
32 1091 : auto& chunk = chunks_[chunk_index_];
33 : size_t event_index;
34 : TraceObject* trace_object = chunk->AddTraceEvent(&event_index);
35 2182 : *handle = MakeHandle(chunk_index_, chunk->seq(), event_index);
36 2182 : return trace_object;
37 : }
38 :
39 1806 : TraceObject* TraceBufferRingBuffer::GetEventByHandle(uint64_t handle) {
40 1806 : base::LockGuard<base::Mutex> guard(&mutex_);
41 : size_t chunk_index, event_index;
42 : uint32_t chunk_seq;
43 : ExtractHandle(handle, &chunk_index, &chunk_seq, &event_index);
44 3612 : if (chunk_index >= chunks_.size()) return NULL;
45 : auto& chunk = chunks_[chunk_index];
46 1806 : if (!chunk || chunk->seq() != chunk_seq) return NULL;
47 1358 : return chunk->GetEventAt(event_index);
48 : }
49 :
50 48 : bool TraceBufferRingBuffer::Flush() {
51 48 : base::LockGuard<base::Mutex> guard(&mutex_);
52 : // This flushes all the traces stored in the buffer.
53 48 : if (!is_empty_) {
54 27 : for (size_t i = NextChunkIndex(chunk_index_);; i = NextChunkIndex(i)) {
55 68 : if (auto& chunk = chunks_[i]) {
56 1320 : for (size_t j = 0; j < chunk->size(); ++j) {
57 643 : trace_writer_->AppendTraceEvent(chunk->GetEventAt(j));
58 : }
59 : }
60 34 : if (i == chunk_index_) break;
61 : }
62 : }
63 48 : trace_writer_->Flush();
64 : // This resets the trace buffer.
65 48 : is_empty_ = true;
66 48 : return true;
67 : }
68 :
69 0 : uint64_t TraceBufferRingBuffer::MakeHandle(size_t chunk_index,
70 : uint32_t chunk_seq,
71 1091 : size_t event_index) const {
72 3273 : return static_cast<uint64_t>(chunk_seq) * Capacity() +
73 2182 : chunk_index * TraceBufferChunk::kChunkSize + event_index;
74 : }
75 :
76 0 : void TraceBufferRingBuffer::ExtractHandle(uint64_t handle, size_t* chunk_index,
77 : uint32_t* chunk_seq,
78 1806 : size_t* event_index) const {
79 1806 : *chunk_seq = static_cast<uint32_t>(handle / Capacity());
80 1806 : size_t indices = handle % Capacity();
81 1806 : *chunk_index = indices / TraceBufferChunk::kChunkSize;
82 1806 : *event_index = indices % TraceBufferChunk::kChunkSize;
83 0 : }
84 :
85 0 : size_t TraceBufferRingBuffer::NextChunkIndex(size_t index) const {
86 48 : if (++index >= max_chunks_) index = 0;
87 0 : return index;
88 : }
89 :
90 2210 : TraceBufferChunk::TraceBufferChunk(uint32_t seq) : seq_(seq) {}
91 :
92 0 : void TraceBufferChunk::Reset(uint32_t new_seq) {
93 7 : next_free_ = 0;
94 7 : seq_ = new_seq;
95 0 : }
96 :
97 0 : TraceObject* TraceBufferChunk::AddTraceEvent(size_t* event_index) {
98 1091 : *event_index = next_free_++;
99 0 : return &chunk_[*event_index];
100 : }
101 :
102 41 : TraceBuffer* TraceBuffer::CreateTraceBufferRingBuffer(
103 : size_t max_chunks, TraceWriter* trace_writer) {
104 41 : return new TraceBufferRingBuffer(max_chunks, trace_writer);
105 : }
106 :
107 : } // namespace tracing
108 : } // namespace platform
109 : } // namespace v8
|