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 "IOEventLoop.h" 29 #include "RecordReadThread.h" 30 #include "event_attr.h" 31 #include "event_fd.h" 32 #include "event_type.h" 33 #include "perf_event.h" 34 #include "record.h" 35 36 namespace simpleperf { 37 38 constexpr double DEFAULT_PERIOD_TO_CHECK_MONITORED_TARGETS_IN_SEC = 1; 39 constexpr uint64_t DEFAULT_SAMPLE_FREQ_FOR_NONTRACEPOINT_EVENT = 4000; 40 constexpr uint64_t DEFAULT_SAMPLE_PERIOD_FOR_TRACEPOINT_EVENT = 1; 41 42 struct CounterInfo { 43 pid_t tid; 44 int cpu; 45 PerfCounter counter; 46 }; 47 48 struct CountersInfo { 49 uint32_t group_id; 50 std::string event_name; 51 std::string event_modifier; 52 std::vector<CounterInfo> counters; 53 }; 54 55 struct SampleRate { 56 // There are two ways to set sample rate: 57 // 1. sample_freq: take [sample_freq] samples every second. 58 // 2. sample_period: take one sample every [sample_period] events happen. 59 uint64_t sample_freq; 60 uint64_t sample_period; sample_freqSampleRate61 SampleRate(uint64_t freq = 0, uint64_t period = 0) : sample_freq(freq), sample_period(period) {} UseFreqSampleRate62 bool UseFreq() const { 63 // Only use one way to set sample rate. 64 CHECK_NE(sample_freq != 0u, sample_period != 0u); 65 return sample_freq != 0u; 66 } 67 }; 68 69 struct AddrFilter { 70 enum Type { 71 FILE_RANGE, 72 FILE_START, 73 FILE_STOP, 74 KERNEL_RANGE, 75 KERNEL_START, 76 KERNEL_STOP, 77 } type; 78 uint64_t addr; 79 uint64_t size; 80 std::string file_path; 81 AddrFilterAddrFilter82 AddrFilter(AddrFilter::Type type, uint64_t addr, uint64_t size, const std::string& file_path) 83 : type(type), addr(addr), size(size), file_path(file_path) {} 84 85 std::string ToString() const; 86 }; 87 88 // EventSelectionSet helps to monitor events. It is used in following steps: 89 // 1. Create an EventSelectionSet, and add event types to monitor by calling 90 // AddEventType() or AddEventGroup(). 91 // 2. Define how to monitor events by calling SetEnableOnExec(), SampleIdAll(), 92 // SetSampleFreq(), etc. 93 // 3. Start monitoring by calling OpenEventFilesForCpus() or 94 // OpenEventFilesForThreadsOnCpus(). If SetEnableOnExec() has been called 95 // in step 2, monitor will be delayed until the monitored thread calls 96 // exec(). 97 // 4. Read counters by calling ReadCounters(), or read mapped event records 98 // by calling MmapEventFiles(), PrepareToReadMmapEventData() and 99 // FinishReadMmapEventData(). 100 // 5. Stop monitoring automatically in the destructor of EventSelectionSet by 101 // closing perf event files. 102 103 class EventSelectionSet { 104 public: 105 EventSelectionSet(bool for_stat_cmd); 106 ~EventSelectionSet(); 107 empty()108 bool empty() const { return groups_.empty(); } 109 110 bool AddEventType(const std::string& event_name); 111 bool AddEventType(const std::string& event_name, const SampleRate& sample_rate); 112 bool AddEventGroup(const std::vector<std::string>& event_names); 113 // For each sample generated for the existing event group, add counters for selected events. 114 bool AddCounters(const std::vector<std::string>& event_names); 115 std::vector<const EventType*> GetEvents() const; 116 std::vector<const EventType*> GetTracepointEvents() const; 117 bool ExcludeKernel() const; HasAuxTrace()118 bool HasAuxTrace() const { return has_aux_trace_; } 119 EventAttrIds GetEventAttrWithId() const; 120 std::unordered_map<uint64_t, std::string> GetEventNamesById() const; 121 std::unordered_map<uint64_t, int> GetCpusById() const; 122 std::map<int, size_t> GetHardwareCountersForCpus() const; 123 124 void SetEnableCondition(bool enable_on_open, bool enable_on_exec); 125 bool IsEnabledOnExec() const; 126 void SampleIdAll(); 127 // Only set sample rate for events that haven't set sample rate. 128 void SetSampleRateForNewEvents(const SampleRate& rate); 129 // Set on which cpus to monitor events. Only set cpus for events that haven't set before. 130 void SetCpusForNewEvents(const std::vector<int>& cpus); 131 bool SetBranchSampling(uint64_t branch_sample_type); 132 void EnableFpCallChainSampling(); 133 bool EnableDwarfCallChainSampling(uint32_t dump_stack_size); 134 void SetInherit(bool enable); 135 void SetClockId(int clock_id); 136 bool NeedKernelSymbol() const; 137 void SetRecordNotExecutableMaps(bool record); 138 bool RecordNotExecutableMaps() const; 139 void EnableSwitchRecord(); 140 void WakeupPerSample(); SetAddrFilters(std::vector<AddrFilter> && filters)141 void SetAddrFilters(std::vector<AddrFilter>&& filters) { addr_filters_ = std::move(filters); } 142 bool SetTracepointFilter(const std::string& filter); 143 144 template <typename Collection = std::vector<pid_t>> AddMonitoredProcesses(const Collection & processes)145 void AddMonitoredProcesses(const Collection& processes) { 146 processes_.insert(processes.begin(), processes.end()); 147 } 148 149 template <typename Collection = std::vector<pid_t>> AddMonitoredThreads(const Collection & threads)150 void AddMonitoredThreads(const Collection& threads) { 151 threads_.insert(threads.begin(), threads.end()); 152 } 153 GetMonitoredProcesses()154 const std::set<pid_t>& GetMonitoredProcesses() const { return processes_; } 155 GetMonitoredThreads()156 const std::set<pid_t>& GetMonitoredThreads() const { return threads_; } 157 ClearMonitoredTargets()158 void ClearMonitoredTargets() { 159 processes_.clear(); 160 threads_.clear(); 161 } 162 HasMonitoredTarget()163 bool HasMonitoredTarget() const { return !processes_.empty() || !threads_.empty(); } 164 GetIOEventLoop()165 IOEventLoop* GetIOEventLoop() { return loop_.get(); } 166 167 bool OpenEventFiles(); 168 bool ReadCounters(std::vector<CountersInfo>* counters); 169 bool MmapEventFiles(size_t min_mmap_pages, size_t max_mmap_pages, size_t aux_buffer_size, 170 size_t record_buffer_size, bool allow_truncating_samples, bool exclude_perf); 171 bool PrepareToReadMmapEventData(const std::function<bool(Record*)>& callback); 172 bool SyncKernelBuffer(); 173 bool FinishReadMmapEventData(); 174 void CloseEventFiles(); 175 GetRecordStat()176 const simpleperf::RecordStat& GetRecordStat() { return record_read_thread_->GetStat(); } 177 178 // Stop profiling if all monitored processes/threads don't exist. 179 bool StopWhenNoMoreTargets( 180 double check_interval_in_sec = DEFAULT_PERIOD_TO_CHECK_MONITORED_TARGETS_IN_SEC); 181 182 bool SetEnableEvents(bool enable); 183 bool EnableETMEvents(); 184 bool DisableETMEvents(); 185 186 private: 187 struct EventSelection { 188 EventTypeAndModifier event_type_modifier; 189 perf_event_attr event_attr; 190 std::vector<std::unique_ptr<EventFd>> event_fds; 191 // counters for event files closed for cpu hotplug events 192 std::vector<CounterInfo> hotplugged_counters; 193 std::vector<int> allowed_cpus; 194 std::string tracepoint_filter; 195 }; 196 197 struct EventSelectionGroup { 198 std::vector<EventSelection> selections; 199 bool set_sample_rate = false; 200 // Select on which cpus to monitor this event group: 201 // If cpus = {}, monitor on all cpus, with a perf event file for each cpu. This is the default 202 // option. 203 // If cpus = {-1}, monitor on all cpus, with a perf event file shared by all cpus. 204 // Otherwise, monitor on selected cpus, with a perf event file for each cpu. 205 std::vector<int> cpus; 206 }; 207 208 bool BuildAndCheckEventSelection(const std::string& event_name, bool first_event, 209 EventSelection* selection); 210 void UnionSampleType(); 211 void SetSampleRateForGroup(EventSelectionGroup& group, const SampleRate& rate); 212 bool OpenEventFilesOnGroup(EventSelectionGroup& group, pid_t tid, int cpu, 213 std::string* failed_event_type); 214 bool ApplyFilters(); 215 bool ApplyAddrFilters(); 216 bool ApplyTracepointFilters(); 217 bool ReadMmapEventData(bool with_time_limit); 218 219 bool CheckMonitoredTargets(); 220 bool HasSampler(); 221 222 const bool for_stat_cmd_; 223 224 std::vector<EventSelectionGroup> groups_; 225 std::set<pid_t> processes_; 226 std::set<pid_t> threads_; 227 228 std::unique_ptr<IOEventLoop> loop_; 229 std::function<bool(Record*)> record_callback_; 230 231 std::unique_ptr<simpleperf::RecordReadThread> record_read_thread_; 232 233 bool has_aux_trace_ = false; 234 std::vector<AddrFilter> addr_filters_; 235 std::optional<SampleRate> sample_rate_; 236 std::optional<std::vector<int>> cpus_; 237 238 std::set<int> etm_event_cpus_; 239 std::set<int>::const_iterator etm_event_cpus_it_; 240 241 DISALLOW_COPY_AND_ASSIGN(EventSelectionSet); 242 }; 243 244 bool IsBranchSamplingSupported(); 245 bool IsDwarfCallChainSamplingSupported(); 246 bool IsDumpingRegsForTracepointEventsSupported(); 247 bool IsSettingClockIdSupported(); 248 bool IsMmap2Supported(); 249 bool IsHardwareEventSupported(); 250 bool IsSwitchRecordSupported(); 251 252 } // namespace simpleperf 253 254 #endif // SIMPLE_PERF_EVENT_SELECTION_SET_H_ 255