1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker *
4*288bf522SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker *
8*288bf522SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker *
10*288bf522SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker */
16*288bf522SAndroid Build Coastguard Worker
17*288bf522SAndroid Build Coastguard Worker #include "RecordReadThread.h"
18*288bf522SAndroid Build Coastguard Worker
19*288bf522SAndroid Build Coastguard Worker #include <sys/resource.h>
20*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
21*288bf522SAndroid Build Coastguard Worker
22*288bf522SAndroid Build Coastguard Worker #include <algorithm>
23*288bf522SAndroid Build Coastguard Worker #include <unordered_map>
24*288bf522SAndroid Build Coastguard Worker
25*288bf522SAndroid Build Coastguard Worker #include "environment.h"
26*288bf522SAndroid Build Coastguard Worker #include "event_type.h"
27*288bf522SAndroid Build Coastguard Worker #include "record.h"
28*288bf522SAndroid Build Coastguard Worker #include "utils.h"
29*288bf522SAndroid Build Coastguard Worker
30*288bf522SAndroid Build Coastguard Worker namespace simpleperf {
31*288bf522SAndroid Build Coastguard Worker
32*288bf522SAndroid Build Coastguard Worker static constexpr size_t kDefaultLowBufferLevel = 10 * kMegabyte;
33*288bf522SAndroid Build Coastguard Worker static constexpr size_t kDefaultCriticalBufferLevel = 5 * kMegabyte;
34*288bf522SAndroid Build Coastguard Worker
RecordBuffer(size_t buffer_size)35*288bf522SAndroid Build Coastguard Worker RecordBuffer::RecordBuffer(size_t buffer_size)
36*288bf522SAndroid Build Coastguard Worker : read_head_(0), write_head_(0), buffer_size_(buffer_size), buffer_(new char[buffer_size]) {}
37*288bf522SAndroid Build Coastguard Worker
GetFreeSize() const38*288bf522SAndroid Build Coastguard Worker size_t RecordBuffer::GetFreeSize() const {
39*288bf522SAndroid Build Coastguard Worker size_t write_head = write_head_.load(std::memory_order_relaxed);
40*288bf522SAndroid Build Coastguard Worker size_t read_head = read_head_.load(std::memory_order_relaxed);
41*288bf522SAndroid Build Coastguard Worker size_t write_tail = read_head > 0 ? read_head - 1 : buffer_size_ - 1;
42*288bf522SAndroid Build Coastguard Worker if (write_head <= write_tail) {
43*288bf522SAndroid Build Coastguard Worker return write_tail - write_head;
44*288bf522SAndroid Build Coastguard Worker }
45*288bf522SAndroid Build Coastguard Worker return buffer_size_ - write_head + write_tail;
46*288bf522SAndroid Build Coastguard Worker }
47*288bf522SAndroid Build Coastguard Worker
AllocWriteSpace(size_t record_size)48*288bf522SAndroid Build Coastguard Worker char* RecordBuffer::AllocWriteSpace(size_t record_size) {
49*288bf522SAndroid Build Coastguard Worker size_t write_head = write_head_.load(std::memory_order_relaxed);
50*288bf522SAndroid Build Coastguard Worker size_t read_head = read_head_.load(std::memory_order_acquire);
51*288bf522SAndroid Build Coastguard Worker size_t write_tail = read_head > 0 ? read_head - 1 : buffer_size_ - 1;
52*288bf522SAndroid Build Coastguard Worker cur_write_record_size_ = record_size;
53*288bf522SAndroid Build Coastguard Worker if (write_head < write_tail) {
54*288bf522SAndroid Build Coastguard Worker if (write_head + record_size > write_tail) {
55*288bf522SAndroid Build Coastguard Worker return nullptr;
56*288bf522SAndroid Build Coastguard Worker }
57*288bf522SAndroid Build Coastguard Worker } else if (write_head + record_size > buffer_size_) {
58*288bf522SAndroid Build Coastguard Worker // Not enough space at the end of the buffer, need to wrap to the start of the buffer.
59*288bf522SAndroid Build Coastguard Worker if (write_tail < record_size) {
60*288bf522SAndroid Build Coastguard Worker return nullptr;
61*288bf522SAndroid Build Coastguard Worker }
62*288bf522SAndroid Build Coastguard Worker if (buffer_size_ - write_head >= sizeof(perf_event_header)) {
63*288bf522SAndroid Build Coastguard Worker // Set the size field in perf_event_header to 0. So GetCurrentRecord() can wrap to the start
64*288bf522SAndroid Build Coastguard Worker // of the buffer when size is 0.
65*288bf522SAndroid Build Coastguard Worker memset(buffer_.get() + write_head, 0, sizeof(perf_event_header));
66*288bf522SAndroid Build Coastguard Worker }
67*288bf522SAndroid Build Coastguard Worker cur_write_record_size_ += buffer_size_ - write_head;
68*288bf522SAndroid Build Coastguard Worker write_head = 0;
69*288bf522SAndroid Build Coastguard Worker }
70*288bf522SAndroid Build Coastguard Worker return buffer_.get() + write_head;
71*288bf522SAndroid Build Coastguard Worker }
72*288bf522SAndroid Build Coastguard Worker
FinishWrite()73*288bf522SAndroid Build Coastguard Worker void RecordBuffer::FinishWrite() {
74*288bf522SAndroid Build Coastguard Worker size_t write_head = write_head_.load(std::memory_order_relaxed);
75*288bf522SAndroid Build Coastguard Worker write_head = (write_head + cur_write_record_size_) % buffer_size_;
76*288bf522SAndroid Build Coastguard Worker write_head_.store(write_head, std::memory_order_release);
77*288bf522SAndroid Build Coastguard Worker }
78*288bf522SAndroid Build Coastguard Worker
GetCurrentRecord()79*288bf522SAndroid Build Coastguard Worker char* RecordBuffer::GetCurrentRecord() {
80*288bf522SAndroid Build Coastguard Worker size_t write_head = write_head_.load(std::memory_order_acquire);
81*288bf522SAndroid Build Coastguard Worker size_t read_head = read_head_.load(std::memory_order_relaxed);
82*288bf522SAndroid Build Coastguard Worker if (read_head == write_head) {
83*288bf522SAndroid Build Coastguard Worker return nullptr;
84*288bf522SAndroid Build Coastguard Worker }
85*288bf522SAndroid Build Coastguard Worker perf_event_header header;
86*288bf522SAndroid Build Coastguard Worker if (read_head > write_head) {
87*288bf522SAndroid Build Coastguard Worker if (buffer_size_ - read_head < sizeof(header) ||
88*288bf522SAndroid Build Coastguard Worker (memcpy(&header, buffer_.get() + read_head, sizeof(header)) && header.size == 0)) {
89*288bf522SAndroid Build Coastguard Worker // Need to wrap to the start of the buffer.
90*288bf522SAndroid Build Coastguard Worker cur_read_record_size_ += buffer_size_ - read_head;
91*288bf522SAndroid Build Coastguard Worker read_head = 0;
92*288bf522SAndroid Build Coastguard Worker memcpy(&header, buffer_.get(), sizeof(header));
93*288bf522SAndroid Build Coastguard Worker }
94*288bf522SAndroid Build Coastguard Worker } else {
95*288bf522SAndroid Build Coastguard Worker memcpy(&header, buffer_.get() + read_head, sizeof(header));
96*288bf522SAndroid Build Coastguard Worker }
97*288bf522SAndroid Build Coastguard Worker cur_read_record_size_ += header.size;
98*288bf522SAndroid Build Coastguard Worker return buffer_.get() + read_head;
99*288bf522SAndroid Build Coastguard Worker }
100*288bf522SAndroid Build Coastguard Worker
MoveToNextRecord()101*288bf522SAndroid Build Coastguard Worker void RecordBuffer::MoveToNextRecord() {
102*288bf522SAndroid Build Coastguard Worker size_t read_head = read_head_.load(std::memory_order_relaxed);
103*288bf522SAndroid Build Coastguard Worker read_head = (read_head + cur_read_record_size_) % buffer_size_;
104*288bf522SAndroid Build Coastguard Worker read_head_.store(read_head, std::memory_order_release);
105*288bf522SAndroid Build Coastguard Worker cur_read_record_size_ = 0;
106*288bf522SAndroid Build Coastguard Worker }
107*288bf522SAndroid Build Coastguard Worker
RecordParser(const perf_event_attr & attr)108*288bf522SAndroid Build Coastguard Worker RecordParser::RecordParser(const perf_event_attr& attr)
109*288bf522SAndroid Build Coastguard Worker : sample_type_(attr.sample_type),
110*288bf522SAndroid Build Coastguard Worker read_format_(attr.read_format),
111*288bf522SAndroid Build Coastguard Worker sample_regs_count_(__builtin_popcountll(attr.sample_regs_user)) {
112*288bf522SAndroid Build Coastguard Worker size_t pos = sizeof(perf_event_header);
113*288bf522SAndroid Build Coastguard Worker uint64_t mask = PERF_SAMPLE_IDENTIFIER | PERF_SAMPLE_IP;
114*288bf522SAndroid Build Coastguard Worker pos += __builtin_popcountll(sample_type_ & mask) * sizeof(uint64_t);
115*288bf522SAndroid Build Coastguard Worker if (sample_type_ & PERF_SAMPLE_TID) {
116*288bf522SAndroid Build Coastguard Worker pid_pos_in_sample_records_ = pos;
117*288bf522SAndroid Build Coastguard Worker pos += sizeof(uint64_t);
118*288bf522SAndroid Build Coastguard Worker }
119*288bf522SAndroid Build Coastguard Worker if (sample_type_ & PERF_SAMPLE_TIME) {
120*288bf522SAndroid Build Coastguard Worker time_pos_in_sample_records_ = pos;
121*288bf522SAndroid Build Coastguard Worker pos += sizeof(uint64_t);
122*288bf522SAndroid Build Coastguard Worker }
123*288bf522SAndroid Build Coastguard Worker mask = PERF_SAMPLE_ADDR | PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID | PERF_SAMPLE_CPU |
124*288bf522SAndroid Build Coastguard Worker PERF_SAMPLE_PERIOD;
125*288bf522SAndroid Build Coastguard Worker pos += __builtin_popcountll(sample_type_ & mask) * sizeof(uint64_t);
126*288bf522SAndroid Build Coastguard Worker read_pos_in_sample_records_ = pos;
127*288bf522SAndroid Build Coastguard Worker if ((sample_type_ & PERF_SAMPLE_TIME) && attr.sample_id_all) {
128*288bf522SAndroid Build Coastguard Worker mask = PERF_SAMPLE_IDENTIFIER | PERF_SAMPLE_CPU | PERF_SAMPLE_STREAM_ID | PERF_SAMPLE_ID;
129*288bf522SAndroid Build Coastguard Worker time_rpos_in_non_sample_records_ =
130*288bf522SAndroid Build Coastguard Worker (__builtin_popcountll(sample_type_ & mask) + 1) * sizeof(uint64_t);
131*288bf522SAndroid Build Coastguard Worker }
132*288bf522SAndroid Build Coastguard Worker }
133*288bf522SAndroid Build Coastguard Worker
GetTimePos(const perf_event_header & header) const134*288bf522SAndroid Build Coastguard Worker size_t RecordParser::GetTimePos(const perf_event_header& header) const {
135*288bf522SAndroid Build Coastguard Worker if (header.type == PERF_RECORD_SAMPLE) {
136*288bf522SAndroid Build Coastguard Worker return time_pos_in_sample_records_;
137*288bf522SAndroid Build Coastguard Worker }
138*288bf522SAndroid Build Coastguard Worker if (time_rpos_in_non_sample_records_ != 0u &&
139*288bf522SAndroid Build Coastguard Worker time_rpos_in_non_sample_records_ < header.size - sizeof(perf_event_header)) {
140*288bf522SAndroid Build Coastguard Worker return header.size - time_rpos_in_non_sample_records_;
141*288bf522SAndroid Build Coastguard Worker }
142*288bf522SAndroid Build Coastguard Worker return 0;
143*288bf522SAndroid Build Coastguard Worker }
144*288bf522SAndroid Build Coastguard Worker
GetStackSizePos(const std::function<void (size_t,size_t,void *)> & read_record_fn) const145*288bf522SAndroid Build Coastguard Worker size_t RecordParser::GetStackSizePos(
146*288bf522SAndroid Build Coastguard Worker const std::function<void(size_t, size_t, void*)>& read_record_fn) const {
147*288bf522SAndroid Build Coastguard Worker size_t pos = read_pos_in_sample_records_;
148*288bf522SAndroid Build Coastguard Worker if (sample_type_ & PERF_SAMPLE_READ) {
149*288bf522SAndroid Build Coastguard Worker uint64_t nr = 1;
150*288bf522SAndroid Build Coastguard Worker if (read_format_ & PERF_FORMAT_GROUP) {
151*288bf522SAndroid Build Coastguard Worker read_record_fn(pos, sizeof(nr), &nr);
152*288bf522SAndroid Build Coastguard Worker pos += sizeof(uint64_t);
153*288bf522SAndroid Build Coastguard Worker }
154*288bf522SAndroid Build Coastguard Worker size_t u64_count = nr;
155*288bf522SAndroid Build Coastguard Worker u64_count += (read_format_ & PERF_FORMAT_TOTAL_TIME_ENABLED) ? 1 : 0;
156*288bf522SAndroid Build Coastguard Worker u64_count += (read_format_ & PERF_FORMAT_TOTAL_TIME_RUNNING) ? 1 : 0;
157*288bf522SAndroid Build Coastguard Worker u64_count += (read_format_ & PERF_FORMAT_ID) ? nr : 0;
158*288bf522SAndroid Build Coastguard Worker pos += u64_count * sizeof(uint64_t);
159*288bf522SAndroid Build Coastguard Worker }
160*288bf522SAndroid Build Coastguard Worker if (sample_type_ & PERF_SAMPLE_CALLCHAIN) {
161*288bf522SAndroid Build Coastguard Worker uint64_t ip_nr;
162*288bf522SAndroid Build Coastguard Worker read_record_fn(pos, sizeof(ip_nr), &ip_nr);
163*288bf522SAndroid Build Coastguard Worker pos += (ip_nr + 1) * sizeof(uint64_t);
164*288bf522SAndroid Build Coastguard Worker }
165*288bf522SAndroid Build Coastguard Worker if (sample_type_ & PERF_SAMPLE_RAW) {
166*288bf522SAndroid Build Coastguard Worker uint32_t size;
167*288bf522SAndroid Build Coastguard Worker read_record_fn(pos, sizeof(size), &size);
168*288bf522SAndroid Build Coastguard Worker pos += size + sizeof(uint32_t);
169*288bf522SAndroid Build Coastguard Worker }
170*288bf522SAndroid Build Coastguard Worker if (sample_type_ & PERF_SAMPLE_BRANCH_STACK) {
171*288bf522SAndroid Build Coastguard Worker uint64_t stack_nr;
172*288bf522SAndroid Build Coastguard Worker read_record_fn(pos, sizeof(stack_nr), &stack_nr);
173*288bf522SAndroid Build Coastguard Worker pos += sizeof(uint64_t) + stack_nr * sizeof(BranchStackItemType);
174*288bf522SAndroid Build Coastguard Worker }
175*288bf522SAndroid Build Coastguard Worker if (sample_type_ & PERF_SAMPLE_REGS_USER) {
176*288bf522SAndroid Build Coastguard Worker uint64_t abi;
177*288bf522SAndroid Build Coastguard Worker read_record_fn(pos, sizeof(abi), &abi);
178*288bf522SAndroid Build Coastguard Worker pos += (1 + (abi == 0 ? 0 : sample_regs_count_)) * sizeof(uint64_t);
179*288bf522SAndroid Build Coastguard Worker }
180*288bf522SAndroid Build Coastguard Worker return (sample_type_ & PERF_SAMPLE_STACK_USER) ? pos : 0;
181*288bf522SAndroid Build Coastguard Worker }
182*288bf522SAndroid Build Coastguard Worker
KernelRecordReader(EventFd * event_fd)183*288bf522SAndroid Build Coastguard Worker KernelRecordReader::KernelRecordReader(EventFd* event_fd) : event_fd_(event_fd) {
184*288bf522SAndroid Build Coastguard Worker size_t buffer_size;
185*288bf522SAndroid Build Coastguard Worker buffer_ = event_fd_->GetMappedBuffer(buffer_size);
186*288bf522SAndroid Build Coastguard Worker buffer_mask_ = buffer_size - 1;
187*288bf522SAndroid Build Coastguard Worker }
188*288bf522SAndroid Build Coastguard Worker
GetDataFromKernelBuffer()189*288bf522SAndroid Build Coastguard Worker bool KernelRecordReader::GetDataFromKernelBuffer() {
190*288bf522SAndroid Build Coastguard Worker data_size_ = event_fd_->GetAvailableMmapDataSize(data_pos_);
191*288bf522SAndroid Build Coastguard Worker if (data_size_ == 0) {
192*288bf522SAndroid Build Coastguard Worker return false;
193*288bf522SAndroid Build Coastguard Worker }
194*288bf522SAndroid Build Coastguard Worker init_data_size_ = data_size_;
195*288bf522SAndroid Build Coastguard Worker record_header_.size = 0;
196*288bf522SAndroid Build Coastguard Worker return true;
197*288bf522SAndroid Build Coastguard Worker }
198*288bf522SAndroid Build Coastguard Worker
ReadRecord(size_t pos,size_t size,void * dest)199*288bf522SAndroid Build Coastguard Worker void KernelRecordReader::ReadRecord(size_t pos, size_t size, void* dest) {
200*288bf522SAndroid Build Coastguard Worker pos = (pos + data_pos_) & buffer_mask_;
201*288bf522SAndroid Build Coastguard Worker size_t copy_size = std::min(size, buffer_mask_ + 1 - pos);
202*288bf522SAndroid Build Coastguard Worker memcpy(dest, buffer_ + pos, copy_size);
203*288bf522SAndroid Build Coastguard Worker if (copy_size < size) {
204*288bf522SAndroid Build Coastguard Worker memcpy(static_cast<char*>(dest) + copy_size, buffer_, size - copy_size);
205*288bf522SAndroid Build Coastguard Worker }
206*288bf522SAndroid Build Coastguard Worker }
207*288bf522SAndroid Build Coastguard Worker
MoveToNextRecord(const RecordParser & parser)208*288bf522SAndroid Build Coastguard Worker bool KernelRecordReader::MoveToNextRecord(const RecordParser& parser) {
209*288bf522SAndroid Build Coastguard Worker data_pos_ = (data_pos_ + record_header_.size) & buffer_mask_;
210*288bf522SAndroid Build Coastguard Worker data_size_ -= record_header_.size;
211*288bf522SAndroid Build Coastguard Worker if (data_size_ == 0) {
212*288bf522SAndroid Build Coastguard Worker event_fd_->DiscardMmapData(init_data_size_);
213*288bf522SAndroid Build Coastguard Worker init_data_size_ = 0;
214*288bf522SAndroid Build Coastguard Worker return false;
215*288bf522SAndroid Build Coastguard Worker }
216*288bf522SAndroid Build Coastguard Worker ReadRecord(0, sizeof(record_header_), &record_header_);
217*288bf522SAndroid Build Coastguard Worker size_t time_pos = parser.GetTimePos(record_header_);
218*288bf522SAndroid Build Coastguard Worker if (time_pos != 0) {
219*288bf522SAndroid Build Coastguard Worker ReadRecord(time_pos, sizeof(record_time_), &record_time_);
220*288bf522SAndroid Build Coastguard Worker }
221*288bf522SAndroid Build Coastguard Worker return true;
222*288bf522SAndroid Build Coastguard Worker }
223*288bf522SAndroid Build Coastguard Worker
RecordReadThread(size_t record_buffer_size,const perf_event_attr & attr,size_t min_mmap_pages,size_t max_mmap_pages,size_t aux_buffer_size,bool allow_truncating_samples,bool exclude_perf)224*288bf522SAndroid Build Coastguard Worker RecordReadThread::RecordReadThread(size_t record_buffer_size, const perf_event_attr& attr,
225*288bf522SAndroid Build Coastguard Worker size_t min_mmap_pages, size_t max_mmap_pages,
226*288bf522SAndroid Build Coastguard Worker size_t aux_buffer_size, bool allow_truncating_samples,
227*288bf522SAndroid Build Coastguard Worker bool exclude_perf)
228*288bf522SAndroid Build Coastguard Worker : record_buffer_(record_buffer_size),
229*288bf522SAndroid Build Coastguard Worker record_parser_(attr),
230*288bf522SAndroid Build Coastguard Worker attr_(attr),
231*288bf522SAndroid Build Coastguard Worker min_mmap_pages_(min_mmap_pages),
232*288bf522SAndroid Build Coastguard Worker max_mmap_pages_(max_mmap_pages),
233*288bf522SAndroid Build Coastguard Worker aux_buffer_size_(aux_buffer_size) {
234*288bf522SAndroid Build Coastguard Worker if (attr.sample_type & PERF_SAMPLE_STACK_USER) {
235*288bf522SAndroid Build Coastguard Worker stack_size_in_sample_record_ = attr.sample_stack_user;
236*288bf522SAndroid Build Coastguard Worker }
237*288bf522SAndroid Build Coastguard Worker record_buffer_low_level_ = std::min(record_buffer_size / 4, kDefaultLowBufferLevel);
238*288bf522SAndroid Build Coastguard Worker record_buffer_critical_level_ = std::min(record_buffer_size / 6, kDefaultCriticalBufferLevel);
239*288bf522SAndroid Build Coastguard Worker LOG(VERBOSE) << "user buffer size = " << record_buffer_size
240*288bf522SAndroid Build Coastguard Worker << ", low_level size = " << record_buffer_low_level_
241*288bf522SAndroid Build Coastguard Worker << ", critical_level size = " << record_buffer_critical_level_;
242*288bf522SAndroid Build Coastguard Worker if (!allow_truncating_samples) {
243*288bf522SAndroid Build Coastguard Worker record_buffer_low_level_ = record_buffer_critical_level_;
244*288bf522SAndroid Build Coastguard Worker }
245*288bf522SAndroid Build Coastguard Worker if (exclude_perf) {
246*288bf522SAndroid Build Coastguard Worker exclude_pid_ = getpid();
247*288bf522SAndroid Build Coastguard Worker }
248*288bf522SAndroid Build Coastguard Worker }
249*288bf522SAndroid Build Coastguard Worker
~RecordReadThread()250*288bf522SAndroid Build Coastguard Worker RecordReadThread::~RecordReadThread() {
251*288bf522SAndroid Build Coastguard Worker if (read_thread_) {
252*288bf522SAndroid Build Coastguard Worker StopReadThread();
253*288bf522SAndroid Build Coastguard Worker }
254*288bf522SAndroid Build Coastguard Worker }
255*288bf522SAndroid Build Coastguard Worker
RegisterDataCallback(IOEventLoop & loop,const std::function<bool ()> & data_callback)256*288bf522SAndroid Build Coastguard Worker bool RecordReadThread::RegisterDataCallback(IOEventLoop& loop,
257*288bf522SAndroid Build Coastguard Worker const std::function<bool()>& data_callback) {
258*288bf522SAndroid Build Coastguard Worker int cmd_fd[2];
259*288bf522SAndroid Build Coastguard Worker int data_fd[2];
260*288bf522SAndroid Build Coastguard Worker if (pipe2(cmd_fd, O_CLOEXEC) != 0 || pipe2(data_fd, O_CLOEXEC) != 0) {
261*288bf522SAndroid Build Coastguard Worker PLOG(ERROR) << "pipe2";
262*288bf522SAndroid Build Coastguard Worker return false;
263*288bf522SAndroid Build Coastguard Worker }
264*288bf522SAndroid Build Coastguard Worker read_cmd_fd_.reset(cmd_fd[0]);
265*288bf522SAndroid Build Coastguard Worker write_cmd_fd_.reset(cmd_fd[1]);
266*288bf522SAndroid Build Coastguard Worker cmd_ = NO_CMD;
267*288bf522SAndroid Build Coastguard Worker read_data_fd_.reset(data_fd[0]);
268*288bf522SAndroid Build Coastguard Worker write_data_fd_.reset(data_fd[1]);
269*288bf522SAndroid Build Coastguard Worker has_data_notification_ = false;
270*288bf522SAndroid Build Coastguard Worker if (!loop.AddReadEvent(read_data_fd_, data_callback)) {
271*288bf522SAndroid Build Coastguard Worker return false;
272*288bf522SAndroid Build Coastguard Worker }
273*288bf522SAndroid Build Coastguard Worker read_thread_.reset(new std::thread([&]() { RunReadThread(); }));
274*288bf522SAndroid Build Coastguard Worker return true;
275*288bf522SAndroid Build Coastguard Worker }
276*288bf522SAndroid Build Coastguard Worker
AddEventFds(const std::vector<EventFd * > & event_fds)277*288bf522SAndroid Build Coastguard Worker bool RecordReadThread::AddEventFds(const std::vector<EventFd*>& event_fds) {
278*288bf522SAndroid Build Coastguard Worker return SendCmdToReadThread(CMD_ADD_EVENT_FDS, const_cast<std::vector<EventFd*>*>(&event_fds));
279*288bf522SAndroid Build Coastguard Worker }
280*288bf522SAndroid Build Coastguard Worker
RemoveEventFds(const std::vector<EventFd * > & event_fds)281*288bf522SAndroid Build Coastguard Worker bool RecordReadThread::RemoveEventFds(const std::vector<EventFd*>& event_fds) {
282*288bf522SAndroid Build Coastguard Worker return SendCmdToReadThread(CMD_REMOVE_EVENT_FDS, const_cast<std::vector<EventFd*>*>(&event_fds));
283*288bf522SAndroid Build Coastguard Worker }
284*288bf522SAndroid Build Coastguard Worker
SyncKernelBuffer()285*288bf522SAndroid Build Coastguard Worker bool RecordReadThread::SyncKernelBuffer() {
286*288bf522SAndroid Build Coastguard Worker return SendCmdToReadThread(CMD_SYNC_KERNEL_BUFFER, nullptr);
287*288bf522SAndroid Build Coastguard Worker }
288*288bf522SAndroid Build Coastguard Worker
StopReadThread()289*288bf522SAndroid Build Coastguard Worker bool RecordReadThread::StopReadThread() {
290*288bf522SAndroid Build Coastguard Worker bool result = true;
291*288bf522SAndroid Build Coastguard Worker if (read_thread_ != nullptr) {
292*288bf522SAndroid Build Coastguard Worker result = SendCmdToReadThread(CMD_STOP_THREAD, nullptr);
293*288bf522SAndroid Build Coastguard Worker if (result) {
294*288bf522SAndroid Build Coastguard Worker read_thread_->join();
295*288bf522SAndroid Build Coastguard Worker read_thread_ = nullptr;
296*288bf522SAndroid Build Coastguard Worker }
297*288bf522SAndroid Build Coastguard Worker }
298*288bf522SAndroid Build Coastguard Worker return result;
299*288bf522SAndroid Build Coastguard Worker }
300*288bf522SAndroid Build Coastguard Worker
SendCmdToReadThread(Cmd cmd,void * cmd_arg)301*288bf522SAndroid Build Coastguard Worker bool RecordReadThread::SendCmdToReadThread(Cmd cmd, void* cmd_arg) {
302*288bf522SAndroid Build Coastguard Worker {
303*288bf522SAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(cmd_mutex_);
304*288bf522SAndroid Build Coastguard Worker cmd_ = cmd;
305*288bf522SAndroid Build Coastguard Worker cmd_arg_ = cmd_arg;
306*288bf522SAndroid Build Coastguard Worker }
307*288bf522SAndroid Build Coastguard Worker char unused = 0;
308*288bf522SAndroid Build Coastguard Worker if (TEMP_FAILURE_RETRY(write(write_cmd_fd_, &unused, 1)) != 1) {
309*288bf522SAndroid Build Coastguard Worker return false;
310*288bf522SAndroid Build Coastguard Worker }
311*288bf522SAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(cmd_mutex_);
312*288bf522SAndroid Build Coastguard Worker while (cmd_ != NO_CMD) {
313*288bf522SAndroid Build Coastguard Worker cmd_finish_cond_.wait(lock);
314*288bf522SAndroid Build Coastguard Worker }
315*288bf522SAndroid Build Coastguard Worker return cmd_result_;
316*288bf522SAndroid Build Coastguard Worker }
317*288bf522SAndroid Build Coastguard Worker
GetRecord()318*288bf522SAndroid Build Coastguard Worker std::unique_ptr<Record> RecordReadThread::GetRecord() {
319*288bf522SAndroid Build Coastguard Worker record_buffer_.MoveToNextRecord();
320*288bf522SAndroid Build Coastguard Worker char* p = record_buffer_.GetCurrentRecord();
321*288bf522SAndroid Build Coastguard Worker if (p != nullptr) {
322*288bf522SAndroid Build Coastguard Worker std::unique_ptr<Record> r = ReadRecordFromBuffer(attr_, p, record_buffer_.BufferEnd());
323*288bf522SAndroid Build Coastguard Worker CHECK(r);
324*288bf522SAndroid Build Coastguard Worker if (r->type() == PERF_RECORD_AUXTRACE) {
325*288bf522SAndroid Build Coastguard Worker auto auxtrace = static_cast<AuxTraceRecord*>(r.get());
326*288bf522SAndroid Build Coastguard Worker record_buffer_.AddCurrentRecordSize(auxtrace->data->aux_size);
327*288bf522SAndroid Build Coastguard Worker auxtrace->location.addr = r->Binary() + r->size();
328*288bf522SAndroid Build Coastguard Worker }
329*288bf522SAndroid Build Coastguard Worker return r;
330*288bf522SAndroid Build Coastguard Worker }
331*288bf522SAndroid Build Coastguard Worker if (has_data_notification_) {
332*288bf522SAndroid Build Coastguard Worker char unused;
333*288bf522SAndroid Build Coastguard Worker TEMP_FAILURE_RETRY(read(read_data_fd_, &unused, 1));
334*288bf522SAndroid Build Coastguard Worker has_data_notification_ = false;
335*288bf522SAndroid Build Coastguard Worker }
336*288bf522SAndroid Build Coastguard Worker return nullptr;
337*288bf522SAndroid Build Coastguard Worker }
338*288bf522SAndroid Build Coastguard Worker
RunReadThread()339*288bf522SAndroid Build Coastguard Worker void RecordReadThread::RunReadThread() {
340*288bf522SAndroid Build Coastguard Worker IncreaseThreadPriority();
341*288bf522SAndroid Build Coastguard Worker IOEventLoop loop;
342*288bf522SAndroid Build Coastguard Worker CHECK(loop.AddReadEvent(read_cmd_fd_, [&]() { return HandleCmd(loop); }));
343*288bf522SAndroid Build Coastguard Worker loop.RunLoop();
344*288bf522SAndroid Build Coastguard Worker }
345*288bf522SAndroid Build Coastguard Worker
IncreaseThreadPriority()346*288bf522SAndroid Build Coastguard Worker void RecordReadThread::IncreaseThreadPriority() {
347*288bf522SAndroid Build Coastguard Worker // TODO: use real time priority for root.
348*288bf522SAndroid Build Coastguard Worker rlimit rlim;
349*288bf522SAndroid Build Coastguard Worker int result = getrlimit(RLIMIT_NICE, &rlim);
350*288bf522SAndroid Build Coastguard Worker if (result == 0 && rlim.rlim_cur == 40) {
351*288bf522SAndroid Build Coastguard Worker result = setpriority(PRIO_PROCESS, gettid(), -20);
352*288bf522SAndroid Build Coastguard Worker if (result == 0) {
353*288bf522SAndroid Build Coastguard Worker LOG(VERBOSE) << "Priority of record read thread is increased";
354*288bf522SAndroid Build Coastguard Worker }
355*288bf522SAndroid Build Coastguard Worker }
356*288bf522SAndroid Build Coastguard Worker }
357*288bf522SAndroid Build Coastguard Worker
GetCmd()358*288bf522SAndroid Build Coastguard Worker RecordReadThread::Cmd RecordReadThread::GetCmd() {
359*288bf522SAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(cmd_mutex_);
360*288bf522SAndroid Build Coastguard Worker return cmd_;
361*288bf522SAndroid Build Coastguard Worker }
362*288bf522SAndroid Build Coastguard Worker
HandleCmd(IOEventLoop & loop)363*288bf522SAndroid Build Coastguard Worker bool RecordReadThread::HandleCmd(IOEventLoop& loop) {
364*288bf522SAndroid Build Coastguard Worker char unused;
365*288bf522SAndroid Build Coastguard Worker TEMP_FAILURE_RETRY(read(read_cmd_fd_, &unused, 1));
366*288bf522SAndroid Build Coastguard Worker bool result = true;
367*288bf522SAndroid Build Coastguard Worker switch (GetCmd()) {
368*288bf522SAndroid Build Coastguard Worker case CMD_ADD_EVENT_FDS:
369*288bf522SAndroid Build Coastguard Worker result = HandleAddEventFds(loop, *static_cast<std::vector<EventFd*>*>(cmd_arg_));
370*288bf522SAndroid Build Coastguard Worker break;
371*288bf522SAndroid Build Coastguard Worker case CMD_REMOVE_EVENT_FDS:
372*288bf522SAndroid Build Coastguard Worker result = HandleRemoveEventFds(*static_cast<std::vector<EventFd*>*>(cmd_arg_));
373*288bf522SAndroid Build Coastguard Worker break;
374*288bf522SAndroid Build Coastguard Worker case CMD_SYNC_KERNEL_BUFFER:
375*288bf522SAndroid Build Coastguard Worker result = ReadRecordsFromKernelBuffer();
376*288bf522SAndroid Build Coastguard Worker break;
377*288bf522SAndroid Build Coastguard Worker case CMD_STOP_THREAD:
378*288bf522SAndroid Build Coastguard Worker result = loop.ExitLoop();
379*288bf522SAndroid Build Coastguard Worker break;
380*288bf522SAndroid Build Coastguard Worker default:
381*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "Unknown cmd: " << GetCmd();
382*288bf522SAndroid Build Coastguard Worker result = false;
383*288bf522SAndroid Build Coastguard Worker break;
384*288bf522SAndroid Build Coastguard Worker }
385*288bf522SAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(cmd_mutex_);
386*288bf522SAndroid Build Coastguard Worker cmd_ = NO_CMD;
387*288bf522SAndroid Build Coastguard Worker cmd_result_ = result;
388*288bf522SAndroid Build Coastguard Worker cmd_finish_cond_.notify_one();
389*288bf522SAndroid Build Coastguard Worker return true;
390*288bf522SAndroid Build Coastguard Worker }
391*288bf522SAndroid Build Coastguard Worker
HandleAddEventFds(IOEventLoop & loop,const std::vector<EventFd * > & event_fds)392*288bf522SAndroid Build Coastguard Worker bool RecordReadThread::HandleAddEventFds(IOEventLoop& loop,
393*288bf522SAndroid Build Coastguard Worker const std::vector<EventFd*>& event_fds) {
394*288bf522SAndroid Build Coastguard Worker std::unordered_map<int, EventFd*> cpu_map;
395*288bf522SAndroid Build Coastguard Worker for (size_t pages = max_mmap_pages_; pages >= min_mmap_pages_; pages >>= 1) {
396*288bf522SAndroid Build Coastguard Worker bool success = true;
397*288bf522SAndroid Build Coastguard Worker bool report_error = pages == min_mmap_pages_;
398*288bf522SAndroid Build Coastguard Worker for (EventFd* fd : event_fds) {
399*288bf522SAndroid Build Coastguard Worker auto it = cpu_map.find(fd->Cpu());
400*288bf522SAndroid Build Coastguard Worker if (it == cpu_map.end()) {
401*288bf522SAndroid Build Coastguard Worker if (!fd->CreateMappedBuffer(pages, report_error)) {
402*288bf522SAndroid Build Coastguard Worker success = false;
403*288bf522SAndroid Build Coastguard Worker break;
404*288bf522SAndroid Build Coastguard Worker }
405*288bf522SAndroid Build Coastguard Worker if (IsEtmEventType(fd->attr().type)) {
406*288bf522SAndroid Build Coastguard Worker if (!fd->CreateAuxBuffer(aux_buffer_size_, report_error)) {
407*288bf522SAndroid Build Coastguard Worker fd->DestroyMappedBuffer();
408*288bf522SAndroid Build Coastguard Worker success = false;
409*288bf522SAndroid Build Coastguard Worker break;
410*288bf522SAndroid Build Coastguard Worker }
411*288bf522SAndroid Build Coastguard Worker has_etm_events_ = true;
412*288bf522SAndroid Build Coastguard Worker }
413*288bf522SAndroid Build Coastguard Worker cpu_map[fd->Cpu()] = fd;
414*288bf522SAndroid Build Coastguard Worker } else {
415*288bf522SAndroid Build Coastguard Worker if (!fd->ShareMappedBuffer(*(it->second), pages == min_mmap_pages_)) {
416*288bf522SAndroid Build Coastguard Worker success = false;
417*288bf522SAndroid Build Coastguard Worker break;
418*288bf522SAndroid Build Coastguard Worker }
419*288bf522SAndroid Build Coastguard Worker }
420*288bf522SAndroid Build Coastguard Worker }
421*288bf522SAndroid Build Coastguard Worker if (success) {
422*288bf522SAndroid Build Coastguard Worker LOG(VERBOSE) << "Each kernel buffer is " << pages << " pages.";
423*288bf522SAndroid Build Coastguard Worker break;
424*288bf522SAndroid Build Coastguard Worker }
425*288bf522SAndroid Build Coastguard Worker for (auto& pair : cpu_map) {
426*288bf522SAndroid Build Coastguard Worker pair.second->DestroyMappedBuffer();
427*288bf522SAndroid Build Coastguard Worker pair.second->DestroyAuxBuffer();
428*288bf522SAndroid Build Coastguard Worker }
429*288bf522SAndroid Build Coastguard Worker cpu_map.clear();
430*288bf522SAndroid Build Coastguard Worker }
431*288bf522SAndroid Build Coastguard Worker if (cpu_map.empty()) {
432*288bf522SAndroid Build Coastguard Worker return false;
433*288bf522SAndroid Build Coastguard Worker }
434*288bf522SAndroid Build Coastguard Worker for (auto& pair : cpu_map) {
435*288bf522SAndroid Build Coastguard Worker if (!pair.second->StartPolling(loop, [this]() { return ReadRecordsFromKernelBuffer(); })) {
436*288bf522SAndroid Build Coastguard Worker return false;
437*288bf522SAndroid Build Coastguard Worker }
438*288bf522SAndroid Build Coastguard Worker kernel_record_readers_.emplace_back(pair.second);
439*288bf522SAndroid Build Coastguard Worker }
440*288bf522SAndroid Build Coastguard Worker return true;
441*288bf522SAndroid Build Coastguard Worker }
442*288bf522SAndroid Build Coastguard Worker
HandleRemoveEventFds(const std::vector<EventFd * > & event_fds)443*288bf522SAndroid Build Coastguard Worker bool RecordReadThread::HandleRemoveEventFds(const std::vector<EventFd*>& event_fds) {
444*288bf522SAndroid Build Coastguard Worker for (auto& event_fd : event_fds) {
445*288bf522SAndroid Build Coastguard Worker if (event_fd->HasMappedBuffer()) {
446*288bf522SAndroid Build Coastguard Worker auto it = std::find_if(
447*288bf522SAndroid Build Coastguard Worker kernel_record_readers_.begin(), kernel_record_readers_.end(),
448*288bf522SAndroid Build Coastguard Worker [&](const KernelRecordReader& reader) { return reader.GetEventFd() == event_fd; });
449*288bf522SAndroid Build Coastguard Worker if (it != kernel_record_readers_.end()) {
450*288bf522SAndroid Build Coastguard Worker kernel_record_readers_.erase(it);
451*288bf522SAndroid Build Coastguard Worker event_fd->StopPolling();
452*288bf522SAndroid Build Coastguard Worker event_fd->DestroyMappedBuffer();
453*288bf522SAndroid Build Coastguard Worker event_fd->DestroyAuxBuffer();
454*288bf522SAndroid Build Coastguard Worker }
455*288bf522SAndroid Build Coastguard Worker }
456*288bf522SAndroid Build Coastguard Worker }
457*288bf522SAndroid Build Coastguard Worker return true;
458*288bf522SAndroid Build Coastguard Worker }
459*288bf522SAndroid Build Coastguard Worker
CompareRecordTime(KernelRecordReader * r1,KernelRecordReader * r2)460*288bf522SAndroid Build Coastguard Worker static bool CompareRecordTime(KernelRecordReader* r1, KernelRecordReader* r2) {
461*288bf522SAndroid Build Coastguard Worker return r1->RecordTime() > r2->RecordTime();
462*288bf522SAndroid Build Coastguard Worker }
463*288bf522SAndroid Build Coastguard Worker
464*288bf522SAndroid Build Coastguard Worker // When reading from mmap buffers, we prefer reading from all buffers at once rather than reading
465*288bf522SAndroid Build Coastguard Worker // one buffer at a time. Because by reading all buffers at once, we can merge records from
466*288bf522SAndroid Build Coastguard Worker // different buffers easily in memory. Otherwise, we have to sort records with greater effort.
ReadRecordsFromKernelBuffer()467*288bf522SAndroid Build Coastguard Worker bool RecordReadThread::ReadRecordsFromKernelBuffer() {
468*288bf522SAndroid Build Coastguard Worker do {
469*288bf522SAndroid Build Coastguard Worker std::vector<KernelRecordReader*> readers;
470*288bf522SAndroid Build Coastguard Worker for (auto& reader : kernel_record_readers_) {
471*288bf522SAndroid Build Coastguard Worker if (reader.GetDataFromKernelBuffer()) {
472*288bf522SAndroid Build Coastguard Worker readers.push_back(&reader);
473*288bf522SAndroid Build Coastguard Worker }
474*288bf522SAndroid Build Coastguard Worker }
475*288bf522SAndroid Build Coastguard Worker bool has_data = false;
476*288bf522SAndroid Build Coastguard Worker if (!readers.empty()) {
477*288bf522SAndroid Build Coastguard Worker has_data = true;
478*288bf522SAndroid Build Coastguard Worker if (readers.size() == 1u) {
479*288bf522SAndroid Build Coastguard Worker // Only one buffer has data, process it directly.
480*288bf522SAndroid Build Coastguard Worker while (readers[0]->MoveToNextRecord(record_parser_)) {
481*288bf522SAndroid Build Coastguard Worker PushRecordToRecordBuffer(readers[0]);
482*288bf522SAndroid Build Coastguard Worker }
483*288bf522SAndroid Build Coastguard Worker } else {
484*288bf522SAndroid Build Coastguard Worker // Use a binary heap to merge records from different buffers. As records from the same
485*288bf522SAndroid Build Coastguard Worker // buffer are already ordered by time, we only need to merge the first record from all
486*288bf522SAndroid Build Coastguard Worker // buffers. And each time a record is popped from the heap, we put the next record from its
487*288bf522SAndroid Build Coastguard Worker // buffer into the heap.
488*288bf522SAndroid Build Coastguard Worker for (auto& reader : readers) {
489*288bf522SAndroid Build Coastguard Worker reader->MoveToNextRecord(record_parser_);
490*288bf522SAndroid Build Coastguard Worker }
491*288bf522SAndroid Build Coastguard Worker std::make_heap(readers.begin(), readers.end(), CompareRecordTime);
492*288bf522SAndroid Build Coastguard Worker size_t size = readers.size();
493*288bf522SAndroid Build Coastguard Worker while (size > 0) {
494*288bf522SAndroid Build Coastguard Worker std::pop_heap(readers.begin(), readers.begin() + size, CompareRecordTime);
495*288bf522SAndroid Build Coastguard Worker PushRecordToRecordBuffer(readers[size - 1]);
496*288bf522SAndroid Build Coastguard Worker if (readers[size - 1]->MoveToNextRecord(record_parser_)) {
497*288bf522SAndroid Build Coastguard Worker std::push_heap(readers.begin(), readers.begin() + size, CompareRecordTime);
498*288bf522SAndroid Build Coastguard Worker } else {
499*288bf522SAndroid Build Coastguard Worker size--;
500*288bf522SAndroid Build Coastguard Worker }
501*288bf522SAndroid Build Coastguard Worker }
502*288bf522SAndroid Build Coastguard Worker }
503*288bf522SAndroid Build Coastguard Worker }
504*288bf522SAndroid Build Coastguard Worker ReadAuxDataFromKernelBuffer(&has_data);
505*288bf522SAndroid Build Coastguard Worker if (!has_data) {
506*288bf522SAndroid Build Coastguard Worker break;
507*288bf522SAndroid Build Coastguard Worker }
508*288bf522SAndroid Build Coastguard Worker // Having collected everything available, this is a good time to
509*288bf522SAndroid Build Coastguard Worker // try to re-enabled any events that might have been disabled by
510*288bf522SAndroid Build Coastguard Worker // the kernel.
511*288bf522SAndroid Build Coastguard Worker for (auto event_fd : event_fds_disabled_by_kernel_) {
512*288bf522SAndroid Build Coastguard Worker event_fd->SetEnableEvent(true);
513*288bf522SAndroid Build Coastguard Worker }
514*288bf522SAndroid Build Coastguard Worker event_fds_disabled_by_kernel_.clear();
515*288bf522SAndroid Build Coastguard Worker if (!SendDataNotificationToMainThread()) {
516*288bf522SAndroid Build Coastguard Worker return false;
517*288bf522SAndroid Build Coastguard Worker }
518*288bf522SAndroid Build Coastguard Worker // If there are no commands, we can loop until there is no more data from the kernel.
519*288bf522SAndroid Build Coastguard Worker } while (GetCmd() == NO_CMD);
520*288bf522SAndroid Build Coastguard Worker return true;
521*288bf522SAndroid Build Coastguard Worker }
522*288bf522SAndroid Build Coastguard Worker
PushRecordToRecordBuffer(KernelRecordReader * kernel_record_reader)523*288bf522SAndroid Build Coastguard Worker void RecordReadThread::PushRecordToRecordBuffer(KernelRecordReader* kernel_record_reader) {
524*288bf522SAndroid Build Coastguard Worker const perf_event_header& header = kernel_record_reader->RecordHeader();
525*288bf522SAndroid Build Coastguard Worker if (header.type == PERF_RECORD_SAMPLE && exclude_pid_ != -1) {
526*288bf522SAndroid Build Coastguard Worker uint32_t pid;
527*288bf522SAndroid Build Coastguard Worker kernel_record_reader->ReadRecord(record_parser_.GetPidPosInSampleRecord(), sizeof(pid), &pid);
528*288bf522SAndroid Build Coastguard Worker if (pid == exclude_pid_) {
529*288bf522SAndroid Build Coastguard Worker return;
530*288bf522SAndroid Build Coastguard Worker }
531*288bf522SAndroid Build Coastguard Worker }
532*288bf522SAndroid Build Coastguard Worker if (header.type == PERF_RECORD_SAMPLE && stack_size_in_sample_record_ > 1024) {
533*288bf522SAndroid Build Coastguard Worker size_t free_size = record_buffer_.GetFreeSize();
534*288bf522SAndroid Build Coastguard Worker if (free_size < record_buffer_critical_level_) {
535*288bf522SAndroid Build Coastguard Worker // When the free size in record buffer is below critical level, drop sample records to save
536*288bf522SAndroid Build Coastguard Worker // space for more important records (like mmap or fork records).
537*288bf522SAndroid Build Coastguard Worker stat_.userspace_lost_samples++;
538*288bf522SAndroid Build Coastguard Worker return;
539*288bf522SAndroid Build Coastguard Worker }
540*288bf522SAndroid Build Coastguard Worker size_t stack_size_limit = stack_size_in_sample_record_;
541*288bf522SAndroid Build Coastguard Worker if (free_size < record_buffer_low_level_) {
542*288bf522SAndroid Build Coastguard Worker // When the free size in record buffer is below low level, truncate the stack data in sample
543*288bf522SAndroid Build Coastguard Worker // records to 1K. This makes the unwinder unwind only part of the callchains, but hopefully
544*288bf522SAndroid Build Coastguard Worker // the call chain joiner can complete the callchains.
545*288bf522SAndroid Build Coastguard Worker stack_size_limit = 1024;
546*288bf522SAndroid Build Coastguard Worker }
547*288bf522SAndroid Build Coastguard Worker size_t stack_size_pos =
548*288bf522SAndroid Build Coastguard Worker record_parser_.GetStackSizePos([&](size_t pos, size_t size, void* dest) {
549*288bf522SAndroid Build Coastguard Worker return kernel_record_reader->ReadRecord(pos, size, dest);
550*288bf522SAndroid Build Coastguard Worker });
551*288bf522SAndroid Build Coastguard Worker uint64_t stack_size;
552*288bf522SAndroid Build Coastguard Worker kernel_record_reader->ReadRecord(stack_size_pos, sizeof(stack_size), &stack_size);
553*288bf522SAndroid Build Coastguard Worker if (stack_size > 0) {
554*288bf522SAndroid Build Coastguard Worker size_t dyn_stack_size_pos = stack_size_pos + sizeof(stack_size) + stack_size;
555*288bf522SAndroid Build Coastguard Worker uint64_t dyn_stack_size;
556*288bf522SAndroid Build Coastguard Worker kernel_record_reader->ReadRecord(dyn_stack_size_pos, sizeof(dyn_stack_size), &dyn_stack_size);
557*288bf522SAndroid Build Coastguard Worker if (dyn_stack_size == 0) {
558*288bf522SAndroid Build Coastguard Worker // If stack_user_data.dyn_size == 0, it may be because the kernel misses the patch to
559*288bf522SAndroid Build Coastguard Worker // update dyn_size, like in N9 (See b/22612370). So assume all stack data is valid if
560*288bf522SAndroid Build Coastguard Worker // dyn_size == 0.
561*288bf522SAndroid Build Coastguard Worker // TODO: Add cts test.
562*288bf522SAndroid Build Coastguard Worker dyn_stack_size = stack_size;
563*288bf522SAndroid Build Coastguard Worker }
564*288bf522SAndroid Build Coastguard Worker // When simpleperf requests the kernel to dump 64K stack per sample, it will allocate 64K
565*288bf522SAndroid Build Coastguard Worker // space in each sample to store stack data. However, a thread may use less stack than 64K.
566*288bf522SAndroid Build Coastguard Worker // So not all the 64K stack data in a sample is valid, and we only need to keep valid stack
567*288bf522SAndroid Build Coastguard Worker // data, whose size is dyn_stack_size.
568*288bf522SAndroid Build Coastguard Worker uint64_t new_stack_size = Align(std::min<uint64_t>(dyn_stack_size, stack_size_limit), 8);
569*288bf522SAndroid Build Coastguard Worker if (stack_size > new_stack_size) {
570*288bf522SAndroid Build Coastguard Worker // Remove part of the stack data.
571*288bf522SAndroid Build Coastguard Worker perf_event_header new_header = header;
572*288bf522SAndroid Build Coastguard Worker new_header.size -= stack_size - new_stack_size;
573*288bf522SAndroid Build Coastguard Worker char* p = record_buffer_.AllocWriteSpace(new_header.size);
574*288bf522SAndroid Build Coastguard Worker if (p != nullptr) {
575*288bf522SAndroid Build Coastguard Worker memcpy(p, &new_header, sizeof(new_header));
576*288bf522SAndroid Build Coastguard Worker size_t pos = sizeof(new_header);
577*288bf522SAndroid Build Coastguard Worker kernel_record_reader->ReadRecord(pos, stack_size_pos - pos, p + pos);
578*288bf522SAndroid Build Coastguard Worker memcpy(p + stack_size_pos, &new_stack_size, sizeof(uint64_t));
579*288bf522SAndroid Build Coastguard Worker pos = stack_size_pos + sizeof(uint64_t);
580*288bf522SAndroid Build Coastguard Worker kernel_record_reader->ReadRecord(pos, new_stack_size, p + pos);
581*288bf522SAndroid Build Coastguard Worker memcpy(p + pos + new_stack_size, &new_stack_size, sizeof(uint64_t));
582*288bf522SAndroid Build Coastguard Worker record_buffer_.FinishWrite();
583*288bf522SAndroid Build Coastguard Worker if (new_stack_size < dyn_stack_size) {
584*288bf522SAndroid Build Coastguard Worker stat_.userspace_truncated_stack_samples++;
585*288bf522SAndroid Build Coastguard Worker }
586*288bf522SAndroid Build Coastguard Worker } else {
587*288bf522SAndroid Build Coastguard Worker stat_.userspace_lost_samples++;
588*288bf522SAndroid Build Coastguard Worker }
589*288bf522SAndroid Build Coastguard Worker return;
590*288bf522SAndroid Build Coastguard Worker }
591*288bf522SAndroid Build Coastguard Worker }
592*288bf522SAndroid Build Coastguard Worker }
593*288bf522SAndroid Build Coastguard Worker char* p = record_buffer_.AllocWriteSpace(header.size);
594*288bf522SAndroid Build Coastguard Worker if (p != nullptr) {
595*288bf522SAndroid Build Coastguard Worker kernel_record_reader->ReadRecord(0, header.size, p);
596*288bf522SAndroid Build Coastguard Worker if (header.type == PERF_RECORD_AUX) {
597*288bf522SAndroid Build Coastguard Worker AuxRecord r;
598*288bf522SAndroid Build Coastguard Worker if (r.Parse(attr_, p, p + header.size) && (r.data->flags & PERF_AUX_FLAG_TRUNCATED)) {
599*288bf522SAndroid Build Coastguard Worker // When the kernel sees aux output flagged with PERF_AUX_FLAG_TRUNCATED,
600*288bf522SAndroid Build Coastguard Worker // it sets a pending disable on the event:
601*288bf522SAndroid Build Coastguard Worker // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/events/ring_buffer.c?h=v5.13#n516
602*288bf522SAndroid Build Coastguard Worker // The truncated flag is set by the Coresight driver when some trace was lost,
603*288bf522SAndroid Build Coastguard Worker // which can be caused by a full buffer. Therefore, try to re-enable the event
604*288bf522SAndroid Build Coastguard Worker // only after we have collected the aux data.
605*288bf522SAndroid Build Coastguard Worker event_fds_disabled_by_kernel_.insert(kernel_record_reader->GetEventFd());
606*288bf522SAndroid Build Coastguard Worker }
607*288bf522SAndroid Build Coastguard Worker } else if (header.type == PERF_RECORD_LOST) {
608*288bf522SAndroid Build Coastguard Worker LostRecord r;
609*288bf522SAndroid Build Coastguard Worker if (r.Parse(attr_, p, p + header.size)) {
610*288bf522SAndroid Build Coastguard Worker stat_.kernelspace_lost_records += static_cast<size_t>(r.lost);
611*288bf522SAndroid Build Coastguard Worker }
612*288bf522SAndroid Build Coastguard Worker }
613*288bf522SAndroid Build Coastguard Worker record_buffer_.FinishWrite();
614*288bf522SAndroid Build Coastguard Worker } else {
615*288bf522SAndroid Build Coastguard Worker if (header.type == PERF_RECORD_SAMPLE) {
616*288bf522SAndroid Build Coastguard Worker stat_.userspace_lost_samples++;
617*288bf522SAndroid Build Coastguard Worker } else {
618*288bf522SAndroid Build Coastguard Worker stat_.userspace_lost_non_samples++;
619*288bf522SAndroid Build Coastguard Worker }
620*288bf522SAndroid Build Coastguard Worker }
621*288bf522SAndroid Build Coastguard Worker }
622*288bf522SAndroid Build Coastguard Worker
ReadAuxDataFromKernelBuffer(bool * has_data)623*288bf522SAndroid Build Coastguard Worker void RecordReadThread::ReadAuxDataFromKernelBuffer(bool* has_data) {
624*288bf522SAndroid Build Coastguard Worker if (!has_etm_events_) {
625*288bf522SAndroid Build Coastguard Worker return;
626*288bf522SAndroid Build Coastguard Worker }
627*288bf522SAndroid Build Coastguard Worker for (auto& reader : kernel_record_readers_) {
628*288bf522SAndroid Build Coastguard Worker EventFd* event_fd = reader.GetEventFd();
629*288bf522SAndroid Build Coastguard Worker if (event_fd->HasAuxBuffer()) {
630*288bf522SAndroid Build Coastguard Worker char* buf[2];
631*288bf522SAndroid Build Coastguard Worker size_t size[2];
632*288bf522SAndroid Build Coastguard Worker uint64_t offset = event_fd->GetAvailableAuxData(&buf[0], &size[0], &buf[1], &size[1]);
633*288bf522SAndroid Build Coastguard Worker size_t aux_size = size[0] + size[1];
634*288bf522SAndroid Build Coastguard Worker if (aux_size == 0) {
635*288bf522SAndroid Build Coastguard Worker continue;
636*288bf522SAndroid Build Coastguard Worker }
637*288bf522SAndroid Build Coastguard Worker *has_data = true;
638*288bf522SAndroid Build Coastguard Worker AuxTraceRecord auxtrace(Align(aux_size, 8), offset, event_fd->Cpu(), 0, event_fd->Cpu());
639*288bf522SAndroid Build Coastguard Worker size_t alloc_size = auxtrace.size() + auxtrace.data->aux_size;
640*288bf522SAndroid Build Coastguard Worker char* p = nullptr;
641*288bf522SAndroid Build Coastguard Worker if ((record_buffer_.GetFreeSize() < alloc_size + record_buffer_critical_level_) ||
642*288bf522SAndroid Build Coastguard Worker (p = record_buffer_.AllocWriteSpace(alloc_size)) == nullptr) {
643*288bf522SAndroid Build Coastguard Worker stat_.lost_aux_data_size += aux_size;
644*288bf522SAndroid Build Coastguard Worker } else {
645*288bf522SAndroid Build Coastguard Worker CHECK(p != nullptr);
646*288bf522SAndroid Build Coastguard Worker MoveToBinaryFormat(auxtrace.Binary(), auxtrace.size(), p);
647*288bf522SAndroid Build Coastguard Worker MoveToBinaryFormat(buf[0], size[0], p);
648*288bf522SAndroid Build Coastguard Worker if (size[1] != 0) {
649*288bf522SAndroid Build Coastguard Worker MoveToBinaryFormat(buf[1], size[1], p);
650*288bf522SAndroid Build Coastguard Worker }
651*288bf522SAndroid Build Coastguard Worker size_t pad_size = auxtrace.data->aux_size - aux_size;
652*288bf522SAndroid Build Coastguard Worker if (pad_size != 0) {
653*288bf522SAndroid Build Coastguard Worker uint64_t pad = 0;
654*288bf522SAndroid Build Coastguard Worker memcpy(p, &pad, pad_size);
655*288bf522SAndroid Build Coastguard Worker }
656*288bf522SAndroid Build Coastguard Worker record_buffer_.FinishWrite();
657*288bf522SAndroid Build Coastguard Worker stat_.aux_data_size += aux_size;
658*288bf522SAndroid Build Coastguard Worker LOG(DEBUG) << "record aux data " << aux_size << " bytes";
659*288bf522SAndroid Build Coastguard Worker }
660*288bf522SAndroid Build Coastguard Worker event_fd->DiscardAuxData(aux_size);
661*288bf522SAndroid Build Coastguard Worker }
662*288bf522SAndroid Build Coastguard Worker }
663*288bf522SAndroid Build Coastguard Worker }
664*288bf522SAndroid Build Coastguard Worker
SendDataNotificationToMainThread()665*288bf522SAndroid Build Coastguard Worker bool RecordReadThread::SendDataNotificationToMainThread() {
666*288bf522SAndroid Build Coastguard Worker if (has_etm_events_) {
667*288bf522SAndroid Build Coastguard Worker // For ETM recording, the default buffer size is large enough to hold ETM data for several
668*288bf522SAndroid Build Coastguard Worker // seconds. To reduce impact of processing ETM data (especially when --decode-etm is used),
669*288bf522SAndroid Build Coastguard Worker // delay processing ETM data until the buffer is half full.
670*288bf522SAndroid Build Coastguard Worker if (record_buffer_.GetFreeSize() >= record_buffer_.size() / 2) {
671*288bf522SAndroid Build Coastguard Worker return true;
672*288bf522SAndroid Build Coastguard Worker }
673*288bf522SAndroid Build Coastguard Worker }
674*288bf522SAndroid Build Coastguard Worker if (!has_data_notification_.load(std::memory_order_relaxed)) {
675*288bf522SAndroid Build Coastguard Worker has_data_notification_ = true;
676*288bf522SAndroid Build Coastguard Worker char unused = 0;
677*288bf522SAndroid Build Coastguard Worker if (TEMP_FAILURE_RETRY(write(write_data_fd_, &unused, 1)) != 1) {
678*288bf522SAndroid Build Coastguard Worker PLOG(ERROR) << "write";
679*288bf522SAndroid Build Coastguard Worker return false;
680*288bf522SAndroid Build Coastguard Worker }
681*288bf522SAndroid Build Coastguard Worker }
682*288bf522SAndroid Build Coastguard Worker return true;
683*288bf522SAndroid Build Coastguard Worker }
684*288bf522SAndroid Build Coastguard Worker
685*288bf522SAndroid Build Coastguard Worker } // namespace simpleperf
686