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 #pragma once 18*288bf522SAndroid Build Coastguard Worker 19*288bf522SAndroid Build Coastguard Worker #include <sys/types.h> 20*288bf522SAndroid Build Coastguard Worker 21*288bf522SAndroid Build Coastguard Worker #include <atomic> 22*288bf522SAndroid Build Coastguard Worker #include <condition_variable> 23*288bf522SAndroid Build Coastguard Worker #include <functional> 24*288bf522SAndroid Build Coastguard Worker #include <memory> 25*288bf522SAndroid Build Coastguard Worker #include <mutex> 26*288bf522SAndroid Build Coastguard Worker #include <thread> 27*288bf522SAndroid Build Coastguard Worker #include <unordered_set> 28*288bf522SAndroid Build Coastguard Worker 29*288bf522SAndroid Build Coastguard Worker #include <android-base/macros.h> 30*288bf522SAndroid Build Coastguard Worker #include <android-base/unique_fd.h> 31*288bf522SAndroid Build Coastguard Worker 32*288bf522SAndroid Build Coastguard Worker #include "event_fd.h" 33*288bf522SAndroid Build Coastguard Worker #include "record.h" 34*288bf522SAndroid Build Coastguard Worker 35*288bf522SAndroid Build Coastguard Worker namespace simpleperf { 36*288bf522SAndroid Build Coastguard Worker 37*288bf522SAndroid Build Coastguard Worker // RecordBuffer is a circular buffer used to cache records in user-space. It allows one read 38*288bf522SAndroid Build Coastguard Worker // thread and one write thread. The record read thread writes records to the buffer, and the main 39*288bf522SAndroid Build Coastguard Worker // thread reads records from the buffer. 40*288bf522SAndroid Build Coastguard Worker class RecordBuffer { 41*288bf522SAndroid Build Coastguard Worker public: 42*288bf522SAndroid Build Coastguard Worker RecordBuffer(size_t buffer_size); size()43*288bf522SAndroid Build Coastguard Worker size_t size() const { return buffer_size_; } BufferEnd()44*288bf522SAndroid Build Coastguard Worker char* BufferEnd() const { return buffer_.get() + buffer_size_; } 45*288bf522SAndroid Build Coastguard Worker 46*288bf522SAndroid Build Coastguard Worker // Return the size of writable space in the buffer. 47*288bf522SAndroid Build Coastguard Worker size_t GetFreeSize() const; 48*288bf522SAndroid Build Coastguard Worker // Allocate a writable space for a record. Return nullptr if there isn't enough space. 49*288bf522SAndroid Build Coastguard Worker char* AllocWriteSpace(size_t record_size); 50*288bf522SAndroid Build Coastguard Worker // Called after writing a record, let the read thread see the record. 51*288bf522SAndroid Build Coastguard Worker void FinishWrite(); 52*288bf522SAndroid Build Coastguard Worker 53*288bf522SAndroid Build Coastguard Worker // Get data of the current record. Return nullptr if there is no records in the buffer. 54*288bf522SAndroid Build Coastguard Worker char* GetCurrentRecord(); AddCurrentRecordSize(size_t size)55*288bf522SAndroid Build Coastguard Worker void AddCurrentRecordSize(size_t size) { cur_read_record_size_ += size; } 56*288bf522SAndroid Build Coastguard Worker // Called after reading a record, the space of the record will be writable. 57*288bf522SAndroid Build Coastguard Worker void MoveToNextRecord(); 58*288bf522SAndroid Build Coastguard Worker 59*288bf522SAndroid Build Coastguard Worker private: 60*288bf522SAndroid Build Coastguard Worker std::atomic_size_t read_head_; 61*288bf522SAndroid Build Coastguard Worker std::atomic_size_t write_head_; 62*288bf522SAndroid Build Coastguard Worker size_t cur_write_record_size_ = 0; 63*288bf522SAndroid Build Coastguard Worker size_t cur_read_record_size_ = 0; 64*288bf522SAndroid Build Coastguard Worker const size_t buffer_size_; 65*288bf522SAndroid Build Coastguard Worker std::unique_ptr<char> buffer_; 66*288bf522SAndroid Build Coastguard Worker 67*288bf522SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(RecordBuffer); 68*288bf522SAndroid Build Coastguard Worker }; 69*288bf522SAndroid Build Coastguard Worker 70*288bf522SAndroid Build Coastguard Worker // Parse positions of different fields in record data. 71*288bf522SAndroid Build Coastguard Worker class RecordParser { 72*288bf522SAndroid Build Coastguard Worker public: 73*288bf522SAndroid Build Coastguard Worker RecordParser(const perf_event_attr& attr); 74*288bf522SAndroid Build Coastguard Worker 75*288bf522SAndroid Build Coastguard Worker // Return pos of the pid field in the sample record. If not available, return 0. GetPidPosInSampleRecord()76*288bf522SAndroid Build Coastguard Worker size_t GetPidPosInSampleRecord() const { return pid_pos_in_sample_records_; } 77*288bf522SAndroid Build Coastguard Worker // Return pos of the time field in the record. If not available, return 0. 78*288bf522SAndroid Build Coastguard Worker size_t GetTimePos(const perf_event_header& header) const; 79*288bf522SAndroid Build Coastguard Worker // Return pos of the user stack size field in the sample record. If not available, return 0. 80*288bf522SAndroid Build Coastguard Worker size_t GetStackSizePos(const std::function<void(size_t, size_t, void*)>& read_record_fn) const; 81*288bf522SAndroid Build Coastguard Worker 82*288bf522SAndroid Build Coastguard Worker private: 83*288bf522SAndroid Build Coastguard Worker uint64_t sample_type_; 84*288bf522SAndroid Build Coastguard Worker uint64_t read_format_; 85*288bf522SAndroid Build Coastguard Worker uint64_t sample_regs_count_; 86*288bf522SAndroid Build Coastguard Worker size_t pid_pos_in_sample_records_ = 0; 87*288bf522SAndroid Build Coastguard Worker size_t time_pos_in_sample_records_ = 0; 88*288bf522SAndroid Build Coastguard Worker size_t time_rpos_in_non_sample_records_ = 0; 89*288bf522SAndroid Build Coastguard Worker size_t read_pos_in_sample_records_ = 0; 90*288bf522SAndroid Build Coastguard Worker }; 91*288bf522SAndroid Build Coastguard Worker 92*288bf522SAndroid Build Coastguard Worker struct RecordStat { 93*288bf522SAndroid Build Coastguard Worker size_t kernelspace_lost_records = 0; 94*288bf522SAndroid Build Coastguard Worker size_t userspace_lost_samples = 0; 95*288bf522SAndroid Build Coastguard Worker size_t userspace_lost_non_samples = 0; 96*288bf522SAndroid Build Coastguard Worker size_t userspace_truncated_stack_samples = 0; 97*288bf522SAndroid Build Coastguard Worker uint64_t aux_data_size = 0; 98*288bf522SAndroid Build Coastguard Worker uint64_t lost_aux_data_size = 0; 99*288bf522SAndroid Build Coastguard Worker }; 100*288bf522SAndroid Build Coastguard Worker 101*288bf522SAndroid Build Coastguard Worker // Read records from the kernel buffer belong to an event_fd. 102*288bf522SAndroid Build Coastguard Worker class KernelRecordReader { 103*288bf522SAndroid Build Coastguard Worker public: 104*288bf522SAndroid Build Coastguard Worker KernelRecordReader(EventFd* event_fd); 105*288bf522SAndroid Build Coastguard Worker GetEventFd()106*288bf522SAndroid Build Coastguard Worker EventFd* GetEventFd() const { return event_fd_; } 107*288bf522SAndroid Build Coastguard Worker // Get available data in the kernel buffer. Return true if there is some data. 108*288bf522SAndroid Build Coastguard Worker bool GetDataFromKernelBuffer(); 109*288bf522SAndroid Build Coastguard Worker // Get header of the current record. RecordHeader()110*288bf522SAndroid Build Coastguard Worker const perf_event_header& RecordHeader() { return record_header_; } 111*288bf522SAndroid Build Coastguard Worker // Get time of the current record. RecordTime()112*288bf522SAndroid Build Coastguard Worker uint64_t RecordTime() { return record_time_; } 113*288bf522SAndroid Build Coastguard Worker // Read data of the current record. 114*288bf522SAndroid Build Coastguard Worker void ReadRecord(size_t pos, size_t size, void* dest); 115*288bf522SAndroid Build Coastguard Worker // Move to the next record, return false if there is no more records. 116*288bf522SAndroid Build Coastguard Worker bool MoveToNextRecord(const RecordParser& parser); 117*288bf522SAndroid Build Coastguard Worker 118*288bf522SAndroid Build Coastguard Worker private: 119*288bf522SAndroid Build Coastguard Worker EventFd* event_fd_; 120*288bf522SAndroid Build Coastguard Worker char* buffer_; 121*288bf522SAndroid Build Coastguard Worker size_t buffer_mask_; 122*288bf522SAndroid Build Coastguard Worker size_t data_pos_ = 0; 123*288bf522SAndroid Build Coastguard Worker size_t data_size_ = 0; 124*288bf522SAndroid Build Coastguard Worker size_t init_data_size_ = 0; 125*288bf522SAndroid Build Coastguard Worker perf_event_header record_header_ = {}; 126*288bf522SAndroid Build Coastguard Worker uint64_t record_time_ = 0; 127*288bf522SAndroid Build Coastguard Worker }; 128*288bf522SAndroid Build Coastguard Worker 129*288bf522SAndroid Build Coastguard Worker // To reduce sample lost rate when recording dwarf based call graph, RecordReadThread uses a 130*288bf522SAndroid Build Coastguard Worker // separate high priority (nice -20) thread to read records from kernel buffers to a RecordBuffer. 131*288bf522SAndroid Build Coastguard Worker class RecordReadThread { 132*288bf522SAndroid Build Coastguard Worker public: 133*288bf522SAndroid Build Coastguard Worker RecordReadThread(size_t record_buffer_size, const perf_event_attr& attr, size_t min_mmap_pages, 134*288bf522SAndroid Build Coastguard Worker size_t max_mmap_pages, size_t aux_buffer_size, 135*288bf522SAndroid Build Coastguard Worker bool allow_truncating_samples = true, bool exclude_perf = false); 136*288bf522SAndroid Build Coastguard Worker ~RecordReadThread(); SetBufferLevels(size_t record_buffer_low_level,size_t record_buffer_critical_level)137*288bf522SAndroid Build Coastguard Worker void SetBufferLevels(size_t record_buffer_low_level, size_t record_buffer_critical_level) { 138*288bf522SAndroid Build Coastguard Worker record_buffer_low_level_ = record_buffer_low_level; 139*288bf522SAndroid Build Coastguard Worker record_buffer_critical_level_ = record_buffer_critical_level; 140*288bf522SAndroid Build Coastguard Worker } 141*288bf522SAndroid Build Coastguard Worker 142*288bf522SAndroid Build Coastguard Worker // Below functions are called in the main thread: 143*288bf522SAndroid Build Coastguard Worker 144*288bf522SAndroid Build Coastguard Worker // When there are records in the RecordBuffer, data_callback will be called in the main thread. 145*288bf522SAndroid Build Coastguard Worker bool RegisterDataCallback(IOEventLoop& loop, const std::function<bool()>& data_callback); 146*288bf522SAndroid Build Coastguard Worker // Create and read kernel buffers for new event fds. 147*288bf522SAndroid Build Coastguard Worker bool AddEventFds(const std::vector<EventFd*>& event_fds); 148*288bf522SAndroid Build Coastguard Worker // Destroy kernel buffers of existing event fds. 149*288bf522SAndroid Build Coastguard Worker bool RemoveEventFds(const std::vector<EventFd*>& event_fds); 150*288bf522SAndroid Build Coastguard Worker // Move all available records in kernel buffers to the RecordBuffer. 151*288bf522SAndroid Build Coastguard Worker bool SyncKernelBuffer(); 152*288bf522SAndroid Build Coastguard Worker // Stop the read thread, no more records will be put into the RecordBuffer. 153*288bf522SAndroid Build Coastguard Worker bool StopReadThread(); 154*288bf522SAndroid Build Coastguard Worker 155*288bf522SAndroid Build Coastguard Worker // If available, return the next record in the RecordBuffer, otherwise return nullptr. 156*288bf522SAndroid Build Coastguard Worker std::unique_ptr<Record> GetRecord(); 157*288bf522SAndroid Build Coastguard Worker GetStat()158*288bf522SAndroid Build Coastguard Worker const RecordStat& GetStat() const { return stat_; } 159*288bf522SAndroid Build Coastguard Worker 160*288bf522SAndroid Build Coastguard Worker private: 161*288bf522SAndroid Build Coastguard Worker enum Cmd { 162*288bf522SAndroid Build Coastguard Worker NO_CMD, 163*288bf522SAndroid Build Coastguard Worker CMD_ADD_EVENT_FDS, 164*288bf522SAndroid Build Coastguard Worker CMD_REMOVE_EVENT_FDS, 165*288bf522SAndroid Build Coastguard Worker CMD_SYNC_KERNEL_BUFFER, 166*288bf522SAndroid Build Coastguard Worker CMD_STOP_THREAD, 167*288bf522SAndroid Build Coastguard Worker }; 168*288bf522SAndroid Build Coastguard Worker 169*288bf522SAndroid Build Coastguard Worker bool SendCmdToReadThread(Cmd cmd, void* cmd_arg); 170*288bf522SAndroid Build Coastguard Worker 171*288bf522SAndroid Build Coastguard Worker // Below functions are called in the read thread: 172*288bf522SAndroid Build Coastguard Worker 173*288bf522SAndroid Build Coastguard Worker void RunReadThread(); 174*288bf522SAndroid Build Coastguard Worker void IncreaseThreadPriority(); 175*288bf522SAndroid Build Coastguard Worker Cmd GetCmd(); 176*288bf522SAndroid Build Coastguard Worker bool HandleCmd(IOEventLoop& loop); 177*288bf522SAndroid Build Coastguard Worker bool HandleAddEventFds(IOEventLoop& loop, const std::vector<EventFd*>& event_fds); 178*288bf522SAndroid Build Coastguard Worker bool HandleRemoveEventFds(const std::vector<EventFd*>& event_fds); 179*288bf522SAndroid Build Coastguard Worker bool ReadRecordsFromKernelBuffer(); 180*288bf522SAndroid Build Coastguard Worker void PushRecordToRecordBuffer(KernelRecordReader* kernel_record_reader); 181*288bf522SAndroid Build Coastguard Worker void ReadAuxDataFromKernelBuffer(bool* has_data); 182*288bf522SAndroid Build Coastguard Worker bool SendDataNotificationToMainThread(); 183*288bf522SAndroid Build Coastguard Worker 184*288bf522SAndroid Build Coastguard Worker RecordBuffer record_buffer_; 185*288bf522SAndroid Build Coastguard Worker // When free size in record buffer is below low level, we cut stack data of sample records to 1K. 186*288bf522SAndroid Build Coastguard Worker size_t record_buffer_low_level_; 187*288bf522SAndroid Build Coastguard Worker // When free size in record buffer is below critical level, we drop sample records to avoid 188*288bf522SAndroid Build Coastguard Worker // losing more important records (like mmap or fork records). 189*288bf522SAndroid Build Coastguard Worker size_t record_buffer_critical_level_; 190*288bf522SAndroid Build Coastguard Worker RecordParser record_parser_; 191*288bf522SAndroid Build Coastguard Worker perf_event_attr attr_; 192*288bf522SAndroid Build Coastguard Worker size_t stack_size_in_sample_record_ = 0; 193*288bf522SAndroid Build Coastguard Worker size_t min_mmap_pages_; 194*288bf522SAndroid Build Coastguard Worker size_t max_mmap_pages_; 195*288bf522SAndroid Build Coastguard Worker size_t aux_buffer_size_; 196*288bf522SAndroid Build Coastguard Worker 197*288bf522SAndroid Build Coastguard Worker // Used to pass command notification from the main thread to the read thread. 198*288bf522SAndroid Build Coastguard Worker android::base::unique_fd write_cmd_fd_; 199*288bf522SAndroid Build Coastguard Worker android::base::unique_fd read_cmd_fd_; 200*288bf522SAndroid Build Coastguard Worker std::mutex cmd_mutex_; 201*288bf522SAndroid Build Coastguard Worker std::condition_variable cmd_finish_cond_; 202*288bf522SAndroid Build Coastguard Worker Cmd cmd_; 203*288bf522SAndroid Build Coastguard Worker void* cmd_arg_; 204*288bf522SAndroid Build Coastguard Worker bool cmd_result_; 205*288bf522SAndroid Build Coastguard Worker 206*288bf522SAndroid Build Coastguard Worker // Used to send data notification from the read thread to the main thread. 207*288bf522SAndroid Build Coastguard Worker android::base::unique_fd write_data_fd_; 208*288bf522SAndroid Build Coastguard Worker android::base::unique_fd read_data_fd_; 209*288bf522SAndroid Build Coastguard Worker std::atomic_bool has_data_notification_; 210*288bf522SAndroid Build Coastguard Worker 211*288bf522SAndroid Build Coastguard Worker std::unique_ptr<std::thread> read_thread_; 212*288bf522SAndroid Build Coastguard Worker std::vector<KernelRecordReader> kernel_record_readers_; 213*288bf522SAndroid Build Coastguard Worker pid_t exclude_pid_ = -1; 214*288bf522SAndroid Build Coastguard Worker bool has_etm_events_ = false; 215*288bf522SAndroid Build Coastguard Worker 216*288bf522SAndroid Build Coastguard Worker std::unordered_set<EventFd*> event_fds_disabled_by_kernel_; 217*288bf522SAndroid Build Coastguard Worker 218*288bf522SAndroid Build Coastguard Worker RecordStat stat_; 219*288bf522SAndroid Build Coastguard Worker }; 220*288bf522SAndroid Build Coastguard Worker 221*288bf522SAndroid Build Coastguard Worker } // namespace simpleperf 222