xref: /aosp_15_r20/external/perfetto/src/profiling/perf/event_reader.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker  * Copyright (C) 2019 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 #include "src/profiling/perf/event_reader.h"
18*6dbdd20aSAndroid Build Coastguard Worker 
19*6dbdd20aSAndroid Build Coastguard Worker #include <linux/perf_event.h>
20*6dbdd20aSAndroid Build Coastguard Worker #include <sys/ioctl.h>
21*6dbdd20aSAndroid Build Coastguard Worker #include <sys/mman.h>
22*6dbdd20aSAndroid Build Coastguard Worker #include <sys/syscall.h>
23*6dbdd20aSAndroid Build Coastguard Worker #include <sys/types.h>
24*6dbdd20aSAndroid Build Coastguard Worker #include <unistd.h>
25*6dbdd20aSAndroid Build Coastguard Worker 
26*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/utils.h"
27*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/perf/regs_parsing.h"
28*6dbdd20aSAndroid Build Coastguard Worker 
29*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
30*6dbdd20aSAndroid Build Coastguard Worker namespace profiling {
31*6dbdd20aSAndroid Build Coastguard Worker 
32*6dbdd20aSAndroid Build Coastguard Worker namespace {
33*6dbdd20aSAndroid Build Coastguard Worker 
34*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
ReadValue(T * value_out,const char * ptr)35*6dbdd20aSAndroid Build Coastguard Worker const char* ReadValue(T* value_out, const char* ptr) {
36*6dbdd20aSAndroid Build Coastguard Worker   memcpy(value_out, reinterpret_cast<const void*>(ptr), sizeof(T));
37*6dbdd20aSAndroid Build Coastguard Worker   return ptr + sizeof(T);
38*6dbdd20aSAndroid Build Coastguard Worker }
39*6dbdd20aSAndroid Build Coastguard Worker 
40*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
ReadValues(T * out,const char * ptr,size_t num_values)41*6dbdd20aSAndroid Build Coastguard Worker const char* ReadValues(T* out, const char* ptr, size_t num_values) {
42*6dbdd20aSAndroid Build Coastguard Worker   size_t sz = sizeof(T) * num_values;
43*6dbdd20aSAndroid Build Coastguard Worker   memcpy(out, reinterpret_cast<const void*>(ptr), sz);
44*6dbdd20aSAndroid Build Coastguard Worker   return ptr + sz;
45*6dbdd20aSAndroid Build Coastguard Worker }
46*6dbdd20aSAndroid Build Coastguard Worker 
IsPowerOfTwo(size_t v)47*6dbdd20aSAndroid Build Coastguard Worker bool IsPowerOfTwo(size_t v) {
48*6dbdd20aSAndroid Build Coastguard Worker   return (v != 0 && ((v & (v - 1)) == 0));
49*6dbdd20aSAndroid Build Coastguard Worker }
50*6dbdd20aSAndroid Build Coastguard Worker 
perf_event_open(perf_event_attr * attr,pid_t pid,int cpu,int group_fd,unsigned long flags)51*6dbdd20aSAndroid Build Coastguard Worker static int perf_event_open(perf_event_attr* attr,
52*6dbdd20aSAndroid Build Coastguard Worker                            pid_t pid,
53*6dbdd20aSAndroid Build Coastguard Worker                            int cpu,
54*6dbdd20aSAndroid Build Coastguard Worker                            int group_fd,
55*6dbdd20aSAndroid Build Coastguard Worker                            unsigned long flags) {
56*6dbdd20aSAndroid Build Coastguard Worker   return static_cast<int>(
57*6dbdd20aSAndroid Build Coastguard Worker       syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags));
58*6dbdd20aSAndroid Build Coastguard Worker }
59*6dbdd20aSAndroid Build Coastguard Worker 
PerfEventOpen(uint32_t cpu,perf_event_attr * perf_attr,int group_fd=-1)60*6dbdd20aSAndroid Build Coastguard Worker base::ScopedFile PerfEventOpen(uint32_t cpu,
61*6dbdd20aSAndroid Build Coastguard Worker                                perf_event_attr* perf_attr,
62*6dbdd20aSAndroid Build Coastguard Worker                                int group_fd = -1) {
63*6dbdd20aSAndroid Build Coastguard Worker   base::ScopedFile perf_fd{perf_event_open(perf_attr, /*pid=*/-1,
64*6dbdd20aSAndroid Build Coastguard Worker                                            static_cast<int>(cpu), group_fd,
65*6dbdd20aSAndroid Build Coastguard Worker                                            PERF_FLAG_FD_CLOEXEC)};
66*6dbdd20aSAndroid Build Coastguard Worker   return perf_fd;
67*6dbdd20aSAndroid Build Coastguard Worker }
68*6dbdd20aSAndroid Build Coastguard Worker 
69*6dbdd20aSAndroid Build Coastguard Worker // If counting tracepoints, set an event filter if requested.
MaybeApplyTracepointFilter(int fd,const PerfCounter & event)70*6dbdd20aSAndroid Build Coastguard Worker bool MaybeApplyTracepointFilter(int fd, const PerfCounter& event) {
71*6dbdd20aSAndroid Build Coastguard Worker   if (event.type != PerfCounter::Type::kTracepoint ||
72*6dbdd20aSAndroid Build Coastguard Worker       event.tracepoint_filter.empty()) {
73*6dbdd20aSAndroid Build Coastguard Worker     return true;
74*6dbdd20aSAndroid Build Coastguard Worker   }
75*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(event.attr_type == PERF_TYPE_TRACEPOINT);
76*6dbdd20aSAndroid Build Coastguard Worker 
77*6dbdd20aSAndroid Build Coastguard Worker   if (ioctl(fd, PERF_EVENT_IOC_SET_FILTER, event.tracepoint_filter.c_str())) {
78*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_PLOG("Failed ioctl to set event filter");
79*6dbdd20aSAndroid Build Coastguard Worker     return false;
80*6dbdd20aSAndroid Build Coastguard Worker   }
81*6dbdd20aSAndroid Build Coastguard Worker   return true;
82*6dbdd20aSAndroid Build Coastguard Worker }
83*6dbdd20aSAndroid Build Coastguard Worker 
84*6dbdd20aSAndroid Build Coastguard Worker }  // namespace
85*6dbdd20aSAndroid Build Coastguard Worker 
PerfRingBuffer(PerfRingBuffer && other)86*6dbdd20aSAndroid Build Coastguard Worker PerfRingBuffer::PerfRingBuffer(PerfRingBuffer&& other) noexcept
87*6dbdd20aSAndroid Build Coastguard Worker     : metadata_page_(other.metadata_page_),
88*6dbdd20aSAndroid Build Coastguard Worker       mmap_sz_(other.mmap_sz_),
89*6dbdd20aSAndroid Build Coastguard Worker       data_buf_(other.data_buf_),
90*6dbdd20aSAndroid Build Coastguard Worker       data_buf_sz_(other.data_buf_sz_) {
91*6dbdd20aSAndroid Build Coastguard Worker   other.metadata_page_ = nullptr;
92*6dbdd20aSAndroid Build Coastguard Worker   other.mmap_sz_ = 0;
93*6dbdd20aSAndroid Build Coastguard Worker   other.data_buf_ = nullptr;
94*6dbdd20aSAndroid Build Coastguard Worker   other.data_buf_sz_ = 0;
95*6dbdd20aSAndroid Build Coastguard Worker }
96*6dbdd20aSAndroid Build Coastguard Worker 
operator =(PerfRingBuffer && other)97*6dbdd20aSAndroid Build Coastguard Worker PerfRingBuffer& PerfRingBuffer::operator=(PerfRingBuffer&& other) noexcept {
98*6dbdd20aSAndroid Build Coastguard Worker   if (this == &other)
99*6dbdd20aSAndroid Build Coastguard Worker     return *this;
100*6dbdd20aSAndroid Build Coastguard Worker 
101*6dbdd20aSAndroid Build Coastguard Worker   this->~PerfRingBuffer();
102*6dbdd20aSAndroid Build Coastguard Worker   new (this) PerfRingBuffer(std::move(other));
103*6dbdd20aSAndroid Build Coastguard Worker   return *this;
104*6dbdd20aSAndroid Build Coastguard Worker }
105*6dbdd20aSAndroid Build Coastguard Worker 
~PerfRingBuffer()106*6dbdd20aSAndroid Build Coastguard Worker PerfRingBuffer::~PerfRingBuffer() {
107*6dbdd20aSAndroid Build Coastguard Worker   if (!valid())
108*6dbdd20aSAndroid Build Coastguard Worker     return;
109*6dbdd20aSAndroid Build Coastguard Worker 
110*6dbdd20aSAndroid Build Coastguard Worker   if (munmap(reinterpret_cast<void*>(metadata_page_), mmap_sz_) != 0)
111*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_PLOG("failed munmap");
112*6dbdd20aSAndroid Build Coastguard Worker }
113*6dbdd20aSAndroid Build Coastguard Worker 
Allocate(int perf_fd,size_t data_page_count)114*6dbdd20aSAndroid Build Coastguard Worker std::optional<PerfRingBuffer> PerfRingBuffer::Allocate(int perf_fd,
115*6dbdd20aSAndroid Build Coastguard Worker                                                        size_t data_page_count) {
116*6dbdd20aSAndroid Build Coastguard Worker   // perf_event_open requires the ring buffer to be a power of two in size.
117*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(IsPowerOfTwo(data_page_count));
118*6dbdd20aSAndroid Build Coastguard Worker 
119*6dbdd20aSAndroid Build Coastguard Worker   PerfRingBuffer ret;
120*6dbdd20aSAndroid Build Coastguard Worker 
121*6dbdd20aSAndroid Build Coastguard Worker   // mmap request is one page larger than the buffer size (for the metadata).
122*6dbdd20aSAndroid Build Coastguard Worker   ret.data_buf_sz_ = data_page_count * base::GetSysPageSize();
123*6dbdd20aSAndroid Build Coastguard Worker   ret.mmap_sz_ = ret.data_buf_sz_ + base::GetSysPageSize();
124*6dbdd20aSAndroid Build Coastguard Worker 
125*6dbdd20aSAndroid Build Coastguard Worker   // If PROT_WRITE, kernel won't overwrite unread samples.
126*6dbdd20aSAndroid Build Coastguard Worker   void* mmap_addr = mmap(nullptr, ret.mmap_sz_, PROT_READ | PROT_WRITE,
127*6dbdd20aSAndroid Build Coastguard Worker                          MAP_SHARED, perf_fd, 0);
128*6dbdd20aSAndroid Build Coastguard Worker   if (mmap_addr == MAP_FAILED) {
129*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_PLOG("failed mmap");
130*6dbdd20aSAndroid Build Coastguard Worker     return std::nullopt;
131*6dbdd20aSAndroid Build Coastguard Worker   }
132*6dbdd20aSAndroid Build Coastguard Worker 
133*6dbdd20aSAndroid Build Coastguard Worker   // Expected layout is [ metadata page ] [ data pages ... ]
134*6dbdd20aSAndroid Build Coastguard Worker   ret.metadata_page_ = reinterpret_cast<perf_event_mmap_page*>(mmap_addr);
135*6dbdd20aSAndroid Build Coastguard Worker   ret.data_buf_ = reinterpret_cast<char*>(mmap_addr) + base::GetSysPageSize();
136*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(ret.metadata_page_->data_offset == base::GetSysPageSize());
137*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(ret.metadata_page_->data_size == ret.data_buf_sz_);
138*6dbdd20aSAndroid Build Coastguard Worker 
139*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(IsPowerOfTwo(ret.data_buf_sz_));
140*6dbdd20aSAndroid Build Coastguard Worker 
141*6dbdd20aSAndroid Build Coastguard Worker   return std::make_optional(std::move(ret));
142*6dbdd20aSAndroid Build Coastguard Worker }
143*6dbdd20aSAndroid Build Coastguard Worker 
144*6dbdd20aSAndroid Build Coastguard Worker // See |perf_output_put_handle| for the necessary synchronization between the
145*6dbdd20aSAndroid Build Coastguard Worker // kernel and this userspace thread (which are using the same shared memory, but
146*6dbdd20aSAndroid Build Coastguard Worker // might be on different cores).
147*6dbdd20aSAndroid Build Coastguard Worker // TODO(rsavitski): is there false sharing between |data_tail| and |data_head|?
148*6dbdd20aSAndroid Build Coastguard Worker // Is there an argument for maintaining our own copy of |data_tail| instead of
149*6dbdd20aSAndroid Build Coastguard Worker // reloading it?
ReadRecordNonconsuming()150*6dbdd20aSAndroid Build Coastguard Worker char* PerfRingBuffer::ReadRecordNonconsuming() {
151*6dbdd20aSAndroid Build Coastguard Worker   static_assert(sizeof(std::atomic<uint64_t>) == sizeof(uint64_t), "");
152*6dbdd20aSAndroid Build Coastguard Worker 
153*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(valid());
154*6dbdd20aSAndroid Build Coastguard Worker 
155*6dbdd20aSAndroid Build Coastguard Worker   // |data_tail| is written only by this userspace thread, so we can safely read
156*6dbdd20aSAndroid Build Coastguard Worker   // it without any synchronization.
157*6dbdd20aSAndroid Build Coastguard Worker   uint64_t read_offset = metadata_page_->data_tail;
158*6dbdd20aSAndroid Build Coastguard Worker 
159*6dbdd20aSAndroid Build Coastguard Worker   // |data_head| is written by the kernel, perform an acquiring load such that
160*6dbdd20aSAndroid Build Coastguard Worker   // the payload reads below are ordered after this load.
161*6dbdd20aSAndroid Build Coastguard Worker   uint64_t write_offset =
162*6dbdd20aSAndroid Build Coastguard Worker       reinterpret_cast<std::atomic<uint64_t>*>(&metadata_page_->data_head)
163*6dbdd20aSAndroid Build Coastguard Worker           ->load(std::memory_order_acquire);
164*6dbdd20aSAndroid Build Coastguard Worker 
165*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(read_offset <= write_offset);
166*6dbdd20aSAndroid Build Coastguard Worker   if (write_offset == read_offset)
167*6dbdd20aSAndroid Build Coastguard Worker     return nullptr;  // no new data
168*6dbdd20aSAndroid Build Coastguard Worker 
169*6dbdd20aSAndroid Build Coastguard Worker   size_t read_pos = static_cast<size_t>(read_offset & (data_buf_sz_ - 1));
170*6dbdd20aSAndroid Build Coastguard Worker 
171*6dbdd20aSAndroid Build Coastguard Worker   // event header (64 bits) guaranteed to be contiguous
172*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(read_pos <= data_buf_sz_ - sizeof(perf_event_header));
173*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(0 == reinterpret_cast<size_t>(data_buf_ + read_pos) %
174*6dbdd20aSAndroid Build Coastguard Worker                            alignof(perf_event_header));
175*6dbdd20aSAndroid Build Coastguard Worker 
176*6dbdd20aSAndroid Build Coastguard Worker   perf_event_header* evt_header =
177*6dbdd20aSAndroid Build Coastguard Worker       reinterpret_cast<perf_event_header*>(data_buf_ + read_pos);
178*6dbdd20aSAndroid Build Coastguard Worker   uint16_t evt_size = evt_header->size;
179*6dbdd20aSAndroid Build Coastguard Worker 
180*6dbdd20aSAndroid Build Coastguard Worker   // event wrapped - reconstruct it, and return a pointer to the buffer
181*6dbdd20aSAndroid Build Coastguard Worker   if (read_pos + evt_size > data_buf_sz_) {
182*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DLOG("PerfRingBuffer: returning reconstructed event");
183*6dbdd20aSAndroid Build Coastguard Worker 
184*6dbdd20aSAndroid Build Coastguard Worker     size_t prefix_sz = data_buf_sz_ - read_pos;
185*6dbdd20aSAndroid Build Coastguard Worker     memcpy(&reconstructed_record_[0], data_buf_ + read_pos, prefix_sz);
186*6dbdd20aSAndroid Build Coastguard Worker     memcpy(&reconstructed_record_[0] + prefix_sz, data_buf_,
187*6dbdd20aSAndroid Build Coastguard Worker            evt_size - prefix_sz);
188*6dbdd20aSAndroid Build Coastguard Worker     return &reconstructed_record_[0];
189*6dbdd20aSAndroid Build Coastguard Worker   } else {
190*6dbdd20aSAndroid Build Coastguard Worker     // usual case - contiguous sample
191*6dbdd20aSAndroid Build Coastguard Worker     return data_buf_ + read_pos;
192*6dbdd20aSAndroid Build Coastguard Worker   }
193*6dbdd20aSAndroid Build Coastguard Worker }
194*6dbdd20aSAndroid Build Coastguard Worker 
Consume(size_t bytes)195*6dbdd20aSAndroid Build Coastguard Worker void PerfRingBuffer::Consume(size_t bytes) {
196*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(valid());
197*6dbdd20aSAndroid Build Coastguard Worker 
198*6dbdd20aSAndroid Build Coastguard Worker   // Advance |data_tail|, which is written only by this thread. The store of the
199*6dbdd20aSAndroid Build Coastguard Worker   // updated value needs to have release semantics such that the preceding
200*6dbdd20aSAndroid Build Coastguard Worker   // payload reads are ordered before it. The reader in this case is the kernel,
201*6dbdd20aSAndroid Build Coastguard Worker   // which reads |data_tail| to calculate the available ring buffer capacity
202*6dbdd20aSAndroid Build Coastguard Worker   // before trying to store a new record.
203*6dbdd20aSAndroid Build Coastguard Worker   uint64_t updated_tail = metadata_page_->data_tail + bytes;
204*6dbdd20aSAndroid Build Coastguard Worker   reinterpret_cast<std::atomic<uint64_t>*>(&metadata_page_->data_tail)
205*6dbdd20aSAndroid Build Coastguard Worker       ->store(updated_tail, std::memory_order_release);
206*6dbdd20aSAndroid Build Coastguard Worker }
207*6dbdd20aSAndroid Build Coastguard Worker 
EventReader(uint32_t cpu,perf_event_attr event_attr,base::ScopedFile perf_fd,std::vector<base::ScopedFile> followers_fds,PerfRingBuffer ring_buffer)208*6dbdd20aSAndroid Build Coastguard Worker EventReader::EventReader(uint32_t cpu,
209*6dbdd20aSAndroid Build Coastguard Worker                          perf_event_attr event_attr,
210*6dbdd20aSAndroid Build Coastguard Worker                          base::ScopedFile perf_fd,
211*6dbdd20aSAndroid Build Coastguard Worker                          std::vector<base::ScopedFile> followers_fds,
212*6dbdd20aSAndroid Build Coastguard Worker                          PerfRingBuffer ring_buffer)
213*6dbdd20aSAndroid Build Coastguard Worker     : cpu_(cpu),
214*6dbdd20aSAndroid Build Coastguard Worker       event_attr_(event_attr),
215*6dbdd20aSAndroid Build Coastguard Worker       perf_fd_(std::move(perf_fd)),
216*6dbdd20aSAndroid Build Coastguard Worker       follower_fds_(std::move(followers_fds)),
217*6dbdd20aSAndroid Build Coastguard Worker       ring_buffer_(std::move(ring_buffer)) {}
218*6dbdd20aSAndroid Build Coastguard Worker 
operator =(EventReader && other)219*6dbdd20aSAndroid Build Coastguard Worker EventReader& EventReader::operator=(EventReader&& other) noexcept {
220*6dbdd20aSAndroid Build Coastguard Worker   if (this == &other)
221*6dbdd20aSAndroid Build Coastguard Worker     return *this;
222*6dbdd20aSAndroid Build Coastguard Worker 
223*6dbdd20aSAndroid Build Coastguard Worker   this->~EventReader();
224*6dbdd20aSAndroid Build Coastguard Worker   new (this) EventReader(std::move(other));
225*6dbdd20aSAndroid Build Coastguard Worker   return *this;
226*6dbdd20aSAndroid Build Coastguard Worker }
227*6dbdd20aSAndroid Build Coastguard Worker 
ConfigureEvents(uint32_t cpu,const EventConfig & event_cfg)228*6dbdd20aSAndroid Build Coastguard Worker std::optional<EventReader> EventReader::ConfigureEvents(
229*6dbdd20aSAndroid Build Coastguard Worker     uint32_t cpu,
230*6dbdd20aSAndroid Build Coastguard Worker     const EventConfig& event_cfg) {
231*6dbdd20aSAndroid Build Coastguard Worker   auto timebase_fd = PerfEventOpen(cpu, event_cfg.perf_attr());
232*6dbdd20aSAndroid Build Coastguard Worker   if (!timebase_fd) {
233*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_PLOG("Failed perf_event_open");
234*6dbdd20aSAndroid Build Coastguard Worker     return std::nullopt;
235*6dbdd20aSAndroid Build Coastguard Worker   }
236*6dbdd20aSAndroid Build Coastguard Worker 
237*6dbdd20aSAndroid Build Coastguard Worker   // Open followers.
238*6dbdd20aSAndroid Build Coastguard Worker   std::vector<base::ScopedFile> follower_fds;
239*6dbdd20aSAndroid Build Coastguard Worker   for (auto follower_attr : event_cfg.perf_attr_followers()) {
240*6dbdd20aSAndroid Build Coastguard Worker     auto follower_fd = PerfEventOpen(cpu, &follower_attr, timebase_fd.get());
241*6dbdd20aSAndroid Build Coastguard Worker     if (!follower_fd) {
242*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_PLOG("Failed perf_event_open (follower)");
243*6dbdd20aSAndroid Build Coastguard Worker       return std::nullopt;
244*6dbdd20aSAndroid Build Coastguard Worker     }
245*6dbdd20aSAndroid Build Coastguard Worker     follower_fds.push_back(std::move(follower_fd));
246*6dbdd20aSAndroid Build Coastguard Worker   }
247*6dbdd20aSAndroid Build Coastguard Worker 
248*6dbdd20aSAndroid Build Coastguard Worker   // Apply the tracepoint to the timebase.
249*6dbdd20aSAndroid Build Coastguard Worker   if (!MaybeApplyTracepointFilter(timebase_fd.get(),
250*6dbdd20aSAndroid Build Coastguard Worker                                   event_cfg.timebase_event()))
251*6dbdd20aSAndroid Build Coastguard Worker     return std::nullopt;
252*6dbdd20aSAndroid Build Coastguard Worker 
253*6dbdd20aSAndroid Build Coastguard Worker   // Apply the tracepoint to the followers.
254*6dbdd20aSAndroid Build Coastguard Worker   if (follower_fds.size() != event_cfg.follower_events().size()) {
255*6dbdd20aSAndroid Build Coastguard Worker     return std::nullopt;
256*6dbdd20aSAndroid Build Coastguard Worker   }
257*6dbdd20aSAndroid Build Coastguard Worker 
258*6dbdd20aSAndroid Build Coastguard Worker   for (size_t i = 0; i < follower_fds.size(); ++i) {
259*6dbdd20aSAndroid Build Coastguard Worker     if (!MaybeApplyTracepointFilter(follower_fds[i].get(),
260*6dbdd20aSAndroid Build Coastguard Worker                                     event_cfg.follower_events()[i]))
261*6dbdd20aSAndroid Build Coastguard Worker       return std::nullopt;
262*6dbdd20aSAndroid Build Coastguard Worker   }
263*6dbdd20aSAndroid Build Coastguard Worker 
264*6dbdd20aSAndroid Build Coastguard Worker   auto ring_buffer = PerfRingBuffer::Allocate(timebase_fd.get(),
265*6dbdd20aSAndroid Build Coastguard Worker                                               event_cfg.ring_buffer_pages());
266*6dbdd20aSAndroid Build Coastguard Worker   if (!ring_buffer.has_value()) {
267*6dbdd20aSAndroid Build Coastguard Worker     return std::nullopt;
268*6dbdd20aSAndroid Build Coastguard Worker   }
269*6dbdd20aSAndroid Build Coastguard Worker   return EventReader(cpu, *event_cfg.perf_attr(), std::move(timebase_fd),
270*6dbdd20aSAndroid Build Coastguard Worker                      std::move(follower_fds), std::move(ring_buffer.value()));
271*6dbdd20aSAndroid Build Coastguard Worker }
272*6dbdd20aSAndroid Build Coastguard Worker 
ReadUntilSample(std::function<void (uint64_t)> records_lost_callback)273*6dbdd20aSAndroid Build Coastguard Worker std::optional<ParsedSample> EventReader::ReadUntilSample(
274*6dbdd20aSAndroid Build Coastguard Worker     std::function<void(uint64_t)> records_lost_callback) {
275*6dbdd20aSAndroid Build Coastguard Worker   for (;;) {
276*6dbdd20aSAndroid Build Coastguard Worker     char* event = ring_buffer_.ReadRecordNonconsuming();
277*6dbdd20aSAndroid Build Coastguard Worker     if (!event)
278*6dbdd20aSAndroid Build Coastguard Worker       return std::nullopt;  // caught up with the writer
279*6dbdd20aSAndroid Build Coastguard Worker 
280*6dbdd20aSAndroid Build Coastguard Worker     auto* event_hdr = reinterpret_cast<const perf_event_header*>(event);
281*6dbdd20aSAndroid Build Coastguard Worker 
282*6dbdd20aSAndroid Build Coastguard Worker     if (event_hdr->type == PERF_RECORD_SAMPLE) {
283*6dbdd20aSAndroid Build Coastguard Worker       ParsedSample sample = ParseSampleRecord(cpu_, event);
284*6dbdd20aSAndroid Build Coastguard Worker       ring_buffer_.Consume(event_hdr->size);
285*6dbdd20aSAndroid Build Coastguard Worker       return std::make_optional(std::move(sample));
286*6dbdd20aSAndroid Build Coastguard Worker     }
287*6dbdd20aSAndroid Build Coastguard Worker 
288*6dbdd20aSAndroid Build Coastguard Worker     if (event_hdr->type == PERF_RECORD_LOST) {
289*6dbdd20aSAndroid Build Coastguard Worker       /*
290*6dbdd20aSAndroid Build Coastguard Worker        * struct {
291*6dbdd20aSAndroid Build Coastguard Worker        *   struct perf_event_header header;
292*6dbdd20aSAndroid Build Coastguard Worker        *   u64 id;
293*6dbdd20aSAndroid Build Coastguard Worker        *   u64 lost;
294*6dbdd20aSAndroid Build Coastguard Worker        *   struct sample_id sample_id;
295*6dbdd20aSAndroid Build Coastguard Worker        * };
296*6dbdd20aSAndroid Build Coastguard Worker        */
297*6dbdd20aSAndroid Build Coastguard Worker       uint64_t records_lost = *reinterpret_cast<const uint64_t*>(
298*6dbdd20aSAndroid Build Coastguard Worker           event + sizeof(perf_event_header) + sizeof(uint64_t));
299*6dbdd20aSAndroid Build Coastguard Worker 
300*6dbdd20aSAndroid Build Coastguard Worker       records_lost_callback(records_lost);
301*6dbdd20aSAndroid Build Coastguard Worker       ring_buffer_.Consume(event_hdr->size);
302*6dbdd20aSAndroid Build Coastguard Worker       continue;  // keep looking for a sample
303*6dbdd20aSAndroid Build Coastguard Worker     }
304*6dbdd20aSAndroid Build Coastguard Worker 
305*6dbdd20aSAndroid Build Coastguard Worker     // Kernel had to throttle irqs.
306*6dbdd20aSAndroid Build Coastguard Worker     if (event_hdr->type == PERF_RECORD_THROTTLE ||
307*6dbdd20aSAndroid Build Coastguard Worker         event_hdr->type == PERF_RECORD_UNTHROTTLE) {
308*6dbdd20aSAndroid Build Coastguard Worker       ring_buffer_.Consume(event_hdr->size);
309*6dbdd20aSAndroid Build Coastguard Worker       continue;  // keep looking for a sample
310*6dbdd20aSAndroid Build Coastguard Worker     }
311*6dbdd20aSAndroid Build Coastguard Worker 
312*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_DFATAL_OR_ELOG("Unsupported event type [%zu]",
313*6dbdd20aSAndroid Build Coastguard Worker                             static_cast<size_t>(event_hdr->type));
314*6dbdd20aSAndroid Build Coastguard Worker     ring_buffer_.Consume(event_hdr->size);
315*6dbdd20aSAndroid Build Coastguard Worker   }
316*6dbdd20aSAndroid Build Coastguard Worker }
317*6dbdd20aSAndroid Build Coastguard Worker 
318*6dbdd20aSAndroid Build Coastguard Worker // Generally, samples can belong to any cpu (which can be recorded with
319*6dbdd20aSAndroid Build Coastguard Worker // PERF_SAMPLE_CPU). However, this producer uses only cpu-scoped events,
320*6dbdd20aSAndroid Build Coastguard Worker // therefore it is already known.
ParseSampleRecord(uint32_t cpu,const char * record_start)321*6dbdd20aSAndroid Build Coastguard Worker ParsedSample EventReader::ParseSampleRecord(uint32_t cpu,
322*6dbdd20aSAndroid Build Coastguard Worker                                             const char* record_start) {
323*6dbdd20aSAndroid Build Coastguard Worker   if (event_attr_.sample_type &
324*6dbdd20aSAndroid Build Coastguard Worker       (~uint64_t(PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_STACK_USER |
325*6dbdd20aSAndroid Build Coastguard Worker                  PERF_SAMPLE_REGS_USER | PERF_SAMPLE_CALLCHAIN |
326*6dbdd20aSAndroid Build Coastguard Worker                  PERF_SAMPLE_READ))) {
327*6dbdd20aSAndroid Build Coastguard Worker     PERFETTO_FATAL("Unsupported sampling option");
328*6dbdd20aSAndroid Build Coastguard Worker   }
329*6dbdd20aSAndroid Build Coastguard Worker 
330*6dbdd20aSAndroid Build Coastguard Worker   auto* event_hdr = reinterpret_cast<const perf_event_header*>(record_start);
331*6dbdd20aSAndroid Build Coastguard Worker   size_t sample_size = event_hdr->size;
332*6dbdd20aSAndroid Build Coastguard Worker 
333*6dbdd20aSAndroid Build Coastguard Worker   ParsedSample sample = {};
334*6dbdd20aSAndroid Build Coastguard Worker   sample.common.cpu = cpu;
335*6dbdd20aSAndroid Build Coastguard Worker   sample.common.cpu_mode = event_hdr->misc & PERF_RECORD_MISC_CPUMODE_MASK;
336*6dbdd20aSAndroid Build Coastguard Worker 
337*6dbdd20aSAndroid Build Coastguard Worker   // Parse the payload, which consists of concatenated data for each
338*6dbdd20aSAndroid Build Coastguard Worker   // |attr.sample_type| flag.
339*6dbdd20aSAndroid Build Coastguard Worker   const char* parse_pos = record_start + sizeof(perf_event_header);
340*6dbdd20aSAndroid Build Coastguard Worker 
341*6dbdd20aSAndroid Build Coastguard Worker   if (event_attr_.sample_type & PERF_SAMPLE_TID) {
342*6dbdd20aSAndroid Build Coastguard Worker     uint32_t pid = 0;
343*6dbdd20aSAndroid Build Coastguard Worker     uint32_t tid = 0;
344*6dbdd20aSAndroid Build Coastguard Worker     parse_pos = ReadValue(&pid, parse_pos);
345*6dbdd20aSAndroid Build Coastguard Worker     parse_pos = ReadValue(&tid, parse_pos);
346*6dbdd20aSAndroid Build Coastguard Worker     sample.common.pid = static_cast<pid_t>(pid);
347*6dbdd20aSAndroid Build Coastguard Worker     sample.common.tid = static_cast<pid_t>(tid);
348*6dbdd20aSAndroid Build Coastguard Worker   }
349*6dbdd20aSAndroid Build Coastguard Worker 
350*6dbdd20aSAndroid Build Coastguard Worker   if (event_attr_.sample_type & PERF_SAMPLE_TIME) {
351*6dbdd20aSAndroid Build Coastguard Worker     parse_pos = ReadValue(&sample.common.timestamp, parse_pos);
352*6dbdd20aSAndroid Build Coastguard Worker   }
353*6dbdd20aSAndroid Build Coastguard Worker 
354*6dbdd20aSAndroid Build Coastguard Worker   if (event_attr_.sample_type & PERF_SAMPLE_READ) {
355*6dbdd20aSAndroid Build Coastguard Worker     if (event_attr_.read_format & PERF_FORMAT_GROUP) {
356*6dbdd20aSAndroid Build Coastguard Worker       // When PERF_FORMAT_GROUP is specified, the record starts with the number
357*6dbdd20aSAndroid Build Coastguard Worker       // of events it contains followed by the events. The event list always
358*6dbdd20aSAndroid Build Coastguard Worker       // starts with the value of the timebase.
359*6dbdd20aSAndroid Build Coastguard Worker       // In a ParsedSample, the value of the timebase goes into timebase_count
360*6dbdd20aSAndroid Build Coastguard Worker       // and the value of the followers events goes into follower_counts.
361*6dbdd20aSAndroid Build Coastguard Worker       uint64_t nr = 0;
362*6dbdd20aSAndroid Build Coastguard Worker       parse_pos = ReadValue(&nr, parse_pos);
363*6dbdd20aSAndroid Build Coastguard Worker       PERFETTO_CHECK(nr != 0);
364*6dbdd20aSAndroid Build Coastguard Worker       parse_pos = ReadValue(&sample.common.timebase_count, parse_pos);
365*6dbdd20aSAndroid Build Coastguard Worker       sample.common.follower_counts.resize(nr - 1);
366*6dbdd20aSAndroid Build Coastguard Worker       for (size_t i = 0; i < nr - 1; ++i) {
367*6dbdd20aSAndroid Build Coastguard Worker         parse_pos = ReadValue(&sample.common.follower_counts[i], parse_pos);
368*6dbdd20aSAndroid Build Coastguard Worker       }
369*6dbdd20aSAndroid Build Coastguard Worker     } else {
370*6dbdd20aSAndroid Build Coastguard Worker       parse_pos = ReadValue(&sample.common.timebase_count, parse_pos);
371*6dbdd20aSAndroid Build Coastguard Worker     }
372*6dbdd20aSAndroid Build Coastguard Worker   }
373*6dbdd20aSAndroid Build Coastguard Worker 
374*6dbdd20aSAndroid Build Coastguard Worker   if (event_attr_.sample_type & PERF_SAMPLE_CALLCHAIN) {
375*6dbdd20aSAndroid Build Coastguard Worker     uint64_t chain_len = 0;
376*6dbdd20aSAndroid Build Coastguard Worker     parse_pos = ReadValue(&chain_len, parse_pos);
377*6dbdd20aSAndroid Build Coastguard Worker     sample.kernel_ips.resize(static_cast<size_t>(chain_len));
378*6dbdd20aSAndroid Build Coastguard Worker     parse_pos = ReadValues<uint64_t>(sample.kernel_ips.data(), parse_pos,
379*6dbdd20aSAndroid Build Coastguard Worker                                      static_cast<size_t>(chain_len));
380*6dbdd20aSAndroid Build Coastguard Worker   }
381*6dbdd20aSAndroid Build Coastguard Worker 
382*6dbdd20aSAndroid Build Coastguard Worker   if (event_attr_.sample_type & PERF_SAMPLE_REGS_USER) {
383*6dbdd20aSAndroid Build Coastguard Worker     // Can be empty, e.g. if we sampled a kernel thread.
384*6dbdd20aSAndroid Build Coastguard Worker     sample.regs = ReadPerfUserRegsData(&parse_pos);
385*6dbdd20aSAndroid Build Coastguard Worker   }
386*6dbdd20aSAndroid Build Coastguard Worker 
387*6dbdd20aSAndroid Build Coastguard Worker   if (event_attr_.sample_type & PERF_SAMPLE_STACK_USER) {
388*6dbdd20aSAndroid Build Coastguard Worker     // Maximum possible sampled stack size for this sample. Can be lower than
389*6dbdd20aSAndroid Build Coastguard Worker     // the requested size if there wasn't enough room in the sample (which is
390*6dbdd20aSAndroid Build Coastguard Worker     // limited to 64k).
391*6dbdd20aSAndroid Build Coastguard Worker     uint64_t max_stack_size;
392*6dbdd20aSAndroid Build Coastguard Worker     parse_pos = ReadValue(&max_stack_size, parse_pos);
393*6dbdd20aSAndroid Build Coastguard Worker 
394*6dbdd20aSAndroid Build Coastguard Worker     const char* stack_start = parse_pos;
395*6dbdd20aSAndroid Build Coastguard Worker     parse_pos += max_stack_size;  // skip to dyn_size
396*6dbdd20aSAndroid Build Coastguard Worker 
397*6dbdd20aSAndroid Build Coastguard Worker     // Payload written conditionally, e.g. kernel threads don't have a
398*6dbdd20aSAndroid Build Coastguard Worker     // user stack.
399*6dbdd20aSAndroid Build Coastguard Worker     if (max_stack_size > 0) {
400*6dbdd20aSAndroid Build Coastguard Worker       uint64_t filled_stack_size;
401*6dbdd20aSAndroid Build Coastguard Worker       parse_pos = ReadValue(&filled_stack_size, parse_pos);
402*6dbdd20aSAndroid Build Coastguard Worker 
403*6dbdd20aSAndroid Build Coastguard Worker       // copy stack bytes into a vector
404*6dbdd20aSAndroid Build Coastguard Worker       size_t payload_sz = static_cast<size_t>(filled_stack_size);
405*6dbdd20aSAndroid Build Coastguard Worker       sample.stack.resize(payload_sz);
406*6dbdd20aSAndroid Build Coastguard Worker       memcpy(sample.stack.data(), stack_start, payload_sz);
407*6dbdd20aSAndroid Build Coastguard Worker 
408*6dbdd20aSAndroid Build Coastguard Worker       // remember whether the stack sample is (most likely) truncated
409*6dbdd20aSAndroid Build Coastguard Worker       sample.stack_maxed = (filled_stack_size == max_stack_size);
410*6dbdd20aSAndroid Build Coastguard Worker     }
411*6dbdd20aSAndroid Build Coastguard Worker   }
412*6dbdd20aSAndroid Build Coastguard Worker 
413*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(parse_pos == record_start + sample_size);
414*6dbdd20aSAndroid Build Coastguard Worker   return sample;
415*6dbdd20aSAndroid Build Coastguard Worker }
416*6dbdd20aSAndroid Build Coastguard Worker 
EnableEvents()417*6dbdd20aSAndroid Build Coastguard Worker void EventReader::EnableEvents() {
418*6dbdd20aSAndroid Build Coastguard Worker   int ret = ioctl(perf_fd_.get(), PERF_EVENT_IOC_ENABLE);
419*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(ret == 0);
420*6dbdd20aSAndroid Build Coastguard Worker }
421*6dbdd20aSAndroid Build Coastguard Worker 
DisableEvents()422*6dbdd20aSAndroid Build Coastguard Worker void EventReader::DisableEvents() {
423*6dbdd20aSAndroid Build Coastguard Worker   int ret = ioctl(perf_fd_.get(), PERF_EVENT_IOC_DISABLE);
424*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_CHECK(ret == 0);
425*6dbdd20aSAndroid Build Coastguard Worker }
426*6dbdd20aSAndroid Build Coastguard Worker 
427*6dbdd20aSAndroid Build Coastguard Worker }  // namespace profiling
428*6dbdd20aSAndroid Build Coastguard Worker }  // namespace perfetto
429