xref: /aosp_15_r20/external/perfetto/src/tracing/service/trace_buffer.h (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker  *
4*6dbdd20aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker  *
8*6dbdd20aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker  *
10*6dbdd20aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker  * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker  */
16*6dbdd20aSAndroid Build Coastguard Worker 
17*6dbdd20aSAndroid Build Coastguard Worker #ifndef SRC_TRACING_SERVICE_TRACE_BUFFER_H_
18*6dbdd20aSAndroid Build Coastguard Worker #define SRC_TRACING_SERVICE_TRACE_BUFFER_H_
19*6dbdd20aSAndroid Build Coastguard Worker 
20*6dbdd20aSAndroid Build Coastguard Worker #include <stdint.h>
21*6dbdd20aSAndroid Build Coastguard Worker #include <string.h>
22*6dbdd20aSAndroid Build Coastguard Worker 
23*6dbdd20aSAndroid Build Coastguard Worker #include <array>
24*6dbdd20aSAndroid Build Coastguard Worker #include <limits>
25*6dbdd20aSAndroid Build Coastguard Worker #include <map>
26*6dbdd20aSAndroid Build Coastguard Worker #include <tuple>
27*6dbdd20aSAndroid Build Coastguard Worker 
28*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h"
29*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/flat_hash_map.h"
30*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/paged_memory.h"
31*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/thread_annotations.h"
32*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/utils.h"
33*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/tracing/core/basic_types.h"
34*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/tracing/core/client_identity.h"
35*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/tracing/core/slice.h"
36*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/tracing/core/trace_stats.h"
37*6dbdd20aSAndroid Build Coastguard Worker #include "src/tracing/service/histogram.h"
38*6dbdd20aSAndroid Build Coastguard Worker 
39*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
40*6dbdd20aSAndroid Build Coastguard Worker 
41*6dbdd20aSAndroid Build Coastguard Worker class TracePacket;
42*6dbdd20aSAndroid Build Coastguard Worker 
43*6dbdd20aSAndroid Build Coastguard Worker // The main buffer, owned by the tracing service, where all the trace data is
44*6dbdd20aSAndroid Build Coastguard Worker // ultimately stored into. The service will own several instances of this class,
45*6dbdd20aSAndroid Build Coastguard Worker // at least one per active consumer (as defined in the |buffers| section of
46*6dbdd20aSAndroid Build Coastguard Worker // trace_config.proto) and will copy chunks from the producer's shared memory
47*6dbdd20aSAndroid Build Coastguard Worker // buffers into here when a CommitData IPC is received.
48*6dbdd20aSAndroid Build Coastguard Worker //
49*6dbdd20aSAndroid Build Coastguard Worker // Writing into the buffer
50*6dbdd20aSAndroid Build Coastguard Worker // -----------------------
51*6dbdd20aSAndroid Build Coastguard Worker // Data is copied from the SMB(s) using CopyChunkUntrusted(). The buffer will
52*6dbdd20aSAndroid Build Coastguard Worker // hence contain data coming from different producers and different writer
53*6dbdd20aSAndroid Build Coastguard Worker // sequences, more specifically:
54*6dbdd20aSAndroid Build Coastguard Worker // - The service receives data by several producer(s), identified by their ID.
55*6dbdd20aSAndroid Build Coastguard Worker // - Each producer writes several sequences identified by the same WriterID.
56*6dbdd20aSAndroid Build Coastguard Worker //   (they correspond to TraceWriter instances in the producer).
57*6dbdd20aSAndroid Build Coastguard Worker // - Each Writer writes, in order, several chunks.
58*6dbdd20aSAndroid Build Coastguard Worker // - Each chunk contains zero, one, or more TracePacket(s), or even just
59*6dbdd20aSAndroid Build Coastguard Worker //   fragments of packets (when they span across several chunks).
60*6dbdd20aSAndroid Build Coastguard Worker //
61*6dbdd20aSAndroid Build Coastguard Worker // So at any point in time, the buffer will contain a variable number of logical
62*6dbdd20aSAndroid Build Coastguard Worker // sequences identified by the {ProducerID, WriterID} tuple. Any given chunk
63*6dbdd20aSAndroid Build Coastguard Worker // will only contain packets (or fragments) belonging to the same sequence.
64*6dbdd20aSAndroid Build Coastguard Worker //
65*6dbdd20aSAndroid Build Coastguard Worker // The buffer operates by default as a ring buffer.
66*6dbdd20aSAndroid Build Coastguard Worker // It has two overwrite policies:
67*6dbdd20aSAndroid Build Coastguard Worker //  1. kOverwrite (default): if the write pointer reaches the read pointer, old
68*6dbdd20aSAndroid Build Coastguard Worker //     unread chunks will be overwritten by new chunks.
69*6dbdd20aSAndroid Build Coastguard Worker //  2. kDiscard: if the write pointer reaches the read pointer, unread chunks
70*6dbdd20aSAndroid Build Coastguard Worker //     are preserved and the new chunks are discarded. Any future write becomes
71*6dbdd20aSAndroid Build Coastguard Worker //     a no-op, even if the reader manages to fully catch up. This is because
72*6dbdd20aSAndroid Build Coastguard Worker //     once a chunk is discarded, the sequence of packets is broken and trying
73*6dbdd20aSAndroid Build Coastguard Worker //     to recover would be too hard (also due to the fact that, at the same
74*6dbdd20aSAndroid Build Coastguard Worker //     time, we allow out-of-order commits and chunk re-writes).
75*6dbdd20aSAndroid Build Coastguard Worker //
76*6dbdd20aSAndroid Build Coastguard Worker // Chunks are (over)written in the same order of the CopyChunkUntrusted() calls.
77*6dbdd20aSAndroid Build Coastguard Worker // When overwriting old content, entire chunks are overwritten or clobbered.
78*6dbdd20aSAndroid Build Coastguard Worker // The buffer never leaves a partial chunk around. Chunks' payload is copied
79*6dbdd20aSAndroid Build Coastguard Worker // as-is, but their header is not and is repacked in order to keep the
80*6dbdd20aSAndroid Build Coastguard Worker // ProducerID around.
81*6dbdd20aSAndroid Build Coastguard Worker //
82*6dbdd20aSAndroid Build Coastguard Worker // Chunks are stored in the buffer next to each other. Each chunk is prefixed by
83*6dbdd20aSAndroid Build Coastguard Worker // an inline header (ChunkRecord), which contains most of the fields of the
84*6dbdd20aSAndroid Build Coastguard Worker // SharedMemoryABI ChunkHeader + the ProducerID + the size of the payload.
85*6dbdd20aSAndroid Build Coastguard Worker // It's a conventional binary object stream essentially, where each ChunkRecord
86*6dbdd20aSAndroid Build Coastguard Worker // tells where it ends and hence where to find the next one, like this:
87*6dbdd20aSAndroid Build Coastguard Worker //
88*6dbdd20aSAndroid Build Coastguard Worker //          .-------------------------. 16 byte boundary
89*6dbdd20aSAndroid Build Coastguard Worker //          | ChunkRecord:   16 bytes |
90*6dbdd20aSAndroid Build Coastguard Worker //          | - chunk id:     4 bytes |
91*6dbdd20aSAndroid Build Coastguard Worker //          | - producer id:  2 bytes |
92*6dbdd20aSAndroid Build Coastguard Worker //          | - writer id:    2 bytes |
93*6dbdd20aSAndroid Build Coastguard Worker //          | - #fragments:   2 bytes |
94*6dbdd20aSAndroid Build Coastguard Worker //    +-----+ - record size:  2 bytes |
95*6dbdd20aSAndroid Build Coastguard Worker //    |     | - flags+pad:    4 bytes |
96*6dbdd20aSAndroid Build Coastguard Worker //    |     +-------------------------+
97*6dbdd20aSAndroid Build Coastguard Worker //    |     |                         |
98*6dbdd20aSAndroid Build Coastguard Worker //    |     :     Chunk payload       :
99*6dbdd20aSAndroid Build Coastguard Worker //    |     |                         |
100*6dbdd20aSAndroid Build Coastguard Worker //    |     +-------------------------+
101*6dbdd20aSAndroid Build Coastguard Worker //    |     |    Optional padding     |
102*6dbdd20aSAndroid Build Coastguard Worker //    +---> +-------------------------+ 16 byte boundary
103*6dbdd20aSAndroid Build Coastguard Worker //          |      ChunkRecord        |
104*6dbdd20aSAndroid Build Coastguard Worker //          :                         :
105*6dbdd20aSAndroid Build Coastguard Worker // Chunks stored in the buffer are always rounded up to 16 bytes (that is
106*6dbdd20aSAndroid Build Coastguard Worker // sizeof(ChunkRecord)), in order to avoid further inner fragmentation.
107*6dbdd20aSAndroid Build Coastguard Worker // Special "padding" chunks can be put in the buffer, e.g. in the case when we
108*6dbdd20aSAndroid Build Coastguard Worker // try to write a chunk of size N while the write pointer is at the end of the
109*6dbdd20aSAndroid Build Coastguard Worker // buffer, but the write pointer is < N bytes from the end (and hence needs to
110*6dbdd20aSAndroid Build Coastguard Worker // wrap over).
111*6dbdd20aSAndroid Build Coastguard Worker // Because of this, the buffer is self-describing: the contents of the buffer
112*6dbdd20aSAndroid Build Coastguard Worker // can be reconstructed by just looking at the buffer content (this will be
113*6dbdd20aSAndroid Build Coastguard Worker // quite useful in future to recover the buffer from crash reports).
114*6dbdd20aSAndroid Build Coastguard Worker //
115*6dbdd20aSAndroid Build Coastguard Worker // However, in order to keep some operations (patching and reading) fast, a
116*6dbdd20aSAndroid Build Coastguard Worker // lookaside index is maintained (in |index_|), keeping each chunk in the buffer
117*6dbdd20aSAndroid Build Coastguard Worker // indexed by their {ProducerID, WriterID, ChunkID} tuple.
118*6dbdd20aSAndroid Build Coastguard Worker //
119*6dbdd20aSAndroid Build Coastguard Worker // Patching data out-of-band
120*6dbdd20aSAndroid Build Coastguard Worker // -------------------------
121*6dbdd20aSAndroid Build Coastguard Worker // This buffer also supports patching chunks' payload out-of-band, after they
122*6dbdd20aSAndroid Build Coastguard Worker // have been stored. This is to allow producers to backfill the "size" fields
123*6dbdd20aSAndroid Build Coastguard Worker // of the protos that spawn across several chunks, when the previous chunks are
124*6dbdd20aSAndroid Build Coastguard Worker // returned to the service. The MaybePatchChunkContents() deals with the fact
125*6dbdd20aSAndroid Build Coastguard Worker // that a chunk might have been lost (because of wrapping) by the time the OOB
126*6dbdd20aSAndroid Build Coastguard Worker // IPC comes.
127*6dbdd20aSAndroid Build Coastguard Worker //
128*6dbdd20aSAndroid Build Coastguard Worker // Reading from the buffer
129*6dbdd20aSAndroid Build Coastguard Worker // -----------------------
130*6dbdd20aSAndroid Build Coastguard Worker // This class supports one reader only (the consumer). Reads are NOT idempotent
131*6dbdd20aSAndroid Build Coastguard Worker // as they move the read cursors around. Reading back the buffer is the most
132*6dbdd20aSAndroid Build Coastguard Worker // conceptually complex part. The ReadNextTracePacket() method operates with
133*6dbdd20aSAndroid Build Coastguard Worker // whole packet granularity. Packets are returned only when all their fragments
134*6dbdd20aSAndroid Build Coastguard Worker // are available.
135*6dbdd20aSAndroid Build Coastguard Worker // This class takes care of:
136*6dbdd20aSAndroid Build Coastguard Worker // - Gluing packets within the same sequence, even if they are not stored
137*6dbdd20aSAndroid Build Coastguard Worker //   adjacently in the buffer.
138*6dbdd20aSAndroid Build Coastguard Worker // - Re-ordering chunks within a sequence (using the ChunkID, which wraps).
139*6dbdd20aSAndroid Build Coastguard Worker // - Detecting holes in packet fragments (because of loss of chunks).
140*6dbdd20aSAndroid Build Coastguard Worker // Reads guarantee that packets for the same sequence are read in FIFO order
141*6dbdd20aSAndroid Build Coastguard Worker // (according to their ChunkID), but don't give any guarantee about the read
142*6dbdd20aSAndroid Build Coastguard Worker // order of packets from different sequences, see comments in
143*6dbdd20aSAndroid Build Coastguard Worker // ReadNextTracePacket() below.
144*6dbdd20aSAndroid Build Coastguard Worker class TraceBuffer {
145*6dbdd20aSAndroid Build Coastguard Worker  public:
146*6dbdd20aSAndroid Build Coastguard Worker   static const size_t InlineChunkHeaderSize;  // For test/fake_packet.{cc,h}.
147*6dbdd20aSAndroid Build Coastguard Worker 
148*6dbdd20aSAndroid Build Coastguard Worker   // See comment in the header above.
149*6dbdd20aSAndroid Build Coastguard Worker   enum OverwritePolicy { kOverwrite, kDiscard };
150*6dbdd20aSAndroid Build Coastguard Worker 
151*6dbdd20aSAndroid Build Coastguard Worker   // Argument for out-of-band patches applied through TryPatchChunkContents().
152*6dbdd20aSAndroid Build Coastguard Worker   struct Patch {
153*6dbdd20aSAndroid Build Coastguard Worker     // From SharedMemoryABI::kPacketHeaderSize.
154*6dbdd20aSAndroid Build Coastguard Worker     static constexpr size_t kSize = 4;
155*6dbdd20aSAndroid Build Coastguard Worker 
156*6dbdd20aSAndroid Build Coastguard Worker     size_t offset_untrusted;
157*6dbdd20aSAndroid Build Coastguard Worker     std::array<uint8_t, kSize> data;
158*6dbdd20aSAndroid Build Coastguard Worker   };
159*6dbdd20aSAndroid Build Coastguard Worker 
160*6dbdd20aSAndroid Build Coastguard Worker   // Identifiers that are constant for a packet sequence.
161*6dbdd20aSAndroid Build Coastguard Worker   struct PacketSequenceProperties {
162*6dbdd20aSAndroid Build Coastguard Worker     ProducerID producer_id_trusted;
163*6dbdd20aSAndroid Build Coastguard Worker     ClientIdentity client_identity_trusted;
164*6dbdd20aSAndroid Build Coastguard Worker     WriterID writer_id;
165*6dbdd20aSAndroid Build Coastguard Worker 
producer_uid_trustedPacketSequenceProperties166*6dbdd20aSAndroid Build Coastguard Worker     uid_t producer_uid_trusted() const { return client_identity_trusted.uid(); }
producer_pid_trustedPacketSequenceProperties167*6dbdd20aSAndroid Build Coastguard Worker     pid_t producer_pid_trusted() const { return client_identity_trusted.pid(); }
168*6dbdd20aSAndroid Build Coastguard Worker   };
169*6dbdd20aSAndroid Build Coastguard Worker 
170*6dbdd20aSAndroid Build Coastguard Worker   // Holds the "used chunk" stats for each <Producer, Writer> tuple.
171*6dbdd20aSAndroid Build Coastguard Worker   struct WriterStats {
172*6dbdd20aSAndroid Build Coastguard Worker     Histogram<8, 32, 128, 512, 1024, 2048, 4096, 8192, 12288, 16384>
173*6dbdd20aSAndroid Build Coastguard Worker         used_chunk_hist;
174*6dbdd20aSAndroid Build Coastguard Worker   };
175*6dbdd20aSAndroid Build Coastguard Worker 
176*6dbdd20aSAndroid Build Coastguard Worker   using WriterStatsMap = base::FlatHashMap<ProducerAndWriterID,
177*6dbdd20aSAndroid Build Coastguard Worker                                            WriterStats,
178*6dbdd20aSAndroid Build Coastguard Worker                                            std::hash<ProducerAndWriterID>,
179*6dbdd20aSAndroid Build Coastguard Worker                                            base::QuadraticProbe,
180*6dbdd20aSAndroid Build Coastguard Worker                                            /*AppendOnly=*/true>;
181*6dbdd20aSAndroid Build Coastguard Worker 
182*6dbdd20aSAndroid Build Coastguard Worker   // Can return nullptr if the memory allocation fails.
183*6dbdd20aSAndroid Build Coastguard Worker   static std::unique_ptr<TraceBuffer> Create(size_t size_in_bytes,
184*6dbdd20aSAndroid Build Coastguard Worker                                              OverwritePolicy = kOverwrite);
185*6dbdd20aSAndroid Build Coastguard Worker 
186*6dbdd20aSAndroid Build Coastguard Worker   ~TraceBuffer();
187*6dbdd20aSAndroid Build Coastguard Worker 
188*6dbdd20aSAndroid Build Coastguard Worker   // Copies a Chunk from a producer Shared Memory Buffer into the trace buffer.
189*6dbdd20aSAndroid Build Coastguard Worker   // |src| points to the first packet in the SharedMemoryABI's chunk shared with
190*6dbdd20aSAndroid Build Coastguard Worker   // an untrusted producer. "untrusted" here means: the producer might be
191*6dbdd20aSAndroid Build Coastguard Worker   // malicious and might change |src| concurrently while we read it (internally
192*6dbdd20aSAndroid Build Coastguard Worker   // this method memcpy()-s first the chunk before processing it). None of the
193*6dbdd20aSAndroid Build Coastguard Worker   // arguments should be trusted, unless otherwise stated. We can trust that
194*6dbdd20aSAndroid Build Coastguard Worker   // |src| points to a valid memory area, but not its contents.
195*6dbdd20aSAndroid Build Coastguard Worker   //
196*6dbdd20aSAndroid Build Coastguard Worker   // This method may be called multiple times for the same chunk. In this case,
197*6dbdd20aSAndroid Build Coastguard Worker   // the original chunk's payload will be overridden and its number of fragments
198*6dbdd20aSAndroid Build Coastguard Worker   // and flags adjusted to match |num_fragments| and |chunk_flags|. The service
199*6dbdd20aSAndroid Build Coastguard Worker   // may use this to insert partial chunks (|chunk_complete = false|) before the
200*6dbdd20aSAndroid Build Coastguard Worker   // producer has committed them.
201*6dbdd20aSAndroid Build Coastguard Worker   //
202*6dbdd20aSAndroid Build Coastguard Worker   // If |chunk_complete| is |false|, the TraceBuffer will only consider the
203*6dbdd20aSAndroid Build Coastguard Worker   // first |num_fragments - 1| packets to be complete, since the producer may
204*6dbdd20aSAndroid Build Coastguard Worker   // not have finished writing the latest packet. Reading from a sequence will
205*6dbdd20aSAndroid Build Coastguard Worker   // also not progress past any incomplete chunks until they were rewritten with
206*6dbdd20aSAndroid Build Coastguard Worker   // |chunk_complete = true|, e.g. after a producer's commit.
207*6dbdd20aSAndroid Build Coastguard Worker   //
208*6dbdd20aSAndroid Build Coastguard Worker   // TODO(eseckler): Pass in a PacketStreamProperties instead of individual IDs.
209*6dbdd20aSAndroid Build Coastguard Worker   void CopyChunkUntrusted(ProducerID producer_id_trusted,
210*6dbdd20aSAndroid Build Coastguard Worker                           const ClientIdentity& client_identity_trusted,
211*6dbdd20aSAndroid Build Coastguard Worker 
212*6dbdd20aSAndroid Build Coastguard Worker                           WriterID writer_id,
213*6dbdd20aSAndroid Build Coastguard Worker                           ChunkID chunk_id,
214*6dbdd20aSAndroid Build Coastguard Worker                           uint16_t num_fragments,
215*6dbdd20aSAndroid Build Coastguard Worker                           uint8_t chunk_flags,
216*6dbdd20aSAndroid Build Coastguard Worker                           bool chunk_complete,
217*6dbdd20aSAndroid Build Coastguard Worker                           const uint8_t* src,
218*6dbdd20aSAndroid Build Coastguard Worker                           size_t size);
219*6dbdd20aSAndroid Build Coastguard Worker 
220*6dbdd20aSAndroid Build Coastguard Worker   // Applies a batch of |patches| to the given chunk, if the given chunk is
221*6dbdd20aSAndroid Build Coastguard Worker   // still in the buffer. Does nothing if the given ChunkID is gone.
222*6dbdd20aSAndroid Build Coastguard Worker   // Returns true if the chunk has been found and patched, false otherwise.
223*6dbdd20aSAndroid Build Coastguard Worker   // |other_patches_pending| is used to determine whether this is the only
224*6dbdd20aSAndroid Build Coastguard Worker   // batch of patches for the chunk or there is more.
225*6dbdd20aSAndroid Build Coastguard Worker   // If |other_patches_pending| == false, the chunk is marked as ready to be
226*6dbdd20aSAndroid Build Coastguard Worker   // consumed. If true, the state of the chunk is not altered.
227*6dbdd20aSAndroid Build Coastguard Worker   //
228*6dbdd20aSAndroid Build Coastguard Worker   // Note: If the producer is batching commits (see shared_memory_arbiter.h), it
229*6dbdd20aSAndroid Build Coastguard Worker   // will also attempt to do patching locally. Namely, if nested messages are
230*6dbdd20aSAndroid Build Coastguard Worker   // completed while the chunk on which they started is being batched (i.e.
231*6dbdd20aSAndroid Build Coastguard Worker   // before it has been committed to the service), the producer will apply the
232*6dbdd20aSAndroid Build Coastguard Worker   // respective patches to the batched chunk. These patches will not be sent to
233*6dbdd20aSAndroid Build Coastguard Worker   // the service - i.e. only the patches that the producer did not manage to
234*6dbdd20aSAndroid Build Coastguard Worker   // apply before committing the chunk will be applied here.
235*6dbdd20aSAndroid Build Coastguard Worker   bool TryPatchChunkContents(ProducerID,
236*6dbdd20aSAndroid Build Coastguard Worker                              WriterID,
237*6dbdd20aSAndroid Build Coastguard Worker                              ChunkID,
238*6dbdd20aSAndroid Build Coastguard Worker                              const Patch* patches,
239*6dbdd20aSAndroid Build Coastguard Worker                              size_t patches_size,
240*6dbdd20aSAndroid Build Coastguard Worker                              bool other_patches_pending);
241*6dbdd20aSAndroid Build Coastguard Worker 
242*6dbdd20aSAndroid Build Coastguard Worker   // To read the contents of the buffer the caller needs to:
243*6dbdd20aSAndroid Build Coastguard Worker   //   BeginRead()
244*6dbdd20aSAndroid Build Coastguard Worker   //   while (ReadNextTracePacket(packet_fragments)) { ... }
245*6dbdd20aSAndroid Build Coastguard Worker   // No other calls to any other method should be interleaved between
246*6dbdd20aSAndroid Build Coastguard Worker   // BeginRead() and ReadNextTracePacket().
247*6dbdd20aSAndroid Build Coastguard Worker   // Reads in the TraceBuffer are NOT idempotent.
248*6dbdd20aSAndroid Build Coastguard Worker   void BeginRead();
249*6dbdd20aSAndroid Build Coastguard Worker 
250*6dbdd20aSAndroid Build Coastguard Worker   // Returns the next packet in the buffer, if any, and the producer_id,
251*6dbdd20aSAndroid Build Coastguard Worker   // producer_uid, and writer_id of the producer/writer that wrote it (as passed
252*6dbdd20aSAndroid Build Coastguard Worker   // in the CopyChunkUntrusted() call). Returns false if no packets can be read
253*6dbdd20aSAndroid Build Coastguard Worker   // at this point. If a packet was read successfully,
254*6dbdd20aSAndroid Build Coastguard Worker   // |previous_packet_on_sequence_dropped| is set to |true| if the previous
255*6dbdd20aSAndroid Build Coastguard Worker   // packet on the sequence was dropped from the buffer before it could be read
256*6dbdd20aSAndroid Build Coastguard Worker   // (e.g. because its chunk was overridden due to the ring buffer wrapping or
257*6dbdd20aSAndroid Build Coastguard Worker   // due to an ABI violation), and to |false| otherwise.
258*6dbdd20aSAndroid Build Coastguard Worker   //
259*6dbdd20aSAndroid Build Coastguard Worker   // This function returns only complete packets. Specifically:
260*6dbdd20aSAndroid Build Coastguard Worker   // When there is at least one complete packet in the buffer, this function
261*6dbdd20aSAndroid Build Coastguard Worker   // returns true and populates the TracePacket argument with the boundaries of
262*6dbdd20aSAndroid Build Coastguard Worker   // each fragment for one packet.
263*6dbdd20aSAndroid Build Coastguard Worker   // TracePacket will have at least one slice when this function returns true.
264*6dbdd20aSAndroid Build Coastguard Worker   // When there are no whole packets eligible to read (e.g. we are still missing
265*6dbdd20aSAndroid Build Coastguard Worker   // fragments) this function returns false.
266*6dbdd20aSAndroid Build Coastguard Worker   // This function guarantees also that packets for a given
267*6dbdd20aSAndroid Build Coastguard Worker   // {ProducerID, WriterID} are read in FIFO order.
268*6dbdd20aSAndroid Build Coastguard Worker   // This function does not guarantee any ordering w.r.t. packets belonging to
269*6dbdd20aSAndroid Build Coastguard Worker   // different WriterID(s). For instance, given the following packets copied
270*6dbdd20aSAndroid Build Coastguard Worker   // into the buffer:
271*6dbdd20aSAndroid Build Coastguard Worker   //   {ProducerID: 1, WriterID: 1}: P1 P2 P3
272*6dbdd20aSAndroid Build Coastguard Worker   //   {ProducerID: 1, WriterID: 2}: P4 P5 P6
273*6dbdd20aSAndroid Build Coastguard Worker   //   {ProducerID: 2, WriterID: 1}: P7 P8 P9
274*6dbdd20aSAndroid Build Coastguard Worker   // The following read sequence is possible:
275*6dbdd20aSAndroid Build Coastguard Worker   //   P1, P4, P7, P2, P3, P5, P8, P9, P6
276*6dbdd20aSAndroid Build Coastguard Worker   // But the following is guaranteed to NOT happen:
277*6dbdd20aSAndroid Build Coastguard Worker   //   P1, P5, P7, P4 (P4 cannot come after P5)
278*6dbdd20aSAndroid Build Coastguard Worker   bool ReadNextTracePacket(TracePacket*,
279*6dbdd20aSAndroid Build Coastguard Worker                            PacketSequenceProperties* sequence_properties,
280*6dbdd20aSAndroid Build Coastguard Worker                            bool* previous_packet_on_sequence_dropped);
281*6dbdd20aSAndroid Build Coastguard Worker 
282*6dbdd20aSAndroid Build Coastguard Worker   // Creates a read-only clone of the trace buffer. The read iterators of the
283*6dbdd20aSAndroid Build Coastguard Worker   // new buffer will be reset, as if no Read() had been called. Calls to
284*6dbdd20aSAndroid Build Coastguard Worker   // CopyChunkUntrusted() and TryPatchChunkContents() on the returned cloned
285*6dbdd20aSAndroid Build Coastguard Worker   // TraceBuffer will CHECK().
286*6dbdd20aSAndroid Build Coastguard Worker   std::unique_ptr<TraceBuffer> CloneReadOnly() const;
287*6dbdd20aSAndroid Build Coastguard Worker 
set_read_only()288*6dbdd20aSAndroid Build Coastguard Worker   void set_read_only() { read_only_ = true; }
writer_stats()289*6dbdd20aSAndroid Build Coastguard Worker   const WriterStatsMap& writer_stats() const { return writer_stats_; }
stats()290*6dbdd20aSAndroid Build Coastguard Worker   const TraceStats::BufferStats& stats() const { return stats_; }
size()291*6dbdd20aSAndroid Build Coastguard Worker   size_t size() const { return size_; }
used_size()292*6dbdd20aSAndroid Build Coastguard Worker   size_t used_size() const { return used_size_; }
overwrite_policy()293*6dbdd20aSAndroid Build Coastguard Worker   OverwritePolicy overwrite_policy() const { return overwrite_policy_; }
has_data()294*6dbdd20aSAndroid Build Coastguard Worker   bool has_data() const { return has_data_; }
295*6dbdd20aSAndroid Build Coastguard Worker 
296*6dbdd20aSAndroid Build Coastguard Worker  private:
297*6dbdd20aSAndroid Build Coastguard Worker   friend class TraceBufferTest;
298*6dbdd20aSAndroid Build Coastguard Worker 
299*6dbdd20aSAndroid Build Coastguard Worker   // ChunkRecord is a Chunk header stored inline in the |data_| buffer, before
300*6dbdd20aSAndroid Build Coastguard Worker   // the chunk payload (the packets' data). The |data_| buffer looks like this:
301*6dbdd20aSAndroid Build Coastguard Worker   // +---------------+------------------++---------------+-----------------+
302*6dbdd20aSAndroid Build Coastguard Worker   // | ChunkRecord 1 | Chunk payload 1  || ChunkRecord 2 | Chunk payload 2 | ...
303*6dbdd20aSAndroid Build Coastguard Worker   // +---------------+------------------++---------------+-----------------+
304*6dbdd20aSAndroid Build Coastguard Worker   // Most of the ChunkRecord fields are copied from SharedMemoryABI::ChunkHeader
305*6dbdd20aSAndroid Build Coastguard Worker   // (the chunk header used in the shared memory buffers).
306*6dbdd20aSAndroid Build Coastguard Worker   // A ChunkRecord can be a special "padding" record. In this case its payload
307*6dbdd20aSAndroid Build Coastguard Worker   // should be ignored and the record should be just skipped.
308*6dbdd20aSAndroid Build Coastguard Worker   //
309*6dbdd20aSAndroid Build Coastguard Worker   // Full page move optimization:
310*6dbdd20aSAndroid Build Coastguard Worker   // This struct has to be exactly (sizeof(PageHeader) + sizeof(ChunkHeader))
311*6dbdd20aSAndroid Build Coastguard Worker   // (from shared_memory_abi.h) to allow full page move optimizations
312*6dbdd20aSAndroid Build Coastguard Worker   // (TODO(primiano): not implemented yet). In the special case of moving a full
313*6dbdd20aSAndroid Build Coastguard Worker   // 4k page that contains only one chunk, in fact, we can just ask the kernel
314*6dbdd20aSAndroid Build Coastguard Worker   // to move the full SHM page (see SPLICE_F_{GIFT,MOVE}) and overlay the
315*6dbdd20aSAndroid Build Coastguard Worker   // ChunkRecord on top of the moved SMB's header (page + chunk header).
316*6dbdd20aSAndroid Build Coastguard Worker   // This special requirement is covered by static_assert(s) in the .cc file.
317*6dbdd20aSAndroid Build Coastguard Worker   struct ChunkRecord {
ChunkRecordChunkRecord318*6dbdd20aSAndroid Build Coastguard Worker     explicit ChunkRecord(size_t sz) : flags{0}, is_padding{0} {
319*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DCHECK(sz >= sizeof(ChunkRecord) &&
320*6dbdd20aSAndroid Build Coastguard Worker                       sz % sizeof(ChunkRecord) == 0 && sz <= kMaxSize);
321*6dbdd20aSAndroid Build Coastguard Worker       size = static_cast<decltype(size)>(sz);
322*6dbdd20aSAndroid Build Coastguard Worker     }
323*6dbdd20aSAndroid Build Coastguard Worker 
is_validChunkRecord324*6dbdd20aSAndroid Build Coastguard Worker     bool is_valid() const { return size != 0; }
325*6dbdd20aSAndroid Build Coastguard Worker 
326*6dbdd20aSAndroid Build Coastguard Worker     // Keep this structure packed and exactly 16 bytes (128 bits) big.
327*6dbdd20aSAndroid Build Coastguard Worker 
328*6dbdd20aSAndroid Build Coastguard Worker     // [32 bits] Monotonic counter within the same writer_id.
329*6dbdd20aSAndroid Build Coastguard Worker     ChunkID chunk_id = 0;
330*6dbdd20aSAndroid Build Coastguard Worker 
331*6dbdd20aSAndroid Build Coastguard Worker     // [16 bits] ID of the Producer from which the Chunk was copied from.
332*6dbdd20aSAndroid Build Coastguard Worker     ProducerID producer_id = 0;
333*6dbdd20aSAndroid Build Coastguard Worker 
334*6dbdd20aSAndroid Build Coastguard Worker     // [16 bits] Unique per Producer (but not within the service).
335*6dbdd20aSAndroid Build Coastguard Worker     // If writer_id == kWriterIdPadding the record should just be skipped.
336*6dbdd20aSAndroid Build Coastguard Worker     WriterID writer_id = 0;
337*6dbdd20aSAndroid Build Coastguard Worker 
338*6dbdd20aSAndroid Build Coastguard Worker     // Number of fragments contained in the chunk.
339*6dbdd20aSAndroid Build Coastguard Worker     uint16_t num_fragments = 0;
340*6dbdd20aSAndroid Build Coastguard Worker 
341*6dbdd20aSAndroid Build Coastguard Worker     // Size in bytes, including sizeof(ChunkRecord) itself.
342*6dbdd20aSAndroid Build Coastguard Worker     uint16_t size;
343*6dbdd20aSAndroid Build Coastguard Worker 
344*6dbdd20aSAndroid Build Coastguard Worker     uint8_t flags : 6;  // See SharedMemoryABI::ChunkHeader::flags.
345*6dbdd20aSAndroid Build Coastguard Worker     static constexpr size_t kFlagsBitMask = (1 << 6) - 1;
346*6dbdd20aSAndroid Build Coastguard Worker 
347*6dbdd20aSAndroid Build Coastguard Worker     uint8_t is_padding : 1;
348*6dbdd20aSAndroid Build Coastguard Worker     uint8_t unused_flag : 1;
349*6dbdd20aSAndroid Build Coastguard Worker 
350*6dbdd20aSAndroid Build Coastguard Worker     // Not strictly needed, can be reused for more fields in the future. But
351*6dbdd20aSAndroid Build Coastguard Worker     // right now helps to spot chunks in hex dumps.
352*6dbdd20aSAndroid Build Coastguard Worker     char unused[3] = {'C', 'H', 'U'};
353*6dbdd20aSAndroid Build Coastguard Worker 
354*6dbdd20aSAndroid Build Coastguard Worker     static constexpr size_t kMaxSize =
355*6dbdd20aSAndroid Build Coastguard Worker         std::numeric_limits<decltype(size)>::max();
356*6dbdd20aSAndroid Build Coastguard Worker   };
357*6dbdd20aSAndroid Build Coastguard Worker 
358*6dbdd20aSAndroid Build Coastguard Worker   // Lookaside index entry. This serves two purposes:
359*6dbdd20aSAndroid Build Coastguard Worker   // 1) Allow a fast lookup of ChunkRecord by their ID (the tuple
360*6dbdd20aSAndroid Build Coastguard Worker   //   {ProducerID, WriterID, ChunkID}). This is used when applying out-of-band
361*6dbdd20aSAndroid Build Coastguard Worker   //   patches to the contents of the chunks after they have been copied into
362*6dbdd20aSAndroid Build Coastguard Worker   //   the TraceBuffer.
363*6dbdd20aSAndroid Build Coastguard Worker   // 2) keep the chunks ordered by their ID. This is used when reading back.
364*6dbdd20aSAndroid Build Coastguard Worker   // 3) Keep metadata about the status of the chunk, e.g. whether the contents
365*6dbdd20aSAndroid Build Coastguard Worker   //    have been read already and should be skipped in a future read pass.
366*6dbdd20aSAndroid Build Coastguard Worker   // This struct should not have any field that is essential for reconstructing
367*6dbdd20aSAndroid Build Coastguard Worker   // the contents of the buffer from a crash dump.
368*6dbdd20aSAndroid Build Coastguard Worker   struct ChunkMeta {
369*6dbdd20aSAndroid Build Coastguard Worker     // Key used for sorting in the map.
370*6dbdd20aSAndroid Build Coastguard Worker     struct Key {
KeyChunkMeta::Key371*6dbdd20aSAndroid Build Coastguard Worker       Key(ProducerID p, WriterID w, ChunkID c)
372*6dbdd20aSAndroid Build Coastguard Worker           : producer_id{p}, writer_id{w}, chunk_id{c} {}
373*6dbdd20aSAndroid Build Coastguard Worker 
374*6dbdd20aSAndroid Build Coastguard Worker       Key(const Key&) noexcept = default;
375*6dbdd20aSAndroid Build Coastguard Worker       Key& operator=(const Key&) = default;
376*6dbdd20aSAndroid Build Coastguard Worker 
KeyChunkMeta::Key377*6dbdd20aSAndroid Build Coastguard Worker       explicit Key(const ChunkRecord& cr)
378*6dbdd20aSAndroid Build Coastguard Worker           : Key(cr.producer_id, cr.writer_id, cr.chunk_id) {}
379*6dbdd20aSAndroid Build Coastguard Worker 
380*6dbdd20aSAndroid Build Coastguard Worker       // Note that this sorting doesn't keep into account the fact that ChunkID
381*6dbdd20aSAndroid Build Coastguard Worker       // will wrap over at some point. The extra logic in SequenceIterator deals
382*6dbdd20aSAndroid Build Coastguard Worker       // with that.
383*6dbdd20aSAndroid Build Coastguard Worker       bool operator<(const Key& other) const {
384*6dbdd20aSAndroid Build Coastguard Worker         return std::tie(producer_id, writer_id, chunk_id) <
385*6dbdd20aSAndroid Build Coastguard Worker                std::tie(other.producer_id, other.writer_id, other.chunk_id);
386*6dbdd20aSAndroid Build Coastguard Worker       }
387*6dbdd20aSAndroid Build Coastguard Worker 
388*6dbdd20aSAndroid Build Coastguard Worker       bool operator==(const Key& other) const {
389*6dbdd20aSAndroid Build Coastguard Worker         return std::tie(producer_id, writer_id, chunk_id) ==
390*6dbdd20aSAndroid Build Coastguard Worker                std::tie(other.producer_id, other.writer_id, other.chunk_id);
391*6dbdd20aSAndroid Build Coastguard Worker       }
392*6dbdd20aSAndroid Build Coastguard Worker 
393*6dbdd20aSAndroid Build Coastguard Worker       bool operator!=(const Key& other) const { return !(*this == other); }
394*6dbdd20aSAndroid Build Coastguard Worker 
395*6dbdd20aSAndroid Build Coastguard Worker       // These fields should match at all times the corresponding fields in
396*6dbdd20aSAndroid Build Coastguard Worker       // the |chunk_record|. They are copied here purely for efficiency to avoid
397*6dbdd20aSAndroid Build Coastguard Worker       // dereferencing the buffer all the time.
398*6dbdd20aSAndroid Build Coastguard Worker       ProducerID producer_id;
399*6dbdd20aSAndroid Build Coastguard Worker       WriterID writer_id;
400*6dbdd20aSAndroid Build Coastguard Worker       ChunkID chunk_id;
401*6dbdd20aSAndroid Build Coastguard Worker     };
402*6dbdd20aSAndroid Build Coastguard Worker 
403*6dbdd20aSAndroid Build Coastguard Worker     enum IndexFlags : uint8_t {
404*6dbdd20aSAndroid Build Coastguard Worker       // If set, the chunk state was kChunkComplete at the time it was copied.
405*6dbdd20aSAndroid Build Coastguard Worker       // If unset, the chunk was still kChunkBeingWritten while copied. When
406*6dbdd20aSAndroid Build Coastguard Worker       // reading from the chunk's sequence, the sequence will not advance past
407*6dbdd20aSAndroid Build Coastguard Worker       // this chunk until this flag is set.
408*6dbdd20aSAndroid Build Coastguard Worker       kComplete = 1 << 0,
409*6dbdd20aSAndroid Build Coastguard Worker 
410*6dbdd20aSAndroid Build Coastguard Worker       // If set, we skipped the last packet that we read from this chunk e.g.
411*6dbdd20aSAndroid Build Coastguard Worker       // because we it was a continuation from a previous chunk that was dropped
412*6dbdd20aSAndroid Build Coastguard Worker       // or due to an ABI violation.
413*6dbdd20aSAndroid Build Coastguard Worker       kLastReadPacketSkipped = 1 << 1
414*6dbdd20aSAndroid Build Coastguard Worker     };
415*6dbdd20aSAndroid Build Coastguard Worker 
ChunkMetaChunkMeta416*6dbdd20aSAndroid Build Coastguard Worker     ChunkMeta(uint32_t _record_off,
417*6dbdd20aSAndroid Build Coastguard Worker               uint16_t _num_fragments,
418*6dbdd20aSAndroid Build Coastguard Worker               bool complete,
419*6dbdd20aSAndroid Build Coastguard Worker               uint8_t _flags,
420*6dbdd20aSAndroid Build Coastguard Worker               const ClientIdentity& client_identity)
421*6dbdd20aSAndroid Build Coastguard Worker         : record_off{_record_off},
422*6dbdd20aSAndroid Build Coastguard Worker           client_identity_trusted(client_identity),
423*6dbdd20aSAndroid Build Coastguard Worker           flags{_flags},
424*6dbdd20aSAndroid Build Coastguard Worker           num_fragments{_num_fragments} {
425*6dbdd20aSAndroid Build Coastguard Worker       if (complete)
426*6dbdd20aSAndroid Build Coastguard Worker         index_flags = kComplete;
427*6dbdd20aSAndroid Build Coastguard Worker     }
428*6dbdd20aSAndroid Build Coastguard Worker 
429*6dbdd20aSAndroid Build Coastguard Worker     ChunkMeta(const ChunkMeta&) noexcept = default;
430*6dbdd20aSAndroid Build Coastguard Worker 
is_completeChunkMeta431*6dbdd20aSAndroid Build Coastguard Worker     bool is_complete() const { return index_flags & kComplete; }
432*6dbdd20aSAndroid Build Coastguard Worker 
set_completeChunkMeta433*6dbdd20aSAndroid Build Coastguard Worker     void set_complete(bool complete) {
434*6dbdd20aSAndroid Build Coastguard Worker       if (complete) {
435*6dbdd20aSAndroid Build Coastguard Worker         index_flags |= kComplete;
436*6dbdd20aSAndroid Build Coastguard Worker       } else {
437*6dbdd20aSAndroid Build Coastguard Worker         index_flags &= ~kComplete;
438*6dbdd20aSAndroid Build Coastguard Worker       }
439*6dbdd20aSAndroid Build Coastguard Worker     }
440*6dbdd20aSAndroid Build Coastguard Worker 
last_read_packet_skippedChunkMeta441*6dbdd20aSAndroid Build Coastguard Worker     bool last_read_packet_skipped() const {
442*6dbdd20aSAndroid Build Coastguard Worker       return index_flags & kLastReadPacketSkipped;
443*6dbdd20aSAndroid Build Coastguard Worker     }
444*6dbdd20aSAndroid Build Coastguard Worker 
set_last_read_packet_skippedChunkMeta445*6dbdd20aSAndroid Build Coastguard Worker     void set_last_read_packet_skipped(bool skipped) {
446*6dbdd20aSAndroid Build Coastguard Worker       if (skipped) {
447*6dbdd20aSAndroid Build Coastguard Worker         index_flags |= kLastReadPacketSkipped;
448*6dbdd20aSAndroid Build Coastguard Worker       } else {
449*6dbdd20aSAndroid Build Coastguard Worker         index_flags &= ~kLastReadPacketSkipped;
450*6dbdd20aSAndroid Build Coastguard Worker       }
451*6dbdd20aSAndroid Build Coastguard Worker     }
452*6dbdd20aSAndroid Build Coastguard Worker 
453*6dbdd20aSAndroid Build Coastguard Worker     const uint32_t record_off;  // Offset of ChunkRecord within |data_|.
454*6dbdd20aSAndroid Build Coastguard Worker     const ClientIdentity client_identity_trusted;
455*6dbdd20aSAndroid Build Coastguard Worker     // Flags set by TraceBuffer to track the state of the chunk in the index.
456*6dbdd20aSAndroid Build Coastguard Worker     uint8_t index_flags = 0;
457*6dbdd20aSAndroid Build Coastguard Worker 
458*6dbdd20aSAndroid Build Coastguard Worker     // Correspond to |chunk_record->flags| and |chunk_record->num_fragments|.
459*6dbdd20aSAndroid Build Coastguard Worker     // Copied here for performance reasons (avoids having to dereference
460*6dbdd20aSAndroid Build Coastguard Worker     // |chunk_record| while iterating over ChunkMeta) and to aid debugging in
461*6dbdd20aSAndroid Build Coastguard Worker     // case the buffer gets corrupted.
462*6dbdd20aSAndroid Build Coastguard Worker     uint8_t flags = 0;           // See SharedMemoryABI::ChunkHeader::flags.
463*6dbdd20aSAndroid Build Coastguard Worker     uint16_t num_fragments = 0;  // Total number of packet fragments.
464*6dbdd20aSAndroid Build Coastguard Worker 
465*6dbdd20aSAndroid Build Coastguard Worker     uint16_t num_fragments_read = 0;  // Number of fragments already read.
466*6dbdd20aSAndroid Build Coastguard Worker 
467*6dbdd20aSAndroid Build Coastguard Worker     // The start offset of the next fragment (the |num_fragments_read|-th) to be
468*6dbdd20aSAndroid Build Coastguard Worker     // read. This is the offset in bytes from the beginning of the ChunkRecord's
469*6dbdd20aSAndroid Build Coastguard Worker     // payload (the 1st fragment starts at |chunk_record| +
470*6dbdd20aSAndroid Build Coastguard Worker     // sizeof(ChunkRecord)).
471*6dbdd20aSAndroid Build Coastguard Worker     uint16_t cur_fragment_offset = 0;
472*6dbdd20aSAndroid Build Coastguard Worker   };
473*6dbdd20aSAndroid Build Coastguard Worker 
474*6dbdd20aSAndroid Build Coastguard Worker   using ChunkMap = std::map<ChunkMeta::Key, ChunkMeta>;
475*6dbdd20aSAndroid Build Coastguard Worker 
476*6dbdd20aSAndroid Build Coastguard Worker   // Allows to iterate over a sub-sequence of |index_| for all keys belonging to
477*6dbdd20aSAndroid Build Coastguard Worker   // the same {ProducerID,WriterID}. Furthermore takes into account the wrapping
478*6dbdd20aSAndroid Build Coastguard Worker   // of ChunkID. Instances are valid only as long as the |index_| is not altered
479*6dbdd20aSAndroid Build Coastguard Worker   // (can be used safely only between adjacent ReadNextTracePacket() calls).
480*6dbdd20aSAndroid Build Coastguard Worker   // The order of the iteration will proceed in the following order:
481*6dbdd20aSAndroid Build Coastguard Worker   // |wrapping_id| + 1 -> |seq_end|, |seq_begin| -> |wrapping_id|.
482*6dbdd20aSAndroid Build Coastguard Worker   // Practical example:
483*6dbdd20aSAndroid Build Coastguard Worker   // - Assume that kMaxChunkID == 7
484*6dbdd20aSAndroid Build Coastguard Worker   // - Assume that we have all 8 chunks in the range (0..7).
485*6dbdd20aSAndroid Build Coastguard Worker   // - Hence, |seq_begin| == c0, |seq_end| == c7
486*6dbdd20aSAndroid Build Coastguard Worker   // - Assume |wrapping_id| = 4 (c4 is the last chunk copied over
487*6dbdd20aSAndroid Build Coastguard Worker   //   through a CopyChunkUntrusted()).
488*6dbdd20aSAndroid Build Coastguard Worker   // The resulting iteration order will be: c5, c6, c7, c0, c1, c2, c3, c4.
489*6dbdd20aSAndroid Build Coastguard Worker   struct SequenceIterator {
490*6dbdd20aSAndroid Build Coastguard Worker     // Points to the 1st key (the one with the numerically min ChunkID).
491*6dbdd20aSAndroid Build Coastguard Worker     ChunkMap::iterator seq_begin;
492*6dbdd20aSAndroid Build Coastguard Worker 
493*6dbdd20aSAndroid Build Coastguard Worker     // Points one past the last key (the one with the numerically max ChunkID).
494*6dbdd20aSAndroid Build Coastguard Worker     ChunkMap::iterator seq_end;
495*6dbdd20aSAndroid Build Coastguard Worker 
496*6dbdd20aSAndroid Build Coastguard Worker     // Current iterator, always >= seq_begin && <= seq_end.
497*6dbdd20aSAndroid Build Coastguard Worker     ChunkMap::iterator cur;
498*6dbdd20aSAndroid Build Coastguard Worker 
499*6dbdd20aSAndroid Build Coastguard Worker     // The latest ChunkID written. Determines the start/end of the sequence.
500*6dbdd20aSAndroid Build Coastguard Worker     ChunkID wrapping_id;
501*6dbdd20aSAndroid Build Coastguard Worker 
is_validSequenceIterator502*6dbdd20aSAndroid Build Coastguard Worker     bool is_valid() const { return cur != seq_end; }
503*6dbdd20aSAndroid Build Coastguard Worker 
producer_idSequenceIterator504*6dbdd20aSAndroid Build Coastguard Worker     ProducerID producer_id() const {
505*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DCHECK(is_valid());
506*6dbdd20aSAndroid Build Coastguard Worker       return cur->first.producer_id;
507*6dbdd20aSAndroid Build Coastguard Worker     }
508*6dbdd20aSAndroid Build Coastguard Worker 
writer_idSequenceIterator509*6dbdd20aSAndroid Build Coastguard Worker     WriterID writer_id() const {
510*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DCHECK(is_valid());
511*6dbdd20aSAndroid Build Coastguard Worker       return cur->first.writer_id;
512*6dbdd20aSAndroid Build Coastguard Worker     }
513*6dbdd20aSAndroid Build Coastguard Worker 
chunk_idSequenceIterator514*6dbdd20aSAndroid Build Coastguard Worker     ChunkID chunk_id() const {
515*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DCHECK(is_valid());
516*6dbdd20aSAndroid Build Coastguard Worker       return cur->first.chunk_id;
517*6dbdd20aSAndroid Build Coastguard Worker     }
518*6dbdd20aSAndroid Build Coastguard Worker 
519*6dbdd20aSAndroid Build Coastguard Worker     ChunkMeta& operator*() {
520*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DCHECK(is_valid());
521*6dbdd20aSAndroid Build Coastguard Worker       return cur->second;
522*6dbdd20aSAndroid Build Coastguard Worker     }
523*6dbdd20aSAndroid Build Coastguard Worker 
524*6dbdd20aSAndroid Build Coastguard Worker     // Moves |cur| to the next chunk in the index.
525*6dbdd20aSAndroid Build Coastguard Worker     // is_valid() will become false after calling this, if this was the last
526*6dbdd20aSAndroid Build Coastguard Worker     // entry of the sequence.
527*6dbdd20aSAndroid Build Coastguard Worker     void MoveNext();
528*6dbdd20aSAndroid Build Coastguard Worker 
MoveToEndSequenceIterator529*6dbdd20aSAndroid Build Coastguard Worker     void MoveToEnd() { cur = seq_end; }
530*6dbdd20aSAndroid Build Coastguard Worker   };
531*6dbdd20aSAndroid Build Coastguard Worker 
532*6dbdd20aSAndroid Build Coastguard Worker   enum class ReadAheadResult {
533*6dbdd20aSAndroid Build Coastguard Worker     kSucceededReturnSlices,
534*6dbdd20aSAndroid Build Coastguard Worker     kFailedMoveToNextSequence,
535*6dbdd20aSAndroid Build Coastguard Worker     kFailedStayOnSameSequence,
536*6dbdd20aSAndroid Build Coastguard Worker   };
537*6dbdd20aSAndroid Build Coastguard Worker 
538*6dbdd20aSAndroid Build Coastguard Worker   enum class ReadPacketResult {
539*6dbdd20aSAndroid Build Coastguard Worker     kSucceeded,
540*6dbdd20aSAndroid Build Coastguard Worker     kFailedInvalidPacket,
541*6dbdd20aSAndroid Build Coastguard Worker     kFailedEmptyPacket,
542*6dbdd20aSAndroid Build Coastguard Worker   };
543*6dbdd20aSAndroid Build Coastguard Worker 
544*6dbdd20aSAndroid Build Coastguard Worker   explicit TraceBuffer(OverwritePolicy);
545*6dbdd20aSAndroid Build Coastguard Worker   TraceBuffer(const TraceBuffer&) = delete;
546*6dbdd20aSAndroid Build Coastguard Worker   TraceBuffer& operator=(const TraceBuffer&) = delete;
547*6dbdd20aSAndroid Build Coastguard Worker 
548*6dbdd20aSAndroid Build Coastguard Worker   // Not using the implicit copy ctor to avoid unintended copies.
549*6dbdd20aSAndroid Build Coastguard Worker   // This tagged ctor should be used only for Clone().
550*6dbdd20aSAndroid Build Coastguard Worker   struct CloneCtor {};
551*6dbdd20aSAndroid Build Coastguard Worker   TraceBuffer(CloneCtor, const TraceBuffer&);
552*6dbdd20aSAndroid Build Coastguard Worker 
553*6dbdd20aSAndroid Build Coastguard Worker   bool Initialize(size_t size);
554*6dbdd20aSAndroid Build Coastguard Worker 
555*6dbdd20aSAndroid Build Coastguard Worker   // Returns an object that allows to iterate over chunks in the |index_| that
556*6dbdd20aSAndroid Build Coastguard Worker   // have the same {ProducerID, WriterID} of
557*6dbdd20aSAndroid Build Coastguard Worker   // |seq_begin.first.{producer,writer}_id|. |seq_begin| must be an iterator to
558*6dbdd20aSAndroid Build Coastguard Worker   // the first entry in the |index_| that has a different {ProducerID, WriterID}
559*6dbdd20aSAndroid Build Coastguard Worker   // from the previous one. It is valid for |seq_begin| to be == index_.end()
560*6dbdd20aSAndroid Build Coastguard Worker   // (i.e. if the index is empty). The iteration takes care of ChunkID wrapping,
561*6dbdd20aSAndroid Build Coastguard Worker   // by using |last_chunk_id_|.
562*6dbdd20aSAndroid Build Coastguard Worker   SequenceIterator GetReadIterForSequence(ChunkMap::iterator seq_begin);
563*6dbdd20aSAndroid Build Coastguard Worker 
564*6dbdd20aSAndroid Build Coastguard Worker   // Used as a last resort when a buffer corruption is detected.
565*6dbdd20aSAndroid Build Coastguard Worker   void ClearContentsAndResetRWCursors();
566*6dbdd20aSAndroid Build Coastguard Worker 
567*6dbdd20aSAndroid Build Coastguard Worker   // Adds a padding record of the given size (must be a multiple of
568*6dbdd20aSAndroid Build Coastguard Worker   // sizeof(ChunkRecord)).
569*6dbdd20aSAndroid Build Coastguard Worker   void AddPaddingRecord(size_t);
570*6dbdd20aSAndroid Build Coastguard Worker 
571*6dbdd20aSAndroid Build Coastguard Worker   // Look for contiguous fragment of the same packet starting from |read_iter_|.
572*6dbdd20aSAndroid Build Coastguard Worker   // If a contiguous packet is found, all the fragments are pushed into
573*6dbdd20aSAndroid Build Coastguard Worker   // TracePacket and the function returns kSucceededReturnSlices. If not, the
574*6dbdd20aSAndroid Build Coastguard Worker   // function returns either kFailedMoveToNextSequence or
575*6dbdd20aSAndroid Build Coastguard Worker   // kFailedStayOnSameSequence, telling the caller to continue looking for
576*6dbdd20aSAndroid Build Coastguard Worker   // packets.
577*6dbdd20aSAndroid Build Coastguard Worker   ReadAheadResult ReadAhead(TracePacket*);
578*6dbdd20aSAndroid Build Coastguard Worker 
579*6dbdd20aSAndroid Build Coastguard Worker   // Deletes (by marking the record invalid and removing form the index) all
580*6dbdd20aSAndroid Build Coastguard Worker   // chunks from |wptr_| to |wptr_| + |bytes_to_clear|.
581*6dbdd20aSAndroid Build Coastguard Worker   // Returns:
582*6dbdd20aSAndroid Build Coastguard Worker   //   * The size of the gap left between the next valid Chunk and the end of
583*6dbdd20aSAndroid Build Coastguard Worker   //     the deletion range.
584*6dbdd20aSAndroid Build Coastguard Worker   //   * 0 if no next valid chunk exists (if the buffer is still zeroed).
585*6dbdd20aSAndroid Build Coastguard Worker   //   * -1 if the buffer |overwrite_policy_| == kDiscard and the deletion would
586*6dbdd20aSAndroid Build Coastguard Worker   //     cause unread chunks to be overwritten. In this case the buffer is left
587*6dbdd20aSAndroid Build Coastguard Worker   //     untouched.
588*6dbdd20aSAndroid Build Coastguard Worker   // Graphically, assume the initial situation is the following (|wptr_| = 10).
589*6dbdd20aSAndroid Build Coastguard Worker   // |0        |10 (wptr_)       |30       |40                 |60
590*6dbdd20aSAndroid Build Coastguard Worker   // +---------+-----------------+---------+-------------------+---------+
591*6dbdd20aSAndroid Build Coastguard Worker   // | Chunk 1 | Chunk 2         | Chunk 3 | Chunk 4           | Chunk 5 |
592*6dbdd20aSAndroid Build Coastguard Worker   // +---------+-----------------+---------+-------------------+---------+
593*6dbdd20aSAndroid Build Coastguard Worker   //           |_________Deletion range_______|~~return value~~|
594*6dbdd20aSAndroid Build Coastguard Worker   //
595*6dbdd20aSAndroid Build Coastguard Worker   // A call to DeleteNextChunksFor(32) will remove chunks 2,3,4 and return 18
596*6dbdd20aSAndroid Build Coastguard Worker   // (60 - 42), the distance between chunk 5 and the end of the deletion range.
597*6dbdd20aSAndroid Build Coastguard Worker   ssize_t DeleteNextChunksFor(size_t bytes_to_clear);
598*6dbdd20aSAndroid Build Coastguard Worker 
599*6dbdd20aSAndroid Build Coastguard Worker   // Decodes the boundaries of the next packet (or a fragment) pointed by
600*6dbdd20aSAndroid Build Coastguard Worker   // ChunkMeta and pushes that into |TracePacket|. It also increments the
601*6dbdd20aSAndroid Build Coastguard Worker   // |num_fragments_read| counter.
602*6dbdd20aSAndroid Build Coastguard Worker   // TracePacket can be nullptr, in which case the read state is still advanced.
603*6dbdd20aSAndroid Build Coastguard Worker   // When TracePacket is not nullptr, ProducerID must also be not null and will
604*6dbdd20aSAndroid Build Coastguard Worker   // be updated with the ProducerID that originally wrote the chunk.
605*6dbdd20aSAndroid Build Coastguard Worker   ReadPacketResult ReadNextPacketInChunk(ProducerAndWriterID,
606*6dbdd20aSAndroid Build Coastguard Worker                                          ChunkMeta*,
607*6dbdd20aSAndroid Build Coastguard Worker                                          TracePacket*);
608*6dbdd20aSAndroid Build Coastguard Worker 
DcheckIsAlignedAndWithinBounds(const uint8_t * ptr)609*6dbdd20aSAndroid Build Coastguard Worker   void DcheckIsAlignedAndWithinBounds(const uint8_t* ptr) const {
610*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(ptr >= begin() && ptr <= end() - sizeof(ChunkRecord));
611*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(
612*6dbdd20aSAndroid Build Coastguard Worker         (reinterpret_cast<uintptr_t>(ptr) & (alignof(ChunkRecord) - 1)) == 0);
613*6dbdd20aSAndroid Build Coastguard Worker   }
614*6dbdd20aSAndroid Build Coastguard Worker 
GetChunkRecordAt(uint8_t * ptr)615*6dbdd20aSAndroid Build Coastguard Worker   ChunkRecord* GetChunkRecordAt(uint8_t* ptr) {
616*6dbdd20aSAndroid Build Coastguard Worker     DcheckIsAlignedAndWithinBounds(ptr);
617*6dbdd20aSAndroid Build Coastguard Worker     // We may be accessing a new (empty) record.
618*6dbdd20aSAndroid Build Coastguard Worker     EnsureCommitted(static_cast<size_t>(ptr + sizeof(ChunkRecord) - begin()));
619*6dbdd20aSAndroid Build Coastguard Worker     return reinterpret_cast<ChunkRecord*>(ptr);
620*6dbdd20aSAndroid Build Coastguard Worker   }
621*6dbdd20aSAndroid Build Coastguard Worker 
EnsureCommitted(size_t size)622*6dbdd20aSAndroid Build Coastguard Worker   void EnsureCommitted(size_t size) {
623*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(size <= size_);
624*6dbdd20aSAndroid Build Coastguard Worker     data_.EnsureCommitted(size);
625*6dbdd20aSAndroid Build Coastguard Worker     used_size_ = std::max(used_size_, size);
626*6dbdd20aSAndroid Build Coastguard Worker   }
627*6dbdd20aSAndroid Build Coastguard Worker 
628*6dbdd20aSAndroid Build Coastguard Worker   void DiscardWrite();
629*6dbdd20aSAndroid Build Coastguard Worker 
630*6dbdd20aSAndroid Build Coastguard Worker   // |src| can be nullptr (in which case |size| must be ==
631*6dbdd20aSAndroid Build Coastguard Worker   // record.size - sizeof(ChunkRecord)), for the case of writing a padding
632*6dbdd20aSAndroid Build Coastguard Worker   // record. |wptr_| is NOT advanced by this function, the caller must do that.
WriteChunkRecord(uint8_t * wptr,const ChunkRecord & record,const uint8_t * src,size_t size)633*6dbdd20aSAndroid Build Coastguard Worker   void WriteChunkRecord(uint8_t* wptr,
634*6dbdd20aSAndroid Build Coastguard Worker                         const ChunkRecord& record,
635*6dbdd20aSAndroid Build Coastguard Worker                         const uint8_t* src,
636*6dbdd20aSAndroid Build Coastguard Worker                         size_t size) {
637*6dbdd20aSAndroid Build Coastguard Worker     // Note: |record.size| will be slightly bigger than |size| because of the
638*6dbdd20aSAndroid Build Coastguard Worker     // ChunkRecord header and rounding, to ensure that all ChunkRecord(s) are
639*6dbdd20aSAndroid Build Coastguard Worker     // multiple of sizeof(ChunkRecord). The invariant is:
640*6dbdd20aSAndroid Build Coastguard Worker     // record.size >= |size| + sizeof(ChunkRecord) (== if no rounding).
641*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(size <= ChunkRecord::kMaxSize);
642*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(record.size >= sizeof(record));
643*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(record.size % sizeof(record) == 0);
644*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(record.size >= size + sizeof(record));
645*6dbdd20aSAndroid Build Coastguard Worker     DcheckIsAlignedAndWithinBounds(wptr);
646*6dbdd20aSAndroid Build Coastguard Worker 
647*6dbdd20aSAndroid Build Coastguard Worker     // We may be writing to this area for the first time.
648*6dbdd20aSAndroid Build Coastguard Worker     EnsureCommitted(static_cast<size_t>(wptr + record.size - begin()));
649*6dbdd20aSAndroid Build Coastguard Worker 
650*6dbdd20aSAndroid Build Coastguard Worker     // Deliberately not a *D*CHECK.
651*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_CHECK(wptr + sizeof(record) + size <= end());
652*6dbdd20aSAndroid Build Coastguard Worker     memcpy(wptr, &record, sizeof(record));
653*6dbdd20aSAndroid Build Coastguard Worker     if (PERFETTO_LIKELY(src)) {
654*6dbdd20aSAndroid Build Coastguard Worker       // If the producer modifies the data in the shared memory buffer while we
655*6dbdd20aSAndroid Build Coastguard Worker       // are copying it to the central buffer, TSAN will (rightfully) flag that
656*6dbdd20aSAndroid Build Coastguard Worker       // as a race. However the entire purpose of copying the data into the
657*6dbdd20aSAndroid Build Coastguard Worker       // central buffer is that we can validate it without worrying that the
658*6dbdd20aSAndroid Build Coastguard Worker       // producer changes it from under our feet, so this race is benign. The
659*6dbdd20aSAndroid Build Coastguard Worker       // alternative would be to try computing which part of the buffer is safe
660*6dbdd20aSAndroid Build Coastguard Worker       // to read (assuming a well-behaving client), but the risk of introducing
661*6dbdd20aSAndroid Build Coastguard Worker       // a bug that way outweighs the benefit.
662*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(
663*6dbdd20aSAndroid Build Coastguard Worker           src, size, "Benign race when copying chunk from shared memory.")
664*6dbdd20aSAndroid Build Coastguard Worker       memcpy(wptr + sizeof(record), src, size);
665*6dbdd20aSAndroid Build Coastguard Worker     } else {
666*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_DCHECK(size == record.size - sizeof(record));
667*6dbdd20aSAndroid Build Coastguard Worker     }
668*6dbdd20aSAndroid Build Coastguard Worker     const size_t rounding_size = record.size - sizeof(record) - size;
669*6dbdd20aSAndroid Build Coastguard Worker     memset(wptr + sizeof(record) + size, 0, rounding_size);
670*6dbdd20aSAndroid Build Coastguard Worker   }
671*6dbdd20aSAndroid Build Coastguard Worker 
GetOffset(const void * _addr)672*6dbdd20aSAndroid Build Coastguard Worker   uint32_t GetOffset(const void* _addr) {
673*6dbdd20aSAndroid Build Coastguard Worker     const uintptr_t addr = reinterpret_cast<uintptr_t>(_addr);
674*6dbdd20aSAndroid Build Coastguard Worker     const uintptr_t buf_start = reinterpret_cast<uintptr_t>(begin());
675*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DCHECK(addr >= buf_start && addr < buf_start + size_);
676*6dbdd20aSAndroid Build Coastguard Worker     return static_cast<uint32_t>(addr - buf_start);
677*6dbdd20aSAndroid Build Coastguard Worker   }
678*6dbdd20aSAndroid Build Coastguard Worker 
begin()679*6dbdd20aSAndroid Build Coastguard Worker   uint8_t* begin() const { return reinterpret_cast<uint8_t*>(data_.Get()); }
end()680*6dbdd20aSAndroid Build Coastguard Worker   uint8_t* end() const { return begin() + size_; }
size_to_end()681*6dbdd20aSAndroid Build Coastguard Worker   size_t size_to_end() const { return static_cast<size_t>(end() - wptr_); }
682*6dbdd20aSAndroid Build Coastguard Worker 
683*6dbdd20aSAndroid Build Coastguard Worker   base::PagedMemory data_;
684*6dbdd20aSAndroid Build Coastguard Worker   size_t size_ = 0;            // Size in bytes of |data_|.
685*6dbdd20aSAndroid Build Coastguard Worker 
686*6dbdd20aSAndroid Build Coastguard Worker   // High watermark. The number of bytes (<= |size_|) written into the buffer
687*6dbdd20aSAndroid Build Coastguard Worker   // before the first wraparound. This increases as data is written into the
688*6dbdd20aSAndroid Build Coastguard Worker   // buffer and then saturates at |size_|. Used for CloneReadOnly().
689*6dbdd20aSAndroid Build Coastguard Worker   size_t used_size_ = 0;
690*6dbdd20aSAndroid Build Coastguard Worker 
691*6dbdd20aSAndroid Build Coastguard Worker   size_t max_chunk_size_ = 0;  // Max size in bytes allowed for a chunk.
692*6dbdd20aSAndroid Build Coastguard Worker   uint8_t* wptr_ = nullptr;    // Write pointer.
693*6dbdd20aSAndroid Build Coastguard Worker 
694*6dbdd20aSAndroid Build Coastguard Worker   // An index that keeps track of the positions and metadata of each
695*6dbdd20aSAndroid Build Coastguard Worker   // ChunkRecord.
696*6dbdd20aSAndroid Build Coastguard Worker   ChunkMap index_;
697*6dbdd20aSAndroid Build Coastguard Worker 
698*6dbdd20aSAndroid Build Coastguard Worker   // Read iterator used for ReadNext(). It is reset by calling BeginRead().
699*6dbdd20aSAndroid Build Coastguard Worker   // It becomes invalid after any call to methods that alters the |index_|.
700*6dbdd20aSAndroid Build Coastguard Worker   SequenceIterator read_iter_;
701*6dbdd20aSAndroid Build Coastguard Worker 
702*6dbdd20aSAndroid Build Coastguard Worker   // See comments at the top of the file.
703*6dbdd20aSAndroid Build Coastguard Worker   OverwritePolicy overwrite_policy_ = kOverwrite;
704*6dbdd20aSAndroid Build Coastguard Worker 
705*6dbdd20aSAndroid Build Coastguard Worker   // This buffer is a read-only snapshot obtained via Clone(). If this is true
706*6dbdd20aSAndroid Build Coastguard Worker   // calls to CopyChunkUntrusted() and TryPatchChunkContents() will CHECK().
707*6dbdd20aSAndroid Build Coastguard Worker   bool read_only_ = false;
708*6dbdd20aSAndroid Build Coastguard Worker 
709*6dbdd20aSAndroid Build Coastguard Worker   // Only used when |overwrite_policy_ == kDiscard|. This is set the first time
710*6dbdd20aSAndroid Build Coastguard Worker   // a write fails because it would overwrite unread chunks.
711*6dbdd20aSAndroid Build Coastguard Worker   bool discard_writes_ = false;
712*6dbdd20aSAndroid Build Coastguard Worker 
713*6dbdd20aSAndroid Build Coastguard Worker   // Keeps track of the highest ChunkID written for a given sequence, taking
714*6dbdd20aSAndroid Build Coastguard Worker   // into account a potential overflow of ChunkIDs. In the case of overflow,
715*6dbdd20aSAndroid Build Coastguard Worker   // stores the highest ChunkID written since the overflow.
716*6dbdd20aSAndroid Build Coastguard Worker   //
717*6dbdd20aSAndroid Build Coastguard Worker   // TODO(primiano): should clean up keys from this map. Right now it grows
718*6dbdd20aSAndroid Build Coastguard Worker   // without bounds (although realistically is not a problem unless we have too
719*6dbdd20aSAndroid Build Coastguard Worker   // many producers/writers within the same trace session).
720*6dbdd20aSAndroid Build Coastguard Worker   std::map<std::pair<ProducerID, WriterID>, ChunkID> last_chunk_id_written_;
721*6dbdd20aSAndroid Build Coastguard Worker 
722*6dbdd20aSAndroid Build Coastguard Worker   // Statistics about buffer usage.
723*6dbdd20aSAndroid Build Coastguard Worker   TraceStats::BufferStats stats_;
724*6dbdd20aSAndroid Build Coastguard Worker 
725*6dbdd20aSAndroid Build Coastguard Worker   // Per-{Producer, Writer} statistics.
726*6dbdd20aSAndroid Build Coastguard Worker   WriterStatsMap writer_stats_;
727*6dbdd20aSAndroid Build Coastguard Worker 
728*6dbdd20aSAndroid Build Coastguard Worker   // Set to true upon the very first call to CopyChunkUntrusted() and never
729*6dbdd20aSAndroid Build Coastguard Worker   // cleared. This is used to tell if the buffer has never been used since its
730*6dbdd20aSAndroid Build Coastguard Worker   // creation (which in turn is used to optimize `clear_before_clone`).
731*6dbdd20aSAndroid Build Coastguard Worker   bool has_data_ = false;
732*6dbdd20aSAndroid Build Coastguard Worker 
733*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_DCHECK_IS_ON()
734*6dbdd20aSAndroid Build Coastguard Worker   bool changed_since_last_read_ = false;
735*6dbdd20aSAndroid Build Coastguard Worker #endif
736*6dbdd20aSAndroid Build Coastguard Worker 
737*6dbdd20aSAndroid Build Coastguard Worker   // When true disable some DCHECKs that have been put in place to detect
738*6dbdd20aSAndroid Build Coastguard Worker   // bugs in the producers. This is for tests that feed malicious inputs and
739*6dbdd20aSAndroid Build Coastguard Worker   // hence mimic a buggy producer.
740*6dbdd20aSAndroid Build Coastguard Worker   bool suppress_client_dchecks_for_testing_ = false;
741*6dbdd20aSAndroid Build Coastguard Worker };
742*6dbdd20aSAndroid Build Coastguard Worker 
743*6dbdd20aSAndroid Build Coastguard Worker }  // namespace perfetto
744*6dbdd20aSAndroid Build Coastguard Worker 
745*6dbdd20aSAndroid Build Coastguard Worker #endif  // SRC_TRACING_SERVICE_TRACE_BUFFER_H_
746