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