1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SIMPLE_PERF_EVENT_SELECTION_SET_H_ 18 #define SIMPLE_PERF_EVENT_SELECTION_SET_H_ 19 20 #include <functional> 21 #include <map> 22 #include <set> 23 #include <unordered_map> 24 #include <vector> 25 26 #include <android-base/macros.h> 27 28 #include "event_attr.h" 29 #include "event_fd.h" 30 #include "event_type.h" 31 #include "IOEventLoop.h" 32 #include "perf_event.h" 33 #include "record.h" 34 #include "RecordReadThread.h" 35 36 constexpr double DEFAULT_PERIOD_TO_CHECK_MONITORED_TARGETS_IN_SEC = 1; 37 constexpr uint64_t DEFAULT_SAMPLE_FREQ_FOR_NONTRACEPOINT_EVENT = 4000; 38 constexpr uint64_t DEFAULT_SAMPLE_PERIOD_FOR_TRACEPOINT_EVENT = 1; 39 40 struct CounterInfo { 41 pid_t tid; 42 int cpu; 43 PerfCounter counter; 44 }; 45 46 struct CountersInfo { 47 uint32_t group_id; 48 std::string event_name; 49 std::string event_modifier; 50 std::vector<CounterInfo> counters; 51 }; 52 53 struct SampleSpeed { 54 // There are two ways to set sample speed: 55 // 1. sample_freq: take [sample_freq] samples every second. 56 // 2. sample_period: take one sample every [sample_period] events happen. 57 uint64_t sample_freq; 58 uint64_t sample_period; sample_freqSampleSpeed59 SampleSpeed(uint64_t freq = 0, uint64_t period = 0) : sample_freq(freq), sample_period(period) {} UseFreqSampleSpeed60 bool UseFreq() const { 61 // Only use one way to set sample speed. 62 CHECK_NE(sample_freq != 0u, sample_period != 0u); 63 return sample_freq != 0u; 64 } 65 }; 66 67 struct AddrFilter { 68 enum Type { 69 FILE_RANGE, 70 FILE_START, 71 FILE_STOP, 72 KERNEL_RANGE, 73 KERNEL_START, 74 KERNEL_STOP, 75 } type; 76 uint64_t addr; 77 uint64_t size; 78 std::string file_path; 79 AddrFilterAddrFilter80 AddrFilter(AddrFilter::Type type, uint64_t addr, uint64_t size, const std::string& file_path) 81 : type(type), addr(addr), size(size), file_path(file_path) {} 82 83 std::string ToString() const; 84 }; 85 86 // EventSelectionSet helps to monitor events. It is used in following steps: 87 // 1. Create an EventSelectionSet, and add event types to monitor by calling 88 // AddEventType() or AddEventGroup(). 89 // 2. Define how to monitor events by calling SetEnableOnExec(), SampleIdAll(), 90 // SetSampleFreq(), etc. 91 // 3. Start monitoring by calling OpenEventFilesForCpus() or 92 // OpenEventFilesForThreadsOnCpus(). If SetEnableOnExec() has been called 93 // in step 2, monitor will be delayed until the monitored thread calls 94 // exec(). 95 // 4. Read counters by calling ReadCounters(), or read mapped event records 96 // by calling MmapEventFiles(), PrepareToReadMmapEventData() and 97 // FinishReadMmapEventData(). 98 // 5. Stop monitoring automatically in the destructor of EventSelectionSet by 99 // closing perf event files. 100 101 class EventSelectionSet { 102 public: 103 EventSelectionSet(bool for_stat_cmd); 104 ~EventSelectionSet(); 105 empty()106 bool empty() const { return groups_.empty(); } 107 108 bool AddEventType(const std::string& event_name, size_t* group_id = nullptr); 109 bool AddEventGroup(const std::vector<std::string>& event_names, size_t* group_id = nullptr); 110 std::vector<const EventType*> GetEvents() const; 111 std::vector<const EventType*> GetTracepointEvents() const; 112 bool ExcludeKernel() const; HasAuxTrace()113 bool HasAuxTrace() const { return has_aux_trace_; } 114 std::vector<EventAttrWithId> GetEventAttrWithId() const; 115 116 void SetEnableOnExec(bool enable); 117 bool GetEnableOnExec(); 118 void SampleIdAll(); 119 void SetSampleSpeed(size_t group_id, const SampleSpeed& speed); 120 bool SetBranchSampling(uint64_t branch_sample_type); 121 void EnableFpCallChainSampling(); 122 bool EnableDwarfCallChainSampling(uint32_t dump_stack_size); 123 void SetInherit(bool enable); 124 void SetClockId(int clock_id); 125 bool NeedKernelSymbol() const; 126 void SetRecordNotExecutableMaps(bool record); 127 bool RecordNotExecutableMaps() const; SetAddrFilters(std::vector<AddrFilter> && filters)128 void SetAddrFilters(std::vector<AddrFilter>&& filters) { 129 addr_filters_ = std::move(filters); 130 } 131 bool SetTracepointFilter(const std::string& filter); 132 133 template <typename Collection = std::vector<pid_t>> AddMonitoredProcesses(const Collection & processes)134 void AddMonitoredProcesses(const Collection& processes) { 135 processes_.insert(processes.begin(), processes.end()); 136 } 137 138 template <typename Collection = std::vector<pid_t>> AddMonitoredThreads(const Collection & threads)139 void AddMonitoredThreads(const Collection& threads) { 140 threads_.insert(threads.begin(), threads.end()); 141 } 142 GetMonitoredProcesses()143 const std::set<pid_t>& GetMonitoredProcesses() const { return processes_; } 144 GetMonitoredThreads()145 const std::set<pid_t>& GetMonitoredThreads() const { return threads_; } 146 ClearMonitoredTargets()147 void ClearMonitoredTargets() { 148 processes_.clear(); 149 threads_.clear(); 150 } 151 HasMonitoredTarget()152 bool HasMonitoredTarget() const { 153 return !processes_.empty() || !threads_.empty(); 154 } 155 GetIOEventLoop()156 IOEventLoop* GetIOEventLoop() { 157 return loop_.get(); 158 } 159 160 // If cpus = {}, monitor on all cpus, with a perf event file for each cpu. 161 // If cpus = {-1}, monitor on all cpus, with a perf event file shared by all cpus. 162 // Otherwise, monitor on selected cpus, with a perf event file for each cpu. 163 bool OpenEventFiles(const std::vector<int>& cpus); 164 bool ReadCounters(std::vector<CountersInfo>* counters); 165 bool MmapEventFiles(size_t min_mmap_pages, size_t max_mmap_pages, size_t aux_buffer_size, 166 size_t record_buffer_size, bool allow_cutting_samples, bool exclude_perf); 167 bool PrepareToReadMmapEventData(const std::function<bool(Record*)>& callback); 168 bool SyncKernelBuffer(); 169 bool FinishReadMmapEventData(); 170 GetRecordStat()171 const simpleperf::RecordStat& GetRecordStat() { 172 return record_read_thread_->GetStat(); 173 } 174 175 // Stop profiling if all monitored processes/threads don't exist. 176 bool StopWhenNoMoreTargets(double check_interval_in_sec = 177 DEFAULT_PERIOD_TO_CHECK_MONITORED_TARGETS_IN_SEC); 178 179 bool SetEnableEvents(bool enable); 180 181 private: 182 struct EventSelection { 183 EventTypeAndModifier event_type_modifier; 184 perf_event_attr event_attr; 185 std::vector<std::unique_ptr<EventFd>> event_fds; 186 // counters for event files closed for cpu hotplug events 187 std::vector<CounterInfo> hotplugged_counters; 188 std::vector<int> allowed_cpus; 189 std::string tracepoint_filter; 190 }; 191 typedef std::vector<EventSelection> EventSelectionGroup; 192 193 bool BuildAndCheckEventSelection(const std::string& event_name, bool first_event, 194 EventSelection* selection); 195 void UnionSampleType(); 196 bool OpenEventFilesOnGroup(EventSelectionGroup& group, pid_t tid, int cpu, 197 std::string* failed_event_type); 198 bool ApplyFilters(); 199 bool ApplyAddrFilters(); 200 bool ApplyTracepointFilters(); 201 bool ReadMmapEventData(bool with_time_limit); 202 203 bool CheckMonitoredTargets(); 204 bool HasSampler(); 205 206 const bool for_stat_cmd_; 207 208 std::vector<EventSelectionGroup> groups_; 209 std::set<pid_t> processes_; 210 std::set<pid_t> threads_; 211 212 std::unique_ptr<IOEventLoop> loop_; 213 std::function<bool(Record*)> record_callback_; 214 215 std::unique_ptr<simpleperf::RecordReadThread> record_read_thread_; 216 217 bool has_aux_trace_ = false; 218 std::vector<AddrFilter> addr_filters_; 219 220 DISALLOW_COPY_AND_ASSIGN(EventSelectionSet); 221 }; 222 223 bool IsBranchSamplingSupported(); 224 bool IsDwarfCallChainSamplingSupported(); 225 bool IsDumpingRegsForTracepointEventsSupported(); 226 bool IsSettingClockIdSupported(); 227 bool IsMmap2Supported(); 228 229 #endif // SIMPLE_PERF_EVENT_SELECTION_SET_H_ 230