OSDN Git Service

Timetest: Clean up
[android-x86/system-extras.git] / simpleperf / record_lib_interface.cpp
1 /*
2  * Copyright (C) 2017 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 #define SIMPLEPERF_EXPORT __attribute__((visibility("default")))
18 #include "include/simpleperf.h"
19
20 #include <memory>
21 #include <set>
22 #include <string>
23 #include <vector>
24
25 #include <android-base/logging.h>
26
27 #include "environment.h"
28 #include "event_attr.h"
29 #include "event_fd.h"
30 #include "event_selection_set.h"
31 #include "event_type.h"
32
33 namespace simpleperf {
34
35 std::vector<std::string> GetAllEvents() {
36   std::vector<std::string> result;
37   if (!CheckPerfEventLimit()) {
38     return result;
39   }
40   for (auto& type : GetAllEventTypes()) {
41     perf_event_attr attr = CreateDefaultPerfEventAttr(type);
42     if (IsEventAttrSupported(attr)) {
43       result.push_back(type.name);
44     }
45   }
46   return result;
47 }
48
49 bool IsEventSupported(const std::string& name) {
50   if (!CheckPerfEventLimit()) {
51     return false;
52   }
53   std::unique_ptr<EventTypeAndModifier> type = ParseEventType(name);
54   if (type == nullptr) {
55     return false;
56   }
57   perf_event_attr attr = CreateDefaultPerfEventAttr(type->event_type);
58   return IsEventAttrSupported(attr);
59 }
60
61 class PerfEventSetImpl : public PerfEventSet {
62  public:
63   virtual ~PerfEventSetImpl() {}
64
65   bool AddEvent(const std::string& name) override {
66     if (!IsEventSupported(name)) {
67       return false;
68     }
69     event_names_.push_back(name);
70     return true;
71   }
72
73   bool MonitorCurrentProcess() override {
74     whole_process_ = true;
75     return true;
76   }
77
78   bool MonitorCurrentThread() override {
79     whole_process_ = false;
80     threads_.insert(gettid());
81     return true;
82   }
83
84   bool MonitorThreadsInCurrentProcess(const std::vector<pid_t>& threads) override {
85     whole_process_ = false;
86     std::vector<pid_t> tids = GetThreadsInProcess(getpid());
87     for (auto& tid : threads) {
88       if (std::find(tids.begin(), tids.end(), tid) == tids.end()) {
89         LOG(ERROR) << "Thread " << tid << " doesn't exist in current process.";
90         return false;
91       }
92     }
93     threads_.insert(threads.begin(), threads.end());
94     return true;
95   }
96
97  protected:
98   PerfEventSetImpl() : whole_process_(false) {}
99
100   std::vector<std::string> event_names_;
101   bool whole_process_;
102   std::set<pid_t> threads_;
103 };
104
105 class PerfEventSetForCounting : public PerfEventSetImpl {
106  public:
107   PerfEventSetForCounting() : in_counting_state_(false) {}
108   virtual ~PerfEventSetForCounting() {}
109
110   bool StartCounters() override;
111   bool StopCounters() override;
112   bool ReadCounters(std::vector<Counter>* counters) override;
113
114  private:
115   bool CreateEventSelectionSet();
116   void InitAccumulatedCounters();
117   bool ReadRawCounters(std::vector<Counter>* counters);
118   // Add counter b to a.
119   void AddCounter(Counter& a, const Counter& b);
120   // Sub counter b from a.
121   void SubCounter(Counter& a, const Counter& b);
122
123   bool in_counting_state_;
124   std::unique_ptr<EventSelectionSet> event_selection_set_;
125   // The counters at the last time calling StartCounting().
126   std::vector<Counter> last_start_counters_;
127   // The accumulated counters of counting periods, excluding
128   // the last one.
129   std::vector<Counter> accumulated_counters_;
130 };
131
132 bool PerfEventSetForCounting::CreateEventSelectionSet() {
133   std::unique_ptr<EventSelectionSet> set(new EventSelectionSet(true));
134   if (event_names_.empty()) {
135     LOG(ERROR) << "No events.";
136     return false;
137   }
138   for (const auto& name : event_names_) {
139     if (!set->AddEventType(name)) {
140       return false;
141     }
142   }
143   if (whole_process_) {
144     set->AddMonitoredProcesses({getpid()});
145   } else {
146     if (threads_.empty()) {
147       LOG(ERROR) << "No monitored threads.";
148       return false;
149     }
150     set->AddMonitoredThreads(threads_);
151   }
152   if (!set->OpenEventFiles({-1})) {
153     return false;
154   }
155   event_selection_set_ = std::move(set);
156   return true;
157 }
158
159 void PerfEventSetForCounting::InitAccumulatedCounters() {
160   for (const auto& name : event_names_) {
161     Counter counter;
162     counter.event = name;
163     counter.value = 0;
164     counter.time_enabled_in_ns = 0;
165     counter.time_running_in_ns = 0;
166     accumulated_counters_.push_back(counter);
167   }
168 }
169
170 bool PerfEventSetForCounting::ReadRawCounters(std::vector<Counter>* counters) {
171   CHECK(event_selection_set_);
172   std::vector<CountersInfo> s;
173   if (!event_selection_set_->ReadCounters(&s)) {
174     return false;
175   }
176   CHECK_EQ(s.size(), event_names_.size());
177   counters->resize(s.size());
178   for (size_t i = 0; i < s.size(); ++i) {
179     CountersInfo& info = s[i];
180     std::string name = info.event_modifier.empty() ? info.event_name :
181         info.event_name + ":" + info.event_modifier;
182     CHECK_EQ(name, event_names_[i]);
183     Counter& sum = (*counters)[i];
184     sum.event = name;
185     sum.value = 0;
186     sum.time_enabled_in_ns = 0;
187     sum.time_running_in_ns = 0;
188     for (CounterInfo& c : info.counters) {
189       sum.value += c.counter.value;
190       sum.time_enabled_in_ns += c.counter.time_enabled;
191       sum.time_running_in_ns += c.counter.time_running;
192     }
193   }
194   return true;
195 }
196
197 void PerfEventSetForCounting::AddCounter(Counter& a, const Counter& b) {
198   a.value += b.value;
199   a.time_enabled_in_ns += b.time_enabled_in_ns;
200   a.time_running_in_ns += b.time_enabled_in_ns;
201 }
202
203 void PerfEventSetForCounting::SubCounter(Counter& a, const Counter& b) {
204   a.value -= b.value;
205   a.time_enabled_in_ns -= b.time_enabled_in_ns;
206   a.time_running_in_ns -= b.time_running_in_ns;
207 }
208
209 bool PerfEventSetForCounting::StartCounters() {
210   if (in_counting_state_) {
211     return true;
212   }
213   if (event_selection_set_ == nullptr) {
214     if (!CreateEventSelectionSet()) {
215       return false;
216     }
217     InitAccumulatedCounters();
218   }
219   if (!ReadRawCounters(&last_start_counters_)) {
220     return false;
221   }
222   in_counting_state_ = true;
223   return true;
224 }
225
226 bool PerfEventSetForCounting::StopCounters() {
227   if (!in_counting_state_) {
228     return true;
229   }
230   std::vector<Counter> cur;
231   if (!ReadRawCounters(&cur)) {
232     return false;
233   }
234   for (size_t i = 0; i < event_names_.size(); ++i) {
235     SubCounter(cur[i], last_start_counters_[i]);
236     AddCounter(accumulated_counters_[i], cur[i]);
237   }
238   in_counting_state_ = false;
239   return true;
240 }
241
242 bool PerfEventSetForCounting::ReadCounters(std::vector<Counter>* counters) {
243   if (!in_counting_state_) {
244     *counters = accumulated_counters_;
245     return true;
246   }
247   if (!ReadRawCounters(counters)) {
248     return false;
249   }
250   for (size_t i = 0; i < event_names_.size(); ++i) {
251     SubCounter((*counters)[i], last_start_counters_[i]);
252     AddCounter((*counters)[i], accumulated_counters_[i]);
253   }
254   return true;
255 }
256
257 PerfEventSet* PerfEventSet::CreateInstance(PerfEventSet::Type type) {
258   if (!CheckPerfEventLimit()) {
259     return nullptr;
260   }
261   if (type == Type::kPerfForCounting) {
262     return new PerfEventSetForCounting;
263   }
264   return nullptr;
265 }
266
267 bool PerfEventSet::AddEvent(const std::string&) {
268   return false;
269 }
270
271 bool PerfEventSet::MonitorCurrentProcess() {
272   return false;
273 }
274
275 bool PerfEventSet::MonitorCurrentThread() {
276   return false;
277 }
278
279 bool PerfEventSet::MonitorThreadsInCurrentProcess(const std::vector<pid_t>&) {
280   return false;
281 }
282
283 bool PerfEventSet::StartCounters() {
284   return false;
285 }
286
287 bool PerfEventSet::StopCounters() {
288   return false;
289 }
290
291 bool PerfEventSet::ReadCounters(std::vector<Counter>*) {
292   return false;
293 }
294
295 }  // namespace simpleperf