OLD | NEW |
| (Empty) |
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 TraceBufferRingBuffer::TraceBufferRingBuffer(size_t max_chunks, | |
12 TraceWriter* trace_writer) | |
13 : max_chunks_(max_chunks) { | |
14 trace_writer_.reset(trace_writer); | |
15 chunks_.resize(max_chunks); | |
16 } | |
17 | |
18 TraceBufferRingBuffer::~TraceBufferRingBuffer() {} | |
19 | |
20 TraceObject* TraceBufferRingBuffer::AddTraceEvent(uint64_t* handle) { | |
21 base::LockGuard<base::Mutex> guard(&mutex_); | |
22 if (is_empty_ || chunks_[chunk_index_]->IsFull()) { | |
23 chunk_index_ = is_empty_ ? 0 : NextChunkIndex(chunk_index_); | |
24 is_empty_ = false; | |
25 auto& chunk = chunks_[chunk_index_]; | |
26 if (chunk) { | |
27 chunk->Reset(current_chunk_seq_++); | |
28 } else { | |
29 chunk.reset(new TraceBufferChunk(current_chunk_seq_++)); | |
30 } | |
31 } | |
32 auto& chunk = chunks_[chunk_index_]; | |
33 size_t event_index; | |
34 TraceObject* trace_object = chunk->AddTraceEvent(&event_index); | |
35 *handle = MakeHandle(chunk_index_, chunk->seq(), event_index); | |
36 return trace_object; | |
37 } | |
38 | |
39 TraceObject* TraceBufferRingBuffer::GetEventByHandle(uint64_t handle) { | |
40 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 if (chunk_index >= chunks_.size()) return NULL; | |
45 auto& chunk = chunks_[chunk_index]; | |
46 if (!chunk || chunk->seq() != chunk_seq) return NULL; | |
47 return chunk->GetEventAt(event_index); | |
48 } | |
49 | |
50 bool TraceBufferRingBuffer::Flush() { | |
51 base::LockGuard<base::Mutex> guard(&mutex_); | |
52 // This flushes all the traces stored in the buffer. | |
53 if (!is_empty_) { | |
54 for (size_t i = NextChunkIndex(chunk_index_);; i = NextChunkIndex(i)) { | |
55 if (auto& chunk = chunks_[i]) { | |
56 for (size_t j = 0; j < chunk->size(); ++j) { | |
57 trace_writer_->AppendTraceEvent(chunk->GetEventAt(j)); | |
58 } | |
59 } | |
60 if (i == chunk_index_) break; | |
61 } | |
62 } | |
63 trace_writer_->Flush(); | |
64 // This resets the trace buffer. | |
65 is_empty_ = true; | |
66 return true; | |
67 } | |
68 | |
69 uint64_t TraceBufferRingBuffer::MakeHandle(size_t chunk_index, | |
70 uint32_t chunk_seq, | |
71 size_t event_index) const { | |
72 return static_cast<uint64_t>(chunk_seq) * Capacity() + | |
73 chunk_index * TraceBufferChunk::kChunkSize + event_index; | |
74 } | |
75 | |
76 void TraceBufferRingBuffer::ExtractHandle(uint64_t handle, size_t* chunk_index, | |
77 uint32_t* chunk_seq, | |
78 size_t* event_index) const { | |
79 *chunk_seq = static_cast<uint32_t>(handle / Capacity()); | |
80 size_t indices = handle % Capacity(); | |
81 *chunk_index = indices / TraceBufferChunk::kChunkSize; | |
82 *event_index = indices % TraceBufferChunk::kChunkSize; | |
83 } | |
84 | |
85 size_t TraceBufferRingBuffer::NextChunkIndex(size_t index) const { | |
86 if (++index >= max_chunks_) index = 0; | |
87 return index; | |
88 } | |
89 | |
90 TraceBufferChunk::TraceBufferChunk(uint32_t seq) : seq_(seq) {} | |
91 | |
92 void TraceBufferChunk::Reset(uint32_t new_seq) { | |
93 next_free_ = 0; | |
94 seq_ = new_seq; | |
95 } | |
96 | |
97 TraceObject* TraceBufferChunk::AddTraceEvent(size_t* event_index) { | |
98 *event_index = next_free_++; | |
99 return &chunk_[*event_index]; | |
100 } | |
101 | |
102 TraceBuffer* TraceBuffer::CreateTraceBufferRingBuffer( | |
103 size_t max_chunks, TraceWriter* trace_writer) { | |
104 return new TraceBufferRingBuffer(max_chunks, trace_writer); | |
105 } | |
106 | |
107 } // namespace tracing | |
108 } // namespace platform | |
109 } // namespace v8 | |
OLD | NEW |