event_selection_set.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907
  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. #include "event_selection_set.h"
  17. #include <algorithm>
  18. #include <atomic>
  19. #include <thread>
  20. #include <android-base/logging.h>
  21. #include "environment.h"
  22. #include "event_attr.h"
  23. #include "event_type.h"
  24. #include "IOEventLoop.h"
  25. #include "perf_regs.h"
  26. #include "utils.h"
  27. #include "RecordReadThread.h"
  28. bool IsBranchSamplingSupported() {
  29. const EventType* type = FindEventTypeByName("cpu-cycles");
  30. if (type == nullptr) {
  31. return false;
  32. }
  33. perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
  34. attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
  35. attr.branch_sample_type = PERF_SAMPLE_BRANCH_ANY;
  36. return IsEventAttrSupported(attr);
  37. }
  38. bool IsDwarfCallChainSamplingSupported() {
  39. const EventType* type = FindEventTypeByName("cpu-cycles");
  40. if (type == nullptr) {
  41. return false;
  42. }
  43. perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
  44. attr.sample_type |=
  45. PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER;
  46. attr.exclude_callchain_user = 1;
  47. attr.sample_regs_user = GetSupportedRegMask(GetBuildArch());
  48. attr.sample_stack_user = 8192;
  49. return IsEventAttrSupported(attr);
  50. }
  51. bool IsDumpingRegsForTracepointEventsSupported() {
  52. const EventType* event_type = FindEventTypeByName("sched:sched_switch", false);
  53. if (event_type == nullptr) {
  54. return false;
  55. }
  56. std::atomic<bool> done(false);
  57. std::atomic<pid_t> thread_id(0);
  58. std::thread thread([&]() {
  59. thread_id = gettid();
  60. while (!done) {
  61. usleep(1);
  62. }
  63. usleep(1); // Make a sched out to generate one sample.
  64. });
  65. while (thread_id == 0) {
  66. usleep(1);
  67. }
  68. perf_event_attr attr = CreateDefaultPerfEventAttr(*event_type);
  69. attr.freq = 0;
  70. attr.sample_period = 1;
  71. std::unique_ptr<EventFd> event_fd =
  72. EventFd::OpenEventFile(attr, thread_id, -1, nullptr);
  73. if (event_fd == nullptr) {
  74. return false;
  75. }
  76. if (!event_fd->CreateMappedBuffer(4, true)) {
  77. return false;
  78. }
  79. done = true;
  80. thread.join();
  81. std::vector<char> buffer = event_fd->GetAvailableMmapData();
  82. std::vector<std::unique_ptr<Record>> records =
  83. ReadRecordsFromBuffer(attr, buffer.data(), buffer.size());
  84. for (auto& r : records) {
  85. if (r->type() == PERF_RECORD_SAMPLE) {
  86. auto& record = *static_cast<SampleRecord*>(r.get());
  87. if (record.ip_data.ip != 0) {
  88. return true;
  89. }
  90. }
  91. }
  92. return false;
  93. }
  94. bool IsSettingClockIdSupported() {
  95. // Do the real check only once and keep the result in a static variable.
  96. static int is_supported = -1;
  97. if (is_supported == -1) {
  98. const EventType* type = FindEventTypeByName("cpu-cycles");
  99. if (type == nullptr) {
  100. is_supported = 0;
  101. } else {
  102. // Check if the kernel supports setting clockid, which was added in kernel 4.0. Just check
  103. // with one clockid is enough. Because all needed clockids were supported before kernel 4.0.
  104. perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
  105. attr.use_clockid = 1;
  106. attr.clockid = CLOCK_MONOTONIC;
  107. is_supported = IsEventAttrSupported(attr) ? 1 : 0;
  108. }
  109. }
  110. return is_supported;
  111. }
  112. bool IsMmap2Supported() {
  113. const EventType* type = FindEventTypeByName("cpu-cycles");
  114. if (type == nullptr) {
  115. return false;
  116. }
  117. perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
  118. attr.mmap2 = 1;
  119. return IsEventAttrSupported(attr);
  120. }
  121. EventSelectionSet::EventSelectionSet(bool for_stat_cmd)
  122. : for_stat_cmd_(for_stat_cmd), loop_(new IOEventLoop) {}
  123. EventSelectionSet::~EventSelectionSet() {}
  124. bool EventSelectionSet::BuildAndCheckEventSelection(const std::string& event_name, bool first_event,
  125. EventSelection* selection) {
  126. std::unique_ptr<EventTypeAndModifier> event_type = ParseEventType(event_name);
  127. if (event_type == nullptr) {
  128. return false;
  129. }
  130. if (for_stat_cmd_) {
  131. if (event_type->event_type.name == "cpu-clock" ||
  132. event_type->event_type.name == "task-clock") {
  133. if (event_type->exclude_user || event_type->exclude_kernel) {
  134. LOG(ERROR) << "Modifier u and modifier k used in event type "
  135. << event_type->event_type.name
  136. << " are not supported by the kernel.";
  137. return false;
  138. }
  139. }
  140. }
  141. selection->event_type_modifier = *event_type;
  142. selection->event_attr = CreateDefaultPerfEventAttr(event_type->event_type);
  143. selection->event_attr.exclude_user = event_type->exclude_user;
  144. selection->event_attr.exclude_kernel = event_type->exclude_kernel;
  145. selection->event_attr.exclude_hv = event_type->exclude_hv;
  146. selection->event_attr.exclude_host = event_type->exclude_host;
  147. selection->event_attr.exclude_guest = event_type->exclude_guest;
  148. selection->event_attr.precise_ip = event_type->precise_ip;
  149. bool set_default_sample_freq = false;
  150. if (!for_stat_cmd_) {
  151. if (event_type->event_type.type == PERF_TYPE_TRACEPOINT) {
  152. selection->event_attr.freq = 0;
  153. selection->event_attr.sample_period = DEFAULT_SAMPLE_PERIOD_FOR_TRACEPOINT_EVENT;
  154. } else {
  155. selection->event_attr.freq = 1;
  156. // Set default sample freq here may print msg "Adjust sample freq to max allowed sample
  157. // freq". But this is misleading. Because default sample freq may not be the final sample
  158. // freq we use. So use minimum sample freq (1) here.
  159. selection->event_attr.sample_freq = 1;
  160. set_default_sample_freq = true;
  161. }
  162. // We only need to dump mmap and comm records for the first event type. Because all event types
  163. // are monitoring the same processes.
  164. if (first_event) {
  165. selection->event_attr.mmap = 1;
  166. selection->event_attr.comm = 1;
  167. if (IsMmap2Supported()) {
  168. selection->event_attr.mmap2 = 1;
  169. }
  170. }
  171. }
  172. if (!IsEventAttrSupported(selection->event_attr)) {
  173. LOG(ERROR) << "Event type '" << event_type->name
  174. << "' is not supported on the device";
  175. return false;
  176. }
  177. if (set_default_sample_freq) {
  178. selection->event_attr.sample_freq = DEFAULT_SAMPLE_FREQ_FOR_NONTRACEPOINT_EVENT;
  179. }
  180. selection->event_fds.clear();
  181. for (const auto& group : groups_) {
  182. for (const auto& sel : group) {
  183. if (sel.event_type_modifier.name == selection->event_type_modifier.name) {
  184. LOG(ERROR) << "Event type '" << sel.event_type_modifier.name
  185. << "' appears more than once";
  186. return false;
  187. }
  188. }
  189. }
  190. return true;
  191. }
  192. bool EventSelectionSet::AddEventType(const std::string& event_name, size_t* group_id) {
  193. return AddEventGroup(std::vector<std::string>(1, event_name), group_id);
  194. }
  195. bool EventSelectionSet::AddEventGroup(
  196. const std::vector<std::string>& event_names, size_t* group_id) {
  197. EventSelectionGroup group;
  198. bool first_event = groups_.empty();
  199. for (const auto& event_name : event_names) {
  200. EventSelection selection;
  201. if (!BuildAndCheckEventSelection(event_name, first_event, &selection)) {
  202. return false;
  203. }
  204. first_event = false;
  205. group.push_back(std::move(selection));
  206. }
  207. groups_.push_back(std::move(group));
  208. UnionSampleType();
  209. if (group_id != nullptr) {
  210. *group_id = groups_.size() - 1;
  211. }
  212. return true;
  213. }
  214. std::vector<const EventType*> EventSelectionSet::GetEvents() const {
  215. std::vector<const EventType*> result;
  216. for (const auto& group : groups_) {
  217. for (const auto& selection : group) {
  218. result.push_back(&selection.event_type_modifier.event_type);
  219. }
  220. }
  221. return result;
  222. }
  223. std::vector<const EventType*> EventSelectionSet::GetTracepointEvents() const {
  224. std::vector<const EventType*> result;
  225. for (const auto& group : groups_) {
  226. for (const auto& selection : group) {
  227. if (selection.event_type_modifier.event_type.type ==
  228. PERF_TYPE_TRACEPOINT) {
  229. result.push_back(&selection.event_type_modifier.event_type);
  230. }
  231. }
  232. }
  233. return result;
  234. }
  235. bool EventSelectionSet::ExcludeKernel() const {
  236. for (const auto& group : groups_) {
  237. for (const auto& selection : group) {
  238. if (!selection.event_type_modifier.exclude_kernel) {
  239. return false;
  240. }
  241. }
  242. }
  243. return true;
  244. }
  245. bool EventSelectionSet::HasInplaceSampler() const {
  246. for (const auto& group : groups_) {
  247. for (const auto& sel : group) {
  248. if (sel.event_attr.type == SIMPLEPERF_TYPE_USER_SPACE_SAMPLERS &&
  249. sel.event_attr.config == SIMPLEPERF_CONFIG_INPLACE_SAMPLER) {
  250. return true;
  251. }
  252. }
  253. }
  254. return false;
  255. }
  256. std::vector<EventAttrWithId> EventSelectionSet::GetEventAttrWithId() const {
  257. std::vector<EventAttrWithId> result;
  258. for (const auto& group : groups_) {
  259. for (const auto& selection : group) {
  260. EventAttrWithId attr_id;
  261. attr_id.attr = &selection.event_attr;
  262. for (const auto& fd : selection.event_fds) {
  263. attr_id.ids.push_back(fd->Id());
  264. }
  265. if (!selection.inplace_samplers.empty()) {
  266. attr_id.ids.push_back(selection.inplace_samplers[0]->Id());
  267. }
  268. result.push_back(attr_id);
  269. }
  270. }
  271. return result;
  272. }
  273. // Union the sample type of different event attrs can make reading sample
  274. // records in perf.data easier.
  275. void EventSelectionSet::UnionSampleType() {
  276. uint64_t sample_type = 0;
  277. for (const auto& group : groups_) {
  278. for (const auto& selection : group) {
  279. sample_type |= selection.event_attr.sample_type;
  280. }
  281. }
  282. for (auto& group : groups_) {
  283. for (auto& selection : group) {
  284. selection.event_attr.sample_type = sample_type;
  285. }
  286. }
  287. }
  288. void EventSelectionSet::SetEnableOnExec(bool enable) {
  289. for (auto& group : groups_) {
  290. for (auto& selection : group) {
  291. // If sampling is enabled on exec, then it is disabled at startup,
  292. // otherwise it should be enabled at startup. Don't use
  293. // ioctl(PERF_EVENT_IOC_ENABLE) to enable it after perf_event_open().
  294. // Because some android kernels can't handle ioctl() well when cpu-hotplug
  295. // happens. See http://b/25193162.
  296. if (enable) {
  297. selection.event_attr.enable_on_exec = 1;
  298. selection.event_attr.disabled = 1;
  299. } else {
  300. selection.event_attr.enable_on_exec = 0;
  301. selection.event_attr.disabled = 0;
  302. }
  303. }
  304. }
  305. }
  306. bool EventSelectionSet::GetEnableOnExec() {
  307. for (const auto& group : groups_) {
  308. for (const auto& selection : group) {
  309. if (selection.event_attr.enable_on_exec == 0) {
  310. return false;
  311. }
  312. }
  313. }
  314. return true;
  315. }
  316. void EventSelectionSet::SampleIdAll() {
  317. for (auto& group : groups_) {
  318. for (auto& selection : group) {
  319. selection.event_attr.sample_id_all = 1;
  320. }
  321. }
  322. }
  323. void EventSelectionSet::SetSampleSpeed(size_t group_id, const SampleSpeed& speed) {
  324. CHECK_LT(group_id, groups_.size());
  325. for (auto& selection : groups_[group_id]) {
  326. if (speed.UseFreq()) {
  327. selection.event_attr.freq = 1;
  328. selection.event_attr.sample_freq = speed.sample_freq;
  329. } else {
  330. selection.event_attr.freq = 0;
  331. selection.event_attr.sample_period = speed.sample_period;
  332. }
  333. }
  334. }
  335. bool EventSelectionSet::SetBranchSampling(uint64_t branch_sample_type) {
  336. if (branch_sample_type != 0 &&
  337. (branch_sample_type &
  338. (PERF_SAMPLE_BRANCH_ANY | PERF_SAMPLE_BRANCH_ANY_CALL |
  339. PERF_SAMPLE_BRANCH_ANY_RETURN | PERF_SAMPLE_BRANCH_IND_CALL)) == 0) {
  340. LOG(ERROR) << "Invalid branch_sample_type: 0x" << std::hex
  341. << branch_sample_type;
  342. return false;
  343. }
  344. if (branch_sample_type != 0 && !IsBranchSamplingSupported()) {
  345. LOG(ERROR) << "branch stack sampling is not supported on this device.";
  346. return false;
  347. }
  348. for (auto& group : groups_) {
  349. for (auto& selection : group) {
  350. perf_event_attr& attr = selection.event_attr;
  351. if (branch_sample_type != 0) {
  352. attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
  353. } else {
  354. attr.sample_type &= ~PERF_SAMPLE_BRANCH_STACK;
  355. }
  356. attr.branch_sample_type = branch_sample_type;
  357. }
  358. }
  359. return true;
  360. }
  361. void EventSelectionSet::EnableFpCallChainSampling() {
  362. for (auto& group : groups_) {
  363. for (auto& selection : group) {
  364. selection.event_attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
  365. }
  366. }
  367. }
  368. bool EventSelectionSet::EnableDwarfCallChainSampling(uint32_t dump_stack_size) {
  369. if (!IsDwarfCallChainSamplingSupported()) {
  370. LOG(ERROR) << "dwarf callchain sampling is not supported on this device.";
  371. return false;
  372. }
  373. for (auto& group : groups_) {
  374. for (auto& selection : group) {
  375. selection.event_attr.sample_type |= PERF_SAMPLE_CALLCHAIN |
  376. PERF_SAMPLE_REGS_USER |
  377. PERF_SAMPLE_STACK_USER;
  378. selection.event_attr.exclude_callchain_user = 1;
  379. selection.event_attr.sample_regs_user =
  380. GetSupportedRegMask(GetMachineArch());
  381. selection.event_attr.sample_stack_user = dump_stack_size;
  382. }
  383. }
  384. return true;
  385. }
  386. void EventSelectionSet::SetInherit(bool enable) {
  387. for (auto& group : groups_) {
  388. for (auto& selection : group) {
  389. selection.event_attr.inherit = (enable ? 1 : 0);
  390. }
  391. }
  392. }
  393. void EventSelectionSet::SetClockId(int clock_id) {
  394. for (auto& group : groups_) {
  395. for (auto& selection : group) {
  396. selection.event_attr.use_clockid = 1;
  397. selection.event_attr.clockid = clock_id;
  398. }
  399. }
  400. }
  401. bool EventSelectionSet::NeedKernelSymbol() const {
  402. for (const auto& group : groups_) {
  403. for (const auto& selection : group) {
  404. if (!selection.event_type_modifier.exclude_kernel) {
  405. return true;
  406. }
  407. }
  408. }
  409. return false;
  410. }
  411. void EventSelectionSet::SetRecordNotExecutableMaps(bool record) {
  412. // We only need to dump non-executable mmap records for the first event type.
  413. groups_[0][0].event_attr.mmap_data = record ? 1 : 0;
  414. }
  415. bool EventSelectionSet::RecordNotExecutableMaps() const {
  416. return groups_[0][0].event_attr.mmap_data == 1;
  417. }
  418. static bool CheckIfCpusOnline(const std::vector<int>& cpus) {
  419. std::vector<int> online_cpus = GetOnlineCpus();
  420. for (const auto& cpu : cpus) {
  421. if (std::find(online_cpus.begin(), online_cpus.end(), cpu) ==
  422. online_cpus.end()) {
  423. LOG(ERROR) << "cpu " << cpu << " is not online.";
  424. return false;
  425. }
  426. }
  427. return true;
  428. }
  429. bool EventSelectionSet::OpenEventFilesOnGroup(EventSelectionGroup& group,
  430. pid_t tid, int cpu,
  431. std::string* failed_event_type) {
  432. std::vector<std::unique_ptr<EventFd>> event_fds;
  433. // Given a tid and cpu, events on the same group should be all opened
  434. // successfully or all failed to open.
  435. EventFd* group_fd = nullptr;
  436. for (auto& selection : group) {
  437. std::unique_ptr<EventFd> event_fd =
  438. EventFd::OpenEventFile(selection.event_attr, tid, cpu, group_fd, false);
  439. if (!event_fd) {
  440. *failed_event_type = selection.event_type_modifier.name;
  441. return false;
  442. }
  443. LOG(VERBOSE) << "OpenEventFile for " << event_fd->Name();
  444. event_fds.push_back(std::move(event_fd));
  445. if (group_fd == nullptr) {
  446. group_fd = event_fds.back().get();
  447. }
  448. }
  449. for (size_t i = 0; i < group.size(); ++i) {
  450. group[i].event_fds.push_back(std::move(event_fds[i]));
  451. }
  452. return true;
  453. }
  454. static std::map<pid_t, std::set<pid_t>> PrepareThreads(const std::set<pid_t>& processes,
  455. const std::set<pid_t>& threads) {
  456. std::map<pid_t, std::set<pid_t>> result;
  457. for (auto& pid : processes) {
  458. std::vector<pid_t> tids = GetThreadsInProcess(pid);
  459. std::set<pid_t>& threads_in_process = result[pid];
  460. threads_in_process.insert(tids.begin(), tids.end());
  461. }
  462. for (auto& tid : threads) {
  463. // tid = -1 means monitoring all threads.
  464. if (tid == -1) {
  465. result[-1].insert(-1);
  466. } else {
  467. pid_t pid;
  468. if (GetProcessForThread(tid, &pid)) {
  469. result[pid].insert(tid);
  470. }
  471. }
  472. }
  473. return result;
  474. }
  475. bool EventSelectionSet::OpenEventFiles(const std::vector<int>& on_cpus) {
  476. std::vector<int> cpus = on_cpus;
  477. if (!cpus.empty()) {
  478. // cpus = {-1} means open an event file for all cpus.
  479. if (!(cpus.size() == 1 && cpus[0] == -1) && !CheckIfCpusOnline(cpus)) {
  480. return false;
  481. }
  482. } else {
  483. cpus = GetOnlineCpus();
  484. }
  485. std::map<pid_t, std::set<pid_t>> process_map = PrepareThreads(processes_, threads_);
  486. for (auto& group : groups_) {
  487. if (IsUserSpaceSamplerGroup(group)) {
  488. if (!OpenUserSpaceSamplersOnGroup(group, process_map)) {
  489. return false;
  490. }
  491. } else {
  492. for (const auto& pair : process_map) {
  493. size_t success_count = 0;
  494. std::string failed_event_type;
  495. for (const auto& tid : pair.second) {
  496. for (const auto& cpu : cpus) {
  497. if (OpenEventFilesOnGroup(group, tid, cpu, &failed_event_type)) {
  498. success_count++;
  499. }
  500. }
  501. }
  502. // We can't guarantee to open perf event file successfully for each thread on each cpu.
  503. // Because threads may exit between PrepareThreads() and OpenEventFilesOnGroup(), and
  504. // cpus may be offlined between GetOnlineCpus() and OpenEventFilesOnGroup().
  505. // So we only check that we can at least monitor one thread for each process.
  506. if (success_count == 0) {
  507. PLOG(ERROR) << "failed to open perf event file for event_type "
  508. << failed_event_type << " for "
  509. << (pair.first == -1 ? "all threads"
  510. : "threads in process " + std::to_string(pair.first));
  511. return false;
  512. }
  513. }
  514. }
  515. }
  516. return true;
  517. }
  518. bool EventSelectionSet::IsUserSpaceSamplerGroup(EventSelectionGroup& group) {
  519. return group.size() == 1 && group[0].event_attr.type == SIMPLEPERF_TYPE_USER_SPACE_SAMPLERS;
  520. }
  521. bool EventSelectionSet::OpenUserSpaceSamplersOnGroup(EventSelectionGroup& group,
  522. const std::map<pid_t, std::set<pid_t>>& process_map) {
  523. CHECK_EQ(group.size(), 1u);
  524. for (auto& selection : group) {
  525. if (selection.event_attr.type == SIMPLEPERF_TYPE_USER_SPACE_SAMPLERS &&
  526. selection.event_attr.config == SIMPLEPERF_CONFIG_INPLACE_SAMPLER) {
  527. for (auto& pair : process_map) {
  528. std::unique_ptr<InplaceSamplerClient> sampler = InplaceSamplerClient::Create(
  529. selection.event_attr, pair.first, pair.second);
  530. if (sampler == nullptr) {
  531. return false;
  532. }
  533. selection.inplace_samplers.push_back(std::move(sampler));
  534. }
  535. }
  536. }
  537. return true;
  538. }
  539. static bool ReadCounter(EventFd* event_fd, CounterInfo* counter) {
  540. if (!event_fd->ReadCounter(&counter->counter)) {
  541. return false;
  542. }
  543. counter->tid = event_fd->ThreadId();
  544. counter->cpu = event_fd->Cpu();
  545. return true;
  546. }
  547. bool EventSelectionSet::ReadCounters(std::vector<CountersInfo>* counters) {
  548. counters->clear();
  549. for (size_t i = 0; i < groups_.size(); ++i) {
  550. for (auto& selection : groups_[i]) {
  551. CountersInfo counters_info;
  552. counters_info.group_id = i;
  553. counters_info.event_name = selection.event_type_modifier.event_type.name;
  554. counters_info.event_modifier = selection.event_type_modifier.modifier;
  555. counters_info.counters = selection.hotplugged_counters;
  556. for (auto& event_fd : selection.event_fds) {
  557. CounterInfo counter;
  558. if (!ReadCounter(event_fd.get(), &counter)) {
  559. return false;
  560. }
  561. counters_info.counters.push_back(counter);
  562. }
  563. counters->push_back(counters_info);
  564. }
  565. }
  566. return true;
  567. }
  568. bool EventSelectionSet::MmapEventFiles(size_t min_mmap_pages, size_t max_mmap_pages,
  569. size_t record_buffer_size) {
  570. record_read_thread_.reset(new simpleperf::RecordReadThread(
  571. record_buffer_size, groups_[0][0].event_attr, min_mmap_pages, max_mmap_pages));
  572. return true;
  573. }
  574. bool EventSelectionSet::PrepareToReadMmapEventData(const std::function<bool(Record*)>& callback) {
  575. // Prepare record callback function.
  576. record_callback_ = callback;
  577. if (!record_read_thread_->RegisterDataCallback(*loop_,
  578. [this]() { return ReadMmapEventData(true); })) {
  579. return false;
  580. }
  581. std::vector<EventFd*> event_fds;
  582. for (auto& group : groups_) {
  583. for (auto& selection : group) {
  584. for (auto& event_fd : selection.event_fds) {
  585. event_fds.push_back(event_fd.get());
  586. }
  587. }
  588. }
  589. return record_read_thread_->AddEventFds(event_fds);
  590. }
  591. bool EventSelectionSet::SyncKernelBuffer() {
  592. return record_read_thread_->SyncKernelBuffer();
  593. }
  594. // Read records from the RecordBuffer. If with_time_limit is false, read until the RecordBuffer is
  595. // empty, otherwise stop after 100 ms or when the record buffer is empty.
  596. bool EventSelectionSet::ReadMmapEventData(bool with_time_limit) {
  597. uint64_t start_time_in_ns;
  598. if (with_time_limit) {
  599. start_time_in_ns = GetSystemClock();
  600. }
  601. std::unique_ptr<Record> r;
  602. while ((r = record_read_thread_->GetRecord()) != nullptr) {
  603. if (!record_callback_(r.get())) {
  604. return false;
  605. }
  606. if (with_time_limit && (GetSystemClock() - start_time_in_ns) >= 1e8) {
  607. break;
  608. }
  609. }
  610. return true;
  611. }
  612. bool EventSelectionSet::FinishReadMmapEventData() {
  613. // Stop the read thread, so we don't get more records beyond current time.
  614. if (!SyncKernelBuffer() || !record_read_thread_->StopReadThread()) {
  615. return false;
  616. }
  617. if (!ReadMmapEventData(false)) {
  618. return false;
  619. }
  620. if (!HasInplaceSampler()) {
  621. return true;
  622. }
  623. // Inplace sampler server uses a buffer to cache samples before sending them, so we need to
  624. // explicitly ask it to send the cached samples.
  625. loop_.reset(new IOEventLoop);
  626. size_t inplace_sampler_count = 0;
  627. auto close_callback = [&]() {
  628. if (--inplace_sampler_count == 0) {
  629. return loop_->ExitLoop();
  630. }
  631. return true;
  632. };
  633. for (auto& group : groups_) {
  634. for (auto& sel : group) {
  635. for (auto& sampler : sel.inplace_samplers) {
  636. if (!sampler->IsClosed()) {
  637. if (!sampler->StopProfiling(*loop_, close_callback)) {
  638. return false;
  639. }
  640. inplace_sampler_count++;
  641. }
  642. }
  643. }
  644. }
  645. if (inplace_sampler_count == 0) {
  646. return true;
  647. }
  648. // Set a timeout to exit the loop.
  649. timeval tv;
  650. tv.tv_sec = 1;
  651. tv.tv_usec = 0;
  652. if (!loop_->AddPeriodicEvent(tv, [&]() { return loop_->ExitLoop(); })) {
  653. return false;
  654. }
  655. return loop_->RunLoop();
  656. }
  657. void EventSelectionSet::GetLostRecords(size_t* lost_samples, size_t* lost_non_samples,
  658. size_t* cut_stack_samples) {
  659. record_read_thread_->GetLostRecords(lost_samples, lost_non_samples, cut_stack_samples);
  660. }
  661. bool EventSelectionSet::HandleCpuHotplugEvents(const std::vector<int>& monitored_cpus,
  662. double check_interval_in_sec) {
  663. monitored_cpus_.insert(monitored_cpus.begin(), monitored_cpus.end());
  664. online_cpus_ = GetOnlineCpus();
  665. if (!loop_->AddPeriodicEvent(SecondToTimeval(check_interval_in_sec),
  666. [&]() { return DetectCpuHotplugEvents(); })) {
  667. return false;
  668. }
  669. return true;
  670. }
  671. bool EventSelectionSet::DetectCpuHotplugEvents() {
  672. std::vector<int> new_cpus = GetOnlineCpus();
  673. for (const auto& cpu : online_cpus_) {
  674. if (std::find(new_cpus.begin(), new_cpus.end(), cpu) == new_cpus.end()) {
  675. if (monitored_cpus_.empty() ||
  676. monitored_cpus_.find(cpu) != monitored_cpus_.end()) {
  677. LOG(INFO) << "Cpu " << cpu << " is offlined";
  678. if (!HandleCpuOfflineEvent(cpu)) {
  679. return false;
  680. }
  681. }
  682. }
  683. }
  684. for (const auto& cpu : new_cpus) {
  685. if (std::find(online_cpus_.begin(), online_cpus_.end(), cpu) ==
  686. online_cpus_.end()) {
  687. if (monitored_cpus_.empty() ||
  688. monitored_cpus_.find(cpu) != monitored_cpus_.end()) {
  689. LOG(INFO) << "Cpu " << cpu << " is onlined";
  690. if (!HandleCpuOnlineEvent(cpu)) {
  691. return false;
  692. }
  693. }
  694. }
  695. }
  696. online_cpus_ = new_cpus;
  697. return true;
  698. }
  699. bool EventSelectionSet::HandleCpuOfflineEvent(int cpu) {
  700. if (!for_stat_cmd_) {
  701. // Read mmap data here, so we won't lose the existing records of the
  702. // offlined cpu.
  703. if (!ReadMmapEventData(true)) {
  704. return false;
  705. }
  706. }
  707. if (record_read_thread_) {
  708. std::vector<EventFd*> remove_fds;
  709. for (auto& group : groups_) {
  710. for (auto& selection : group) {
  711. for (auto& fd : selection.event_fds) {
  712. if (fd->Cpu() == cpu) {
  713. remove_fds.push_back(fd.get());
  714. }
  715. }
  716. }
  717. }
  718. if (!record_read_thread_->RemoveEventFds(remove_fds)) {
  719. return false;
  720. }
  721. }
  722. for (auto& group : groups_) {
  723. for (auto& selection : group) {
  724. for (auto it = selection.event_fds.begin(); it != selection.event_fds.end();) {
  725. if ((*it)->Cpu() == cpu) {
  726. if (for_stat_cmd_) {
  727. CounterInfo counter;
  728. if (!ReadCounter(it->get(), &counter)) {
  729. return false;
  730. }
  731. selection.hotplugged_counters.push_back(counter);
  732. }
  733. it = selection.event_fds.erase(it);
  734. } else {
  735. ++it;
  736. }
  737. }
  738. }
  739. }
  740. return true;
  741. }
  742. bool EventSelectionSet::HandleCpuOnlineEvent(int cpu) {
  743. // We need to start profiling when opening new event files.
  744. SetEnableOnExec(false);
  745. std::map<pid_t, std::set<pid_t>> process_map = PrepareThreads(processes_, threads_);
  746. for (auto& group : groups_) {
  747. if (IsUserSpaceSamplerGroup(group)) {
  748. continue;
  749. }
  750. for (const auto& pair : process_map) {
  751. for (const auto& tid : pair.second) {
  752. std::string failed_event_type;
  753. if (!OpenEventFilesOnGroup(group, tid, cpu, &failed_event_type)) {
  754. // If failed to open event files, maybe the cpu has been offlined.
  755. PLOG(WARNING) << "failed to open perf event file for event_type "
  756. << failed_event_type << " for "
  757. << (tid == -1 ? "all threads" : "thread " + std::to_string(tid))
  758. << " on cpu " << cpu;
  759. }
  760. }
  761. }
  762. }
  763. if (record_read_thread_) {
  764. // Prepare mapped buffer.
  765. if (!CreateMappedBufferForCpu(cpu)) {
  766. return false;
  767. }
  768. // Send a EventIdRecord.
  769. std::vector<uint64_t> event_id_data;
  770. uint64_t attr_id = 0;
  771. for (const auto& group : groups_) {
  772. for (const auto& selection : group) {
  773. for (const auto& event_fd : selection.event_fds) {
  774. if (event_fd->Cpu() == cpu) {
  775. event_id_data.push_back(attr_id);
  776. event_id_data.push_back(event_fd->Id());
  777. }
  778. }
  779. ++attr_id;
  780. }
  781. }
  782. EventIdRecord r(event_id_data);
  783. if (!record_callback_(&r)) {
  784. return false;
  785. }
  786. }
  787. return true;
  788. }
  789. bool EventSelectionSet::CreateMappedBufferForCpu(int cpu) {
  790. std::vector<EventFd*> event_fds;
  791. for (auto& group : groups_) {
  792. for (auto& selection : group) {
  793. for (auto& fd : selection.event_fds) {
  794. if (fd->Cpu() == cpu) {
  795. event_fds.push_back(fd.get());
  796. }
  797. }
  798. }
  799. }
  800. return record_read_thread_->AddEventFds(event_fds);
  801. }
  802. bool EventSelectionSet::StopWhenNoMoreTargets(double check_interval_in_sec) {
  803. return loop_->AddPeriodicEvent(SecondToTimeval(check_interval_in_sec),
  804. [&]() { return CheckMonitoredTargets(); });
  805. }
  806. bool EventSelectionSet::CheckMonitoredTargets() {
  807. if (!HasSampler()) {
  808. return loop_->ExitLoop();
  809. }
  810. for (const auto& tid : threads_) {
  811. if (IsThreadAlive(tid)) {
  812. return true;
  813. }
  814. }
  815. for (const auto& pid : processes_) {
  816. if (IsThreadAlive(pid)) {
  817. return true;
  818. }
  819. }
  820. return loop_->ExitLoop();
  821. }
  822. bool EventSelectionSet::HasSampler() {
  823. for (auto& group : groups_) {
  824. for (auto& sel : group) {
  825. if (!sel.event_fds.empty()) {
  826. return true;
  827. }
  828. for (auto& sampler : sel.inplace_samplers) {
  829. if (!sampler->IsClosed()) {
  830. return true;
  831. }
  832. }
  833. }
  834. }
  835. return false;
  836. }
  837. bool EventSelectionSet::SetEnableEvents(bool enable) {
  838. for (auto& group : groups_) {
  839. for (auto& sel : group) {
  840. for (auto& fd : sel.event_fds) {
  841. if (!fd->SetEnableEvent(enable)) {
  842. return false;
  843. }
  844. }
  845. }
  846. }
  847. return true;
  848. }