blob: 8929ee5a0191ec6baf13720cef3ab807085cc425 [file] [log] [blame]
Yabin Cui9759e1b2015-04-28 15:54:13 -07001/*
2 * Copyright (C) 2015 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#ifndef SIMPLE_PERF_RECORD_H_
18#define SIMPLE_PERF_RECORD_H_
19
Yabin Cuib7f481f2015-10-23 19:48:42 -070020#include <stdio.h>
Dan Albert918e4b72015-08-11 15:59:43 -070021#include <sys/types.h>
22
Yabin Cuiffaa9122016-01-15 15:25:48 -080023#include <memory>
Yabin Cuif469c3d2015-10-07 15:00:46 -070024#include <queue>
Yabin Cui9759e1b2015-04-28 15:54:13 -070025#include <string>
26#include <vector>
27
Yabin Cuib4212972016-05-25 14:08:05 -070028#include <android-base/logging.h>
29
Yabin Cui8f622512015-05-05 19:58:07 -070030#include "build_id.h"
Yabin Cui9759e1b2015-04-28 15:54:13 -070031#include "perf_event.h"
32
33struct KernelMmap;
34struct ModuleMmap;
35struct ThreadComm;
36struct ThreadMmap;
37
38enum user_record_type {
Yabin Cuib4212972016-05-25 14:08:05 -070039 PERF_RECORD_USER_DEFINED_TYPE_START = 64,
Yabin Cui9759e1b2015-04-28 15:54:13 -070040 PERF_RECORD_ATTR = 64,
41 PERF_RECORD_EVENT_TYPE,
42 PERF_RECORD_TRACING_DATA,
43 PERF_RECORD_BUILD_ID,
44 PERF_RECORD_FINISHED_ROUND,
Yabin Cuib4212972016-05-25 14:08:05 -070045
46 SIMPLE_PERF_RECORD_TYPE_START = 32768,
47 SIMPLE_PERF_RECORD_KERNEL_SYMBOL,
Yabin Cui767dd172016-06-02 21:02:43 -070048 SIMPLE_PERF_RECORD_DSO,
49 SIMPLE_PERF_RECORD_SYMBOL,
Yabin Cui1761a272016-06-23 17:11:14 -070050 SIMPLE_PERF_RECORD_SPLIT,
51 SIMPLE_PERF_RECORD_SPLIT_END,
Yabin Cui9759e1b2015-04-28 15:54:13 -070052};
53
Yabin Cui1761a272016-06-23 17:11:14 -070054// perf_event_header uses u16 to store record size. However, that is not
55// enough for storing records like KERNEL_SYMBOL or TRACING_DATA. So define
56// a simpleperf_record_header struct to store record header for simpleperf
57// defined records (type > SIMPLE_PERF_RECORD_TYPE_START).
58struct simpleperf_record_header {
59 uint32_t type;
60 uint16_t size1;
61 uint16_t size0;
62};
63
64static_assert(
65 sizeof(simpleperf_record_header) == sizeof(perf_event_header),
66 "simpleperf_record_header should have the same size as perf_event_header");
67
Yabin Cui9759e1b2015-04-28 15:54:13 -070068struct PerfSampleIpType {
69 uint64_t ip;
70};
71
72struct PerfSampleTidType {
73 uint32_t pid, tid;
74};
75
76struct PerfSampleTimeType {
77 uint64_t time;
78};
79
80struct PerfSampleAddrType {
81 uint64_t addr;
82};
83
84struct PerfSampleIdType {
85 uint64_t id;
86};
87
88struct PerfSampleStreamIdType {
89 uint64_t stream_id;
90};
91
92struct PerfSampleCpuType {
93 uint32_t cpu, res;
94};
95
96struct PerfSamplePeriodType {
97 uint64_t period;
98};
99
Yabin Cui6e8a9a42015-06-15 14:36:43 -0700100struct PerfSampleCallChainType {
101 std::vector<uint64_t> ips;
102};
103
Yabin Cuibfc11b62015-08-19 10:12:51 -0700104struct PerfSampleRawType {
105 std::vector<char> data;
106};
107
Yabin Cuib64a8632016-05-24 18:23:33 -0700108struct BranchStackItemType {
109 uint64_t from;
110 uint64_t to;
111 uint64_t flags;
112};
113
Yabin Cuiddddc062015-06-02 17:54:52 -0700114struct PerfSampleBranchStackType {
Yabin Cuiddddc062015-06-02 17:54:52 -0700115 std::vector<BranchStackItemType> stack;
116};
117
Yabin Cui76769e52015-07-13 12:23:54 -0700118struct PerfSampleRegsUserType {
119 uint64_t abi;
120 uint64_t reg_mask;
121 std::vector<uint64_t> regs;
122};
123
124struct PerfSampleStackUserType {
125 std::vector<char> data;
126 uint64_t dyn_size;
127};
128
Yabin Cui1761a272016-06-23 17:11:14 -0700129struct RecordHeader {
130 public:
131 uint32_t type;
132 uint16_t misc;
133 uint32_t size;
134
135 RecordHeader() : type(0), misc(0), size(0) {}
136
137 RecordHeader(const char* p) {
138 auto pheader = reinterpret_cast<const perf_event_header*>(p);
139 if (pheader->type < SIMPLE_PERF_RECORD_TYPE_START) {
140 type = pheader->type;
141 misc = pheader->misc;
142 size = pheader->size;
143 } else {
144 auto sheader = reinterpret_cast<const simpleperf_record_header*>(p);
145 type = sheader->type;
146 misc = 0;
147 size = (sheader->size1 << 16) | sheader->size0;
148 }
149 }
150
151 void MoveToBinaryFormat(char*& p) const {
152 if (type < SIMPLE_PERF_RECORD_TYPE_START) {
153 auto pheader = reinterpret_cast<perf_event_header*>(p);
154 pheader->type = type;
155 pheader->misc = misc;
156 CHECK_LT(size, 1u << 16);
157 pheader->size = static_cast<uint16_t>(size);
158 } else {
159 auto sheader = reinterpret_cast<simpleperf_record_header*>(p);
160 sheader->type = type;
161 CHECK_EQ(misc, 0u);
162 sheader->size1 = size >> 16;
163 sheader->size0 = size & 0xffff;
164 }
165 p += sizeof(perf_event_header);
166 }
167};
168
Yabin Cui767dd172016-06-02 21:02:43 -0700169// SampleId is optional at the end of a record in binary format. Its content is
170// determined by sample_id_all and sample_type in perf_event_attr. To avoid the
171// complexity of referring to perf_event_attr each time, we copy sample_id_all
172// and sample_type inside the SampleId structure.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700173struct SampleId {
174 bool sample_id_all;
175 uint64_t sample_type;
176
Yabin Cui767dd172016-06-02 21:02:43 -0700177 PerfSampleTidType tid_data; // Valid if sample_id_all && PERF_SAMPLE_TID.
178 PerfSampleTimeType time_data; // Valid if sample_id_all && PERF_SAMPLE_TIME.
179 PerfSampleIdType id_data; // Valid if sample_id_all && PERF_SAMPLE_ID.
180 PerfSampleStreamIdType
181 stream_id_data; // Valid if sample_id_all && PERF_SAMPLE_STREAM_ID.
182 PerfSampleCpuType cpu_data; // Valid if sample_id_all && PERF_SAMPLE_CPU.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700183
184 SampleId();
185
186 // Create the content of sample_id. It depends on the attr we use.
Yabin Cui2d6efe42016-04-01 20:22:35 -0700187 size_t CreateContent(const perf_event_attr& attr, uint64_t event_id);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700188
189 // Parse sample_id from binary format in the buffer pointed by p.
Yabin Cui767dd172016-06-02 21:02:43 -0700190 void ReadFromBinaryFormat(const perf_event_attr& attr, const char* p,
191 const char* end);
Yabin Cui9759e1b2015-04-28 15:54:13 -0700192
193 // Write the binary format of sample_id to the buffer pointed by p.
194 void WriteToBinaryFormat(char*& p) const;
195 void Dump(size_t indent) const;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800196 size_t Size() const;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700197};
198
Yabin Cui767dd172016-06-02 21:02:43 -0700199// Usually one record contains the following three parts in order in binary
200// format:
Yabin Cui1761a272016-06-23 17:11:14 -0700201// RecordHeader (at the head of a record, containing type and size info)
Yabin Cui9759e1b2015-04-28 15:54:13 -0700202// data depends on the record type
Yabin Cui1761a272016-06-23 17:11:14 -0700203// SampleId (optional part at the end of a record)
204// We hold the common parts (RecordHeader and SampleId) in the base class
Yabin Cui767dd172016-06-02 21:02:43 -0700205// Record, and hold the type specific data part in classes derived from Record.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700206struct Record {
Yabin Cui1761a272016-06-23 17:11:14 -0700207 RecordHeader header;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700208 SampleId sample_id;
209
Yabin Cui1761a272016-06-23 17:11:14 -0700210 Record() {}
211 Record(const char* p) : header(p) {}
Yabin Cui9759e1b2015-04-28 15:54:13 -0700212
Yabin Cui767dd172016-06-02 21:02:43 -0700213 virtual ~Record() {}
Yabin Cuib7f481f2015-10-23 19:48:42 -0700214
Yabin Cui767dd172016-06-02 21:02:43 -0700215 uint32_t type() const { return header.type; }
Yabin Cuib7f481f2015-10-23 19:48:42 -0700216
Yabin Cui767dd172016-06-02 21:02:43 -0700217 uint16_t misc() const { return header.misc; }
Yabin Cuib4212972016-05-25 14:08:05 -0700218
Yabin Cui1761a272016-06-23 17:11:14 -0700219 uint32_t size() const { return header.size; }
Yabin Cuib4212972016-05-25 14:08:05 -0700220
Yabin Cui767dd172016-06-02 21:02:43 -0700221 static uint32_t header_size() { return sizeof(perf_event_header); }
Yabin Cuib4212972016-05-25 14:08:05 -0700222
Yabin Cuib64a8632016-05-24 18:23:33 -0700223 bool InKernel() const {
Yabin Cui767dd172016-06-02 21:02:43 -0700224 return (header.misc & PERF_RECORD_MISC_CPUMODE_MASK) ==
225 PERF_RECORD_MISC_KERNEL;
Yabin Cuib64a8632016-05-24 18:23:33 -0700226 }
227
Yabin Cuib4212972016-05-25 14:08:05 -0700228 void SetTypeAndMisc(uint32_t type, uint16_t misc) {
229 header.type = type;
230 header.misc = misc;
231 }
232
Yabin Cui1761a272016-06-23 17:11:14 -0700233 void SetSize(uint32_t size) { header.size = size; }
Yabin Cuib4212972016-05-25 14:08:05 -0700234
Yabin Cui9759e1b2015-04-28 15:54:13 -0700235 void Dump(size_t indent = 0) const;
Yabin Cuicb84c982015-09-30 17:22:35 -0700236 virtual std::vector<char> BinaryFormat() const = 0;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700237 virtual uint64_t Timestamp() const;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700238
239 protected:
Yabin Cuicb84c982015-09-30 17:22:35 -0700240 virtual void DumpData(size_t) const = 0;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700241};
242
243struct MmapRecord : public Record {
244 struct MmapRecordDataType {
245 uint32_t pid, tid;
246 uint64_t addr;
247 uint64_t len;
248 uint64_t pgoff;
249 } data;
250 std::string filename;
251
Yabin Cuicb84c982015-09-30 17:22:35 -0700252 MmapRecord() { // For CreateMmapRecord.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700253 }
254
Yabin Cui1761a272016-06-23 17:11:14 -0700255 MmapRecord(const perf_event_attr& attr, const char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700256 std::vector<char> BinaryFormat() const override;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800257 void AdjustSizeBasedOnData();
Yabin Cui8f622512015-05-05 19:58:07 -0700258
Yabin Cui767dd172016-06-02 21:02:43 -0700259 static MmapRecord Create(const perf_event_attr& attr, bool in_kernel,
260 uint32_t pid, uint32_t tid, uint64_t addr,
261 uint64_t len, uint64_t pgoff,
262 const std::string& filename, uint64_t event_id);
263
Yabin Cui8f622512015-05-05 19:58:07 -0700264 protected:
265 void DumpData(size_t indent) const override;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700266};
267
Yabin Cui41d4ba92015-06-22 12:27:58 -0700268struct Mmap2Record : public Record {
269 struct Mmap2RecordDataType {
270 uint32_t pid, tid;
271 uint64_t addr;
272 uint64_t len;
273 uint64_t pgoff;
274 uint32_t maj;
275 uint32_t min;
276 uint64_t ino;
277 uint64_t ino_generation;
278 uint32_t prot, flags;
279 } data;
280 std::string filename;
281
Yabin Cui767dd172016-06-02 21:02:43 -0700282 Mmap2Record() {}
Yabin Cui41d4ba92015-06-22 12:27:58 -0700283
Yabin Cui1761a272016-06-23 17:11:14 -0700284 Mmap2Record(const perf_event_attr& attr, const char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700285 std::vector<char> BinaryFormat() const override;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800286 void AdjustSizeBasedOnData();
Yabin Cui41d4ba92015-06-22 12:27:58 -0700287
288 protected:
289 void DumpData(size_t indent) const override;
290};
291
Yabin Cui9759e1b2015-04-28 15:54:13 -0700292struct CommRecord : public Record {
293 struct CommRecordDataType {
294 uint32_t pid, tid;
295 } data;
296 std::string comm;
297
Yabin Cui767dd172016-06-02 21:02:43 -0700298 CommRecord() {}
Yabin Cui9759e1b2015-04-28 15:54:13 -0700299
Yabin Cui1761a272016-06-23 17:11:14 -0700300 CommRecord(const perf_event_attr& attr, const char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700301 std::vector<char> BinaryFormat() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700302
Yabin Cui767dd172016-06-02 21:02:43 -0700303 static CommRecord Create(const perf_event_attr& attr, uint32_t pid,
304 uint32_t tid, const std::string& comm,
305 uint64_t event_id);
306
Yabin Cui8f622512015-05-05 19:58:07 -0700307 protected:
308 void DumpData(size_t indent) const override;
Yabin Cui9759e1b2015-04-28 15:54:13 -0700309};
310
Yabin Cui41d4ba92015-06-22 12:27:58 -0700311struct ExitOrForkRecord : public Record {
312 struct ExitOrForkRecordDataType {
Yabin Cui9759e1b2015-04-28 15:54:13 -0700313 uint32_t pid, ppid;
314 uint32_t tid, ptid;
315 uint64_t time;
316 } data;
317
Yabin Cui767dd172016-06-02 21:02:43 -0700318 ExitOrForkRecord() {}
Yabin Cui1761a272016-06-23 17:11:14 -0700319 ExitOrForkRecord(const perf_event_attr& attr, const char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700320 std::vector<char> BinaryFormat() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700321
322 protected:
Yabin Cui9759e1b2015-04-28 15:54:13 -0700323 void DumpData(size_t indent) const override;
324};
325
Yabin Cui41d4ba92015-06-22 12:27:58 -0700326struct ExitRecord : public ExitOrForkRecord {
Yabin Cui1761a272016-06-23 17:11:14 -0700327 ExitRecord(const perf_event_attr& attr, const char* p)
328 : ExitOrForkRecord(attr, p) {}
Yabin Cui41d4ba92015-06-22 12:27:58 -0700329};
330
331struct ForkRecord : public ExitOrForkRecord {
Yabin Cui767dd172016-06-02 21:02:43 -0700332 ForkRecord() {}
Yabin Cui1761a272016-06-23 17:11:14 -0700333 ForkRecord(const perf_event_attr& attr, const char* p)
334 : ExitOrForkRecord(attr, p) {}
Yabin Cui767dd172016-06-02 21:02:43 -0700335
336 static ForkRecord Create(const perf_event_attr& attr, uint32_t pid,
337 uint32_t tid, uint32_t ppid, uint32_t ptid,
338 uint64_t event_id);
Yabin Cui41d4ba92015-06-22 12:27:58 -0700339};
340
Yabin Cuie5adc132016-06-22 11:37:26 -0700341struct LostRecord : public Record {
342 uint64_t id;
343 uint64_t lost;
344
Yabin Cui1761a272016-06-23 17:11:14 -0700345 LostRecord() {}
Yabin Cuie5adc132016-06-22 11:37:26 -0700346
Yabin Cui1761a272016-06-23 17:11:14 -0700347 LostRecord(const perf_event_attr& attr, const char* p);
Yabin Cuie5adc132016-06-22 11:37:26 -0700348 std::vector<char> BinaryFormat() const override;
349
350 protected:
351 void DumpData(size_t indent) const override;
352};
353
Yabin Cui9759e1b2015-04-28 15:54:13 -0700354struct SampleRecord : public Record {
Yabin Cui767dd172016-06-02 21:02:43 -0700355 uint64_t sample_type; // sample_type is a bit mask determining which fields
356 // below are valid.
Yabin Cui9759e1b2015-04-28 15:54:13 -0700357
358 PerfSampleIpType ip_data; // Valid if PERF_SAMPLE_IP.
359 PerfSampleTidType tid_data; // Valid if PERF_SAMPLE_TID.
360 PerfSampleTimeType time_data; // Valid if PERF_SAMPLE_TIME.
361 PerfSampleAddrType addr_data; // Valid if PERF_SAMPLE_ADDR.
362 PerfSampleIdType id_data; // Valid if PERF_SAMPLE_ID.
363 PerfSampleStreamIdType stream_id_data; // Valid if PERF_SAMPLE_STREAM_ID.
364 PerfSampleCpuType cpu_data; // Valid if PERF_SAMPLE_CPU.
365 PerfSamplePeriodType period_data; // Valid if PERF_SAMPLE_PERIOD.
366
Yabin Cui767dd172016-06-02 21:02:43 -0700367 PerfSampleCallChainType callchain_data; // Valid if PERF_SAMPLE_CALLCHAIN.
368 PerfSampleRawType raw_data; // Valid if PERF_SAMPLE_RAW.
369 PerfSampleBranchStackType
370 branch_stack_data; // Valid if PERF_SAMPLE_BRANCH_STACK.
371 PerfSampleRegsUserType regs_user_data; // Valid if PERF_SAMPLE_REGS_USER.
372 PerfSampleStackUserType stack_user_data; // Valid if PERF_SAMPLE_STACK_USER.
Yabin Cuiddddc062015-06-02 17:54:52 -0700373
Yabin Cui1761a272016-06-23 17:11:14 -0700374 SampleRecord(const perf_event_attr& attr, const char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700375 std::vector<char> BinaryFormat() const override;
376 void AdjustSizeBasedOnData();
Yabin Cuif469c3d2015-10-07 15:00:46 -0700377 uint64_t Timestamp() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700378
379 protected:
380 void DumpData(size_t indent) const override;
381};
382
Yabin Cui767dd172016-06-02 21:02:43 -0700383// BuildIdRecord is defined in user-space, stored in BuildId feature section in
384// record file.
Yabin Cui8f622512015-05-05 19:58:07 -0700385struct BuildIdRecord : public Record {
386 uint32_t pid;
387 BuildId build_id;
388 std::string filename;
389
Yabin Cui767dd172016-06-02 21:02:43 -0700390 BuildIdRecord() {}
Yabin Cui8f622512015-05-05 19:58:07 -0700391
Yabin Cui1761a272016-06-23 17:11:14 -0700392 BuildIdRecord(const char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700393 std::vector<char> BinaryFormat() const override;
394
Yabin Cui767dd172016-06-02 21:02:43 -0700395 static BuildIdRecord Create(bool in_kernel, pid_t pid,
396 const BuildId& build_id,
397 const std::string& filename);
398
Yabin Cuicb84c982015-09-30 17:22:35 -0700399 protected:
400 void DumpData(size_t indent) const override;
401};
402
Yabin Cuib4212972016-05-25 14:08:05 -0700403struct KernelSymbolRecord : public Record {
Yabin Cuib4212972016-05-25 14:08:05 -0700404 std::string kallsyms;
405
Yabin Cui767dd172016-06-02 21:02:43 -0700406 KernelSymbolRecord() {}
Yabin Cuib4212972016-05-25 14:08:05 -0700407
Yabin Cui1761a272016-06-23 17:11:14 -0700408 KernelSymbolRecord(const char* p);
Yabin Cuib4212972016-05-25 14:08:05 -0700409 std::vector<char> BinaryFormat() const override;
410
Yabin Cui1761a272016-06-23 17:11:14 -0700411 static KernelSymbolRecord Create(std::string kallsyms);
Yabin Cui767dd172016-06-02 21:02:43 -0700412
Yabin Cuib4212972016-05-25 14:08:05 -0700413 protected:
414 void DumpData(size_t indent) const override;
415};
416
Yabin Cui767dd172016-06-02 21:02:43 -0700417struct DsoRecord : public Record {
418 uint64_t dso_type;
419 uint64_t dso_id;
Yabin Cuic855ecc2016-07-11 17:04:54 -0700420 uint64_t min_vaddr;
Yabin Cui767dd172016-06-02 21:02:43 -0700421 std::string dso_name;
422
423 DsoRecord() {}
424
Yabin Cui1761a272016-06-23 17:11:14 -0700425 DsoRecord(const char* p);
Yabin Cui767dd172016-06-02 21:02:43 -0700426 std::vector<char> BinaryFormat() const override;
427
428 static DsoRecord Create(uint64_t dso_type, uint64_t dso_id,
Yabin Cuic855ecc2016-07-11 17:04:54 -0700429 const std::string& dso_name, uint64_t min_vaddr);
Yabin Cui767dd172016-06-02 21:02:43 -0700430
431 protected:
432 void DumpData(size_t indent) const override;
433};
434
435struct SymbolRecord : public Record {
436 uint64_t addr;
437 uint64_t len;
438 uint64_t dso_id;
439 std::string name;
440
441 SymbolRecord() {}
442
Yabin Cui1761a272016-06-23 17:11:14 -0700443 SymbolRecord(const char* p);
Yabin Cui767dd172016-06-02 21:02:43 -0700444 std::vector<char> BinaryFormat() const override;
445
446 static SymbolRecord Create(uint64_t addr, uint64_t len,
447 const std::string& name, uint64_t dso_id);
Yabin Cui1761a272016-06-23 17:11:14 -0700448
Yabin Cui4f41df62016-06-01 17:29:06 -0700449 protected:
450 void DumpData(size_t indent) const override;
451};
Yabin Cui767dd172016-06-02 21:02:43 -0700452
Yabin Cui4f41df62016-06-01 17:29:06 -0700453struct TracingDataRecord : public Record {
454 std::vector<char> data;
455
Yabin Cui1761a272016-06-23 17:11:14 -0700456 TracingDataRecord() {}
Yabin Cui4f41df62016-06-01 17:29:06 -0700457
Yabin Cui1761a272016-06-23 17:11:14 -0700458 TracingDataRecord(const char* p);
Yabin Cui4f41df62016-06-01 17:29:06 -0700459 std::vector<char> BinaryFormat() const override;
460
461 static TracingDataRecord Create(std::vector<char> tracing_data);
Yabin Cuie5adc132016-06-22 11:37:26 -0700462
Yabin Cui767dd172016-06-02 21:02:43 -0700463 protected:
464 void DumpData(size_t indent) const override;
465};
466
467// UnknownRecord is used for unknown record types, it makes sure all unknown
Yabin Cui4f41df62016-06-01 17:29:06 -0700468// records are not changed when modifying perf.data.
Yabin Cuicb84c982015-09-30 17:22:35 -0700469struct UnknownRecord : public Record {
470 std::vector<char> data;
471
Yabin Cui1761a272016-06-23 17:11:14 -0700472 UnknownRecord(const char* p);
Yabin Cuicb84c982015-09-30 17:22:35 -0700473 std::vector<char> BinaryFormat() const override;
Yabin Cui8f622512015-05-05 19:58:07 -0700474
475 protected:
Yabin Cui9759e1b2015-04-28 15:54:13 -0700476 void DumpData(size_t indent) const override;
477};
478
Yabin Cui767dd172016-06-02 21:02:43 -0700479std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr,
Yabin Cui1761a272016-06-23 17:11:14 -0700480 uint32_t type, const char* p);
Yabin Cui767dd172016-06-02 21:02:43 -0700481std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(
482 const perf_event_attr& attr, const char* buf, size_t buf_size);
483
Yabin Cuif469c3d2015-10-07 15:00:46 -0700484// RecordCache is a cache used when receiving records from the kernel.
485// It sorts received records based on type and timestamp, and pops records
486// in sorted order. Records from the kernel need to be sorted because
487// records may come from different cpus at the same time, and it is affected
488// by the order in which we collect records from different cpus.
Yabin Cui767dd172016-06-02 21:02:43 -0700489// RecordCache pushes records and pops sorted record online. It uses two checks
490// to help ensure that records are popped in order. Each time we pop a record A,
491// it is the earliest record among all records in the cache. In addition, we
492// have checks for min_cache_size and min_time_diff. For min_cache_size check,
493// we check if the cache size >= min_cache_size, which is based on the
494// assumption that if we have received (min_cache_size - 1) records after
495// record A, we are not likely to receive a record earlier than A. For
496// min_time_diff check, we check if record A is generated min_time_diff ns
497// earlier than the latest record, which is based on the assumption that if we
498// have received a record for time t, we are not likely to receive a record for
499// time (t - min_time_diff) or earlier.
Yabin Cuif469c3d2015-10-07 15:00:46 -0700500class RecordCache {
501 public:
Yabin Cui2d6efe42016-04-01 20:22:35 -0700502 RecordCache(bool has_timestamp, size_t min_cache_size = 1000u,
Yabin Cuib7f481f2015-10-23 19:48:42 -0700503 uint64_t min_time_diff_in_ns = 1000000u);
Yabin Cuif469c3d2015-10-07 15:00:46 -0700504 ~RecordCache();
Yabin Cuib7f481f2015-10-23 19:48:42 -0700505 void Push(std::unique_ptr<Record> record);
Yabin Cui2d6efe42016-04-01 20:22:35 -0700506 void Push(std::vector<std::unique_ptr<Record>> records);
Yabin Cuif469c3d2015-10-07 15:00:46 -0700507 std::unique_ptr<Record> Pop();
508 std::vector<std::unique_ptr<Record>> PopAll();
509
510 private:
Yabin Cui4913c122016-01-11 17:15:55 -0800511 struct RecordWithSeq {
512 uint32_t seq;
Yabin Cui767dd172016-06-02 21:02:43 -0700513 Record* record;
Yabin Cui4913c122016-01-11 17:15:55 -0800514
Yabin Cui86d93402016-07-06 12:01:35 -0700515 RecordWithSeq(uint32_t seq, Record* record) : seq(seq), record(record) {
516 }
Yabin Cui4913c122016-01-11 17:15:55 -0800517 bool IsHappensBefore(const RecordWithSeq& other) const;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700518 };
519
Yabin Cui4913c122016-01-11 17:15:55 -0800520 struct RecordComparator {
521 bool operator()(const RecordWithSeq& r1, const RecordWithSeq& r2);
522 };
523
Yabin Cuif469c3d2015-10-07 15:00:46 -0700524 bool has_timestamp_;
525 size_t min_cache_size_;
526 uint64_t min_time_diff_in_ns_;
527 uint64_t last_time_;
Yabin Cui4913c122016-01-11 17:15:55 -0800528 uint32_t cur_seq_;
529 std::priority_queue<RecordWithSeq, std::vector<RecordWithSeq>,
Yabin Cui767dd172016-06-02 21:02:43 -0700530 RecordComparator> queue_;
Yabin Cuif469c3d2015-10-07 15:00:46 -0700531};
532
Yabin Cui9759e1b2015-04-28 15:54:13 -0700533#endif // SIMPLE_PERF_RECORD_H_