xref: /aosp_15_r20/external/perfetto/src/profiling/perf/event_reader.h (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 #ifndef SRC_PROFILING_PERF_EVENT_READER_H_
18*6dbdd20aSAndroid Build Coastguard Worker #define SRC_PROFILING_PERF_EVENT_READER_H_
19*6dbdd20aSAndroid Build Coastguard Worker 
20*6dbdd20aSAndroid Build Coastguard Worker #include <linux/perf_event.h>
21*6dbdd20aSAndroid Build Coastguard Worker #include <stdint.h>
22*6dbdd20aSAndroid Build Coastguard Worker #include <sys/mman.h>
23*6dbdd20aSAndroid Build Coastguard Worker #include <sys/types.h>
24*6dbdd20aSAndroid Build Coastguard Worker #include <optional>
25*6dbdd20aSAndroid Build Coastguard Worker 
26*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/scoped_file.h"
27*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/tracing/core/basic_types.h"
28*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/perf/common_types.h"
29*6dbdd20aSAndroid Build Coastguard Worker #include "src/profiling/perf/event_config.h"
30*6dbdd20aSAndroid Build Coastguard Worker 
31*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
32*6dbdd20aSAndroid Build Coastguard Worker namespace profiling {
33*6dbdd20aSAndroid Build Coastguard Worker 
34*6dbdd20aSAndroid Build Coastguard Worker class PerfRingBuffer {
35*6dbdd20aSAndroid Build Coastguard Worker  public:
36*6dbdd20aSAndroid Build Coastguard Worker   static std::optional<PerfRingBuffer> Allocate(int perf_fd,
37*6dbdd20aSAndroid Build Coastguard Worker                                                 size_t data_page_count);
38*6dbdd20aSAndroid Build Coastguard Worker 
39*6dbdd20aSAndroid Build Coastguard Worker   ~PerfRingBuffer();
40*6dbdd20aSAndroid Build Coastguard Worker 
41*6dbdd20aSAndroid Build Coastguard Worker   // move-only
42*6dbdd20aSAndroid Build Coastguard Worker   PerfRingBuffer(const PerfRingBuffer&) = delete;
43*6dbdd20aSAndroid Build Coastguard Worker   PerfRingBuffer& operator=(const PerfRingBuffer&) = delete;
44*6dbdd20aSAndroid Build Coastguard Worker   PerfRingBuffer(PerfRingBuffer&& other) noexcept;
45*6dbdd20aSAndroid Build Coastguard Worker   PerfRingBuffer& operator=(PerfRingBuffer&& other) noexcept;
46*6dbdd20aSAndroid Build Coastguard Worker 
47*6dbdd20aSAndroid Build Coastguard Worker   char* ReadRecordNonconsuming();
48*6dbdd20aSAndroid Build Coastguard Worker   void Consume(size_t bytes);
49*6dbdd20aSAndroid Build Coastguard Worker 
50*6dbdd20aSAndroid Build Coastguard Worker  private:
51*6dbdd20aSAndroid Build Coastguard Worker   PerfRingBuffer() = default;
52*6dbdd20aSAndroid Build Coastguard Worker 
valid()53*6dbdd20aSAndroid Build Coastguard Worker   bool valid() const { return metadata_page_ != nullptr; }
54*6dbdd20aSAndroid Build Coastguard Worker 
55*6dbdd20aSAndroid Build Coastguard Worker   // Points at the start of the mmap'd region.
56*6dbdd20aSAndroid Build Coastguard Worker   perf_event_mmap_page* metadata_page_ = nullptr;
57*6dbdd20aSAndroid Build Coastguard Worker 
58*6dbdd20aSAndroid Build Coastguard Worker   // Size of the mmap'd region (1 metadata page + data_buf_sz_).
59*6dbdd20aSAndroid Build Coastguard Worker   size_t mmap_sz_ = 0;
60*6dbdd20aSAndroid Build Coastguard Worker 
61*6dbdd20aSAndroid Build Coastguard Worker   // mmap'd ring buffer
62*6dbdd20aSAndroid Build Coastguard Worker   char* data_buf_ = nullptr;
63*6dbdd20aSAndroid Build Coastguard Worker   size_t data_buf_sz_ = 0;
64*6dbdd20aSAndroid Build Coastguard Worker 
65*6dbdd20aSAndroid Build Coastguard Worker   // When a record wraps around the ring buffer boundary, it is reconstructed in
66*6dbdd20aSAndroid Build Coastguard Worker   // a contiguous form in this buffer. This allows us to always return a pointer
67*6dbdd20aSAndroid Build Coastguard Worker   // to a contiguous record.
68*6dbdd20aSAndroid Build Coastguard Worker   constexpr static size_t kMaxPerfRecordSize = 1 << 16;  // max size 64k
69*6dbdd20aSAndroid Build Coastguard Worker   alignas(uint64_t) char reconstructed_record_[kMaxPerfRecordSize];
70*6dbdd20aSAndroid Build Coastguard Worker };
71*6dbdd20aSAndroid Build Coastguard Worker 
72*6dbdd20aSAndroid Build Coastguard Worker class EventReader {
73*6dbdd20aSAndroid Build Coastguard Worker  public:
74*6dbdd20aSAndroid Build Coastguard Worker   static std::optional<EventReader> ConfigureEvents(
75*6dbdd20aSAndroid Build Coastguard Worker       uint32_t cpu,
76*6dbdd20aSAndroid Build Coastguard Worker       const EventConfig& event_cfg);
77*6dbdd20aSAndroid Build Coastguard Worker 
78*6dbdd20aSAndroid Build Coastguard Worker   // Consumes records from the ring buffer until either encountering a sample,
79*6dbdd20aSAndroid Build Coastguard Worker   // or catching up to the writer. The other record of interest
80*6dbdd20aSAndroid Build Coastguard Worker   // (PERF_RECORD_LOST) is handled via the given callback.
81*6dbdd20aSAndroid Build Coastguard Worker   std::optional<ParsedSample> ReadUntilSample(
82*6dbdd20aSAndroid Build Coastguard Worker       std::function<void(uint64_t)> lost_events_callback);
83*6dbdd20aSAndroid Build Coastguard Worker 
84*6dbdd20aSAndroid Build Coastguard Worker   void EnableEvents();
85*6dbdd20aSAndroid Build Coastguard Worker   // Pauses the event counting, without invalidating existing samples.
86*6dbdd20aSAndroid Build Coastguard Worker   void DisableEvents();
87*6dbdd20aSAndroid Build Coastguard Worker 
cpu()88*6dbdd20aSAndroid Build Coastguard Worker   uint32_t cpu() const { return cpu_; }
89*6dbdd20aSAndroid Build Coastguard Worker 
90*6dbdd20aSAndroid Build Coastguard Worker   ~EventReader() = default;
91*6dbdd20aSAndroid Build Coastguard Worker 
92*6dbdd20aSAndroid Build Coastguard Worker   // move-only
93*6dbdd20aSAndroid Build Coastguard Worker   EventReader(const EventReader&) = delete;
94*6dbdd20aSAndroid Build Coastguard Worker   EventReader& operator=(const EventReader&) = delete;
95*6dbdd20aSAndroid Build Coastguard Worker   EventReader(EventReader&&) noexcept = default;
96*6dbdd20aSAndroid Build Coastguard Worker   EventReader& operator=(EventReader&&) noexcept;
97*6dbdd20aSAndroid Build Coastguard Worker 
98*6dbdd20aSAndroid Build Coastguard Worker  private:
99*6dbdd20aSAndroid Build Coastguard Worker   EventReader(uint32_t cpu,
100*6dbdd20aSAndroid Build Coastguard Worker               perf_event_attr event_attr,
101*6dbdd20aSAndroid Build Coastguard Worker               base::ScopedFile perf_fd,
102*6dbdd20aSAndroid Build Coastguard Worker               std::vector<base::ScopedFile> followers_fds,
103*6dbdd20aSAndroid Build Coastguard Worker               PerfRingBuffer ring_buffer);
104*6dbdd20aSAndroid Build Coastguard Worker 
105*6dbdd20aSAndroid Build Coastguard Worker   ParsedSample ParseSampleRecord(uint32_t cpu, const char* record_start);
106*6dbdd20aSAndroid Build Coastguard Worker 
107*6dbdd20aSAndroid Build Coastguard Worker   // All events are cpu-bound (thread-scoped events not supported).
108*6dbdd20aSAndroid Build Coastguard Worker   const uint32_t cpu_;
109*6dbdd20aSAndroid Build Coastguard Worker   const perf_event_attr event_attr_;
110*6dbdd20aSAndroid Build Coastguard Worker   base::ScopedFile perf_fd_;
111*6dbdd20aSAndroid Build Coastguard Worker   std::vector<base::ScopedFile> follower_fds_;
112*6dbdd20aSAndroid Build Coastguard Worker   PerfRingBuffer ring_buffer_;
113*6dbdd20aSAndroid Build Coastguard Worker };
114*6dbdd20aSAndroid Build Coastguard Worker 
115*6dbdd20aSAndroid Build Coastguard Worker }  // namespace profiling
116*6dbdd20aSAndroid Build Coastguard Worker }  // namespace perfetto
117*6dbdd20aSAndroid Build Coastguard Worker 
118*6dbdd20aSAndroid Build Coastguard Worker #endif  // SRC_PROFILING_PERF_EVENT_READER_H_
119