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