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 "InplaceSamplerClient.h" 32 #include "IOEventLoop.h" 33 #include "perf_event.h" 34 #include "record.h" 35 36 namespace simpleperf { 37 class RecordReadThread; 38 } 39 40 constexpr double DEFAULT_PERIOD_TO_DETECT_CPU_HOTPLUG_EVENTS_IN_SEC = 0.5; 41 constexpr double DEFAULT_PERIOD_TO_CHECK_MONITORED_TARGETS_IN_SEC = 1; 42 constexpr uint64_t DEFAULT_SAMPLE_FREQ_FOR_NONTRACEPOINT_EVENT = 4000; 43 constexpr uint64_t DEFAULT_SAMPLE_PERIOD_FOR_TRACEPOINT_EVENT = 1; 44 45 struct CounterInfo { 46 pid_t tid; 47 int cpu; 48 PerfCounter counter; 49 }; 50 51 struct CountersInfo { 52 uint32_t group_id; 53 std::string event_name; 54 std::string event_modifier; 55 std::vector<CounterInfo> counters; 56 }; 57 58 struct SampleSpeed { 59 // There are two ways to set sample speed: 60 // 1. sample_freq: take [sample_freq] samples every second. 61 // 2. sample_period: take one sample every [sample_period] events happen. 62 uint64_t sample_freq; 63 uint64_t sample_period; sample_freqSampleSpeed64 SampleSpeed(uint64_t freq = 0, uint64_t period = 0) : sample_freq(freq), sample_period(period) {} UseFreqSampleSpeed65 bool UseFreq() const { 66 // Only use one way to set sample speed. 67 CHECK_NE(sample_freq != 0u, sample_period != 0u); 68 return sample_freq != 0u; 69 } 70 }; 71 72 // EventSelectionSet helps to monitor events. It is used in following steps: 73 // 1. Create an EventSelectionSet, and add event types to monitor by calling 74 // AddEventType() or AddEventGroup(). 75 // 2. Define how to monitor events by calling SetEnableOnExec(), SampleIdAll(), 76 // SetSampleFreq(), etc. 77 // 3. Start monitoring by calling OpenEventFilesForCpus() or 78 // OpenEventFilesForThreadsOnCpus(). If SetEnableOnExec() has been called 79 // in step 2, monitor will be delayed until the monitored thread calls 80 // exec(). 81 // 4. Read counters by calling ReadCounters(), or read mapped event records 82 // by calling MmapEventFiles(), PrepareToReadMmapEventData() and 83 // FinishReadMmapEventData(). 84 // 5. Stop monitoring automatically in the destructor of EventSelectionSet by 85 // closing perf event files. 86 87 class EventSelectionSet { 88 public: 89 EventSelectionSet(bool for_stat_cmd); 90 ~EventSelectionSet(); 91 empty()92 bool empty() const { return groups_.empty(); } 93 94 bool AddEventType(const std::string& event_name, size_t* group_id = nullptr); 95 bool AddEventGroup(const std::vector<std::string>& event_names, size_t* group_id = nullptr); 96 std::vector<const EventType*> GetEvents() const; 97 std::vector<const EventType*> GetTracepointEvents() const; 98 bool ExcludeKernel() const; 99 bool HasInplaceSampler() const; 100 std::vector<EventAttrWithId> GetEventAttrWithId() const; 101 102 void SetEnableOnExec(bool enable); 103 bool GetEnableOnExec(); 104 void SampleIdAll(); 105 void SetSampleSpeed(size_t group_id, const SampleSpeed& speed); 106 bool SetBranchSampling(uint64_t branch_sample_type); 107 void EnableFpCallChainSampling(); 108 bool EnableDwarfCallChainSampling(uint32_t dump_stack_size); 109 void SetInherit(bool enable); 110 void SetClockId(int clock_id); 111 bool NeedKernelSymbol() const; 112 void SetRecordNotExecutableMaps(bool record); 113 bool RecordNotExecutableMaps() const; 114 AddMonitoredProcesses(const std::set<pid_t> & processes)115 void AddMonitoredProcesses(const std::set<pid_t>& processes) { 116 processes_.insert(processes.begin(), processes.end()); 117 } 118 AddMonitoredThreads(const std::set<pid_t> & threads)119 void AddMonitoredThreads(const std::set<pid_t>& threads) { 120 threads_.insert(threads.begin(), threads.end()); 121 } 122 GetMonitoredProcesses()123 const std::set<pid_t>& GetMonitoredProcesses() const { return processes_; } 124 GetMonitoredThreads()125 const std::set<pid_t>& GetMonitoredThreads() const { return threads_; } 126 HasMonitoredTarget()127 bool HasMonitoredTarget() const { 128 return !processes_.empty() || !threads_.empty(); 129 } 130 GetIOEventLoop()131 IOEventLoop* GetIOEventLoop() { 132 return loop_.get(); 133 } 134 135 bool OpenEventFiles(const std::vector<int>& on_cpus); 136 bool ReadCounters(std::vector<CountersInfo>* counters); 137 bool MmapEventFiles(size_t min_mmap_pages, size_t max_mmap_pages, size_t record_buffer_size); 138 bool PrepareToReadMmapEventData(const std::function<bool(Record*)>& callback); 139 bool SyncKernelBuffer(); 140 bool FinishReadMmapEventData(); 141 void GetLostRecords(size_t* lost_samples, size_t* lost_non_samples, size_t* cut_stack_samples); 142 143 // If monitored_cpus is empty, monitor all cpus. 144 bool HandleCpuHotplugEvents(const std::vector<int>& monitored_cpus, 145 double check_interval_in_sec = 146 DEFAULT_PERIOD_TO_DETECT_CPU_HOTPLUG_EVENTS_IN_SEC); 147 148 // Stop profiling if all monitored processes/threads don't exist. 149 bool StopWhenNoMoreTargets(double check_interval_in_sec = 150 DEFAULT_PERIOD_TO_CHECK_MONITORED_TARGETS_IN_SEC); 151 152 bool SetEnableEvents(bool enable); 153 154 private: 155 struct EventSelection { 156 EventTypeAndModifier event_type_modifier; 157 perf_event_attr event_attr; 158 std::vector<std::unique_ptr<EventFd>> event_fds; 159 std::vector<std::unique_ptr<InplaceSamplerClient>> inplace_samplers; 160 // counters for event files closed for cpu hotplug events 161 std::vector<CounterInfo> hotplugged_counters; 162 }; 163 typedef std::vector<EventSelection> EventSelectionGroup; 164 165 bool BuildAndCheckEventSelection(const std::string& event_name, bool first_event, 166 EventSelection* selection); 167 void UnionSampleType(); 168 bool IsUserSpaceSamplerGroup(EventSelectionGroup& group); 169 bool OpenUserSpaceSamplersOnGroup(EventSelectionGroup& group, 170 const std::map<pid_t, std::set<pid_t>>& process_map); 171 bool OpenEventFilesOnGroup(EventSelectionGroup& group, pid_t tid, int cpu, 172 std::string* failed_event_type); 173 bool ReadMmapEventData(bool with_time_limit); 174 175 bool DetectCpuHotplugEvents(); 176 bool HandleCpuOnlineEvent(int cpu); 177 bool HandleCpuOfflineEvent(int cpu); 178 bool CreateMappedBufferForCpu(int cpu); 179 bool CheckMonitoredTargets(); 180 bool HasSampler(); 181 182 const bool for_stat_cmd_; 183 184 std::vector<EventSelectionGroup> groups_; 185 std::set<pid_t> processes_; 186 std::set<pid_t> threads_; 187 188 std::unique_ptr<IOEventLoop> loop_; 189 std::function<bool(Record*)> record_callback_; 190 191 std::set<int> monitored_cpus_; 192 std::vector<int> online_cpus_; 193 194 std::unique_ptr<simpleperf::RecordReadThread> record_read_thread_; 195 196 DISALLOW_COPY_AND_ASSIGN(EventSelectionSet); 197 }; 198 199 bool IsBranchSamplingSupported(); 200 bool IsDwarfCallChainSamplingSupported(); 201 bool IsDumpingRegsForTracepointEventsSupported(); 202 bool IsSettingClockIdSupported(); 203 bool IsMmap2Supported(); 204 205 #endif // SIMPLE_PERF_EVENT_SELECTION_SET_H_ 206