record_lib_interface.cpp 7.6 KB

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