|  | /* | 
|  | * Copyright (C) 2019 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | #ifndef SRC_PROFILING_PERF_EVENT_READER_H_ | 
|  | #define SRC_PROFILING_PERF_EVENT_READER_H_ | 
|  |  | 
|  | #include <linux/perf_event.h> | 
|  | #include <stdint.h> | 
|  | #include <sys/mman.h> | 
|  | #include <sys/types.h> | 
|  | #include <optional> | 
|  |  | 
|  | #include "perfetto/ext/base/scoped_file.h" | 
|  | #include "perfetto/ext/tracing/core/basic_types.h" | 
|  | #include "src/profiling/perf/common_types.h" | 
|  | #include "src/profiling/perf/event_config.h" | 
|  |  | 
|  | namespace perfetto { | 
|  | namespace profiling { | 
|  |  | 
|  | class PerfRingBuffer { | 
|  | public: | 
|  | static std::optional<PerfRingBuffer> Allocate(int perf_fd, | 
|  | size_t data_page_count); | 
|  |  | 
|  | ~PerfRingBuffer(); | 
|  |  | 
|  | // move-only | 
|  | PerfRingBuffer(const PerfRingBuffer&) = delete; | 
|  | PerfRingBuffer& operator=(const PerfRingBuffer&) = delete; | 
|  | PerfRingBuffer(PerfRingBuffer&& other) noexcept; | 
|  | PerfRingBuffer& operator=(PerfRingBuffer&& other) noexcept; | 
|  |  | 
|  | char* ReadRecordNonconsuming(); | 
|  | void Consume(size_t bytes); | 
|  |  | 
|  | private: | 
|  | PerfRingBuffer() = default; | 
|  |  | 
|  | bool valid() const { return metadata_page_ != nullptr; } | 
|  |  | 
|  | // Points at the start of the mmap'd region. | 
|  | perf_event_mmap_page* metadata_page_ = nullptr; | 
|  |  | 
|  | // Size of the mmap'd region (1 metadata page + data_buf_sz_). | 
|  | size_t mmap_sz_ = 0; | 
|  |  | 
|  | // mmap'd ring buffer | 
|  | char* data_buf_ = nullptr; | 
|  | size_t data_buf_sz_ = 0; | 
|  |  | 
|  | // When a record wraps around the ring buffer boundary, it is reconstructed in | 
|  | // a contiguous form in this buffer. This allows us to always return a pointer | 
|  | // to a contiguous record. | 
|  | constexpr static size_t kMaxPerfRecordSize = 1 << 16;  // max size 64k | 
|  | alignas(uint64_t) char reconstructed_record_[kMaxPerfRecordSize]; | 
|  | }; | 
|  |  | 
|  | class EventReader { | 
|  | public: | 
|  | static std::optional<EventReader> ConfigureEvents( | 
|  | uint32_t cpu, | 
|  | const EventConfig& event_cfg); | 
|  |  | 
|  | // Consumes records from the ring buffer until either encountering a sample, | 
|  | // or catching up to the writer. The other record of interest | 
|  | // (PERF_RECORD_LOST) is handled via the given callback. | 
|  | std::optional<ParsedSample> ReadUntilSample( | 
|  | std::function<void(uint64_t)> lost_events_callback); | 
|  |  | 
|  | void EnableEvents(); | 
|  | // Pauses the event counting, without invalidating existing samples. | 
|  | void DisableEvents(); | 
|  |  | 
|  | uint32_t cpu() const { return cpu_; } | 
|  |  | 
|  | ~EventReader() = default; | 
|  |  | 
|  | // move-only | 
|  | EventReader(const EventReader&) = delete; | 
|  | EventReader& operator=(const EventReader&) = delete; | 
|  | EventReader(EventReader&&) noexcept = default; | 
|  | EventReader& operator=(EventReader&&) noexcept; | 
|  |  | 
|  | private: | 
|  | EventReader(uint32_t cpu, | 
|  | perf_event_attr event_attr, | 
|  | base::ScopedFile perf_fd, | 
|  | PerfRingBuffer ring_buffer); | 
|  |  | 
|  | ParsedSample ParseSampleRecord(uint32_t cpu, const char* record_start); | 
|  |  | 
|  | // All events are cpu-bound (thread-scoped events not supported). | 
|  | const uint32_t cpu_; | 
|  | const perf_event_attr event_attr_; | 
|  | base::ScopedFile perf_fd_; | 
|  | PerfRingBuffer ring_buffer_; | 
|  | }; | 
|  |  | 
|  | }  // namespace profiling | 
|  | }  // namespace perfetto | 
|  |  | 
|  | #endif  // SRC_PROFILING_PERF_EVENT_READER_H_ |