1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/trace_processor/tp_metatrace.h"
18 
19 namespace perfetto {
20 namespace trace_processor {
21 namespace metatrace {
22 
23 bool g_enabled = false;
24 
Enable()25 void Enable() {
26   g_enabled = true;
27 }
28 
DisableAndReadBuffer(std::function<void (Record *)> fn)29 void DisableAndReadBuffer(std::function<void(Record*)> fn) {
30   g_enabled = false;
31   if (!fn)
32     return;
33   RingBuffer::GetInstance()->ReadAll(fn);
34 }
35 
RingBuffer()36 RingBuffer::RingBuffer() {
37   static_assert((kCapacity & (kCapacity - 1)) == 0,
38                 "Capacity should be a power of 2");
39 }
40 
ReadAll(std::function<void (Record *)> fn)41 void RingBuffer::ReadAll(std::function<void(Record*)> fn) {
42   // Mark as reading so we don't get reentrancy in obtaining new
43   // trace events.
44   is_reading_ = true;
45 
46   uint64_t start = (write_idx_ - start_idx_) < kCapacity
47                        ? start_idx_
48                        : write_idx_ - kCapacity;
49   uint64_t end = write_idx_;
50 
51   // Increment the write index by kCapacity + 1. This ensures that if
52   // ScopedEntry is destoryed in |fn| below, we won't get overwrites
53   // while reading the buffer.
54   // This works because of the logic in ~ScopedEntry and
55   // RingBuffer::HasOverwritten which ensures that we don't overwrite entries
56   // more than kCapcity elements in the past.
57   write_idx_ += kCapacity + 1;
58 
59   for (uint64_t i = start; i < end; ++i) {
60     Record* record = At(i);
61 
62     // If the slice was unfinished for some reason, don't emit it.
63     if (record->duration_ns != 0) {
64       fn(record);
65     }
66   }
67 
68   // Ensure that the start pointer is updated to the write pointer.
69   start_idx_ = write_idx_;
70 
71   // Remove the reading marker.
72   is_reading_ = false;
73 }
74 
75 }  // namespace metatrace
76 }  // namespace trace_processor
77 }  // namespace perfetto
78