• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TraceBufferRingBuffer(size_t max_chunks,TraceWriter * trace_writer)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 
~TraceBufferRingBuffer()18 TraceBufferRingBuffer::~TraceBufferRingBuffer() {}
19 
AddTraceEvent(uint64_t * handle)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 
GetEventByHandle(uint64_t handle)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 nullptr;
45   auto& chunk = chunks_[chunk_index];
46   if (!chunk || chunk->seq() != chunk_seq) return nullptr;
47   return chunk->GetEventAt(event_index);
48 }
49 
Flush()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 
MakeHandle(size_t chunk_index,uint32_t chunk_seq,size_t event_index) const69 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 
ExtractHandle(uint64_t handle,size_t * chunk_index,uint32_t * chunk_seq,size_t * event_index) const76 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 
NextChunkIndex(size_t index) const85 size_t TraceBufferRingBuffer::NextChunkIndex(size_t index) const {
86   if (++index >= max_chunks_) index = 0;
87   return index;
88 }
89 
TraceBufferChunk(uint32_t seq)90 TraceBufferChunk::TraceBufferChunk(uint32_t seq) : seq_(seq) {}
91 
Reset(uint32_t new_seq)92 void TraceBufferChunk::Reset(uint32_t new_seq) {
93   next_free_ = 0;
94   seq_ = new_seq;
95 }
96 
AddTraceEvent(size_t * event_index)97 TraceObject* TraceBufferChunk::AddTraceEvent(size_t* event_index) {
98   *event_index = next_free_++;
99   return &chunk_[*event_index];
100 }
101 
CreateTraceBufferRingBuffer(size_t max_chunks,TraceWriter * trace_writer)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
110