event_selection_set.cpp revision f569b478e74560a2d9e29a96824e16b93a55b97f
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#include "event_selection_set.h"
18
19#include <base/logging.h>
20
21#include "environment.h"
22#include "event_attr.h"
23#include "event_type.h"
24
25void EventSelectionSet::AddEventType(const EventType& event_type) {
26  EventSelection selection;
27  selection.event_type = &event_type;
28  selection.event_attr = CreateDefaultPerfEventAttr(event_type);
29  selections_.push_back(std::move(selection));
30}
31
32void EventSelectionSet::EnableOnExec() {
33  for (auto& selection : selections_) {
34    selection.event_attr.enable_on_exec = 1;
35  }
36}
37
38void EventSelectionSet::SampleIdAll() {
39  for (auto& selection : selections_) {
40    selection.event_attr.sample_id_all = 1;
41  }
42}
43
44void EventSelectionSet::SetSampleFreq(uint64_t sample_freq) {
45  for (auto& selection : selections_) {
46    perf_event_attr& attr = selection.event_attr;
47    attr.freq = 1;
48    attr.sample_freq = sample_freq;
49  }
50}
51
52void EventSelectionSet::SetSamplePeriod(uint64_t sample_period) {
53  for (auto& selection : selections_) {
54    perf_event_attr& attr = selection.event_attr;
55    attr.freq = 0;
56    attr.sample_period = sample_period;
57  }
58}
59
60bool EventSelectionSet::OpenEventFilesForAllCpus() {
61  std::vector<int> cpus = GetOnlineCpus();
62  if (cpus.empty()) {
63    return false;
64  }
65  for (auto& selection : selections_) {
66    for (auto& cpu : cpus) {
67      auto event_fd = EventFd::OpenEventFileForCpu(selection.event_attr, cpu);
68      if (event_fd != nullptr) {
69        selection.event_fds.push_back(std::move(event_fd));
70      }
71    }
72    // As the online cpus can be enabled or disabled at runtime, we may not open event file for
73    // all cpus successfully. But we should open at least one cpu successfully.
74    if (selection.event_fds.empty()) {
75      LOG(ERROR) << "failed to open perf event file for event_type " << selection.event_type->name
76                 << " on all cpus";
77      return false;
78    }
79  }
80  return true;
81}
82
83bool EventSelectionSet::OpenEventFilesForProcess(pid_t pid) {
84  for (auto& selection : selections_) {
85    auto event_fd = EventFd::OpenEventFileForProcess(selection.event_attr, pid);
86    if (event_fd == nullptr) {
87      PLOG(ERROR) << "failed to open perf event file for event type " << selection.event_type->name
88                  << " on pid " << pid;
89      return false;
90    }
91    selection.event_fds.push_back(std::move(event_fd));
92  }
93  return true;
94}
95
96bool EventSelectionSet::EnableEvents() {
97  for (auto& selection : selections_) {
98    for (auto& event_fd : selection.event_fds) {
99      if (!event_fd->EnableEvent()) {
100        return false;
101      }
102    }
103  }
104  return true;
105}
106
107bool EventSelectionSet::ReadCounters(
108    std::map<const EventType*, std::vector<PerfCounter>>* counters_map) {
109  for (auto& selection : selections_) {
110    std::vector<PerfCounter> counters;
111    for (auto& event_fd : selection.event_fds) {
112      PerfCounter counter;
113      if (!event_fd->ReadCounter(&counter)) {
114        return false;
115      }
116      counters.push_back(counter);
117    }
118    counters_map->insert(std::make_pair(selection.event_type, counters));
119  }
120  return true;
121}
122
123void EventSelectionSet::PreparePollForEventFiles(std::vector<pollfd>* pollfds) {
124  for (auto& selection : selections_) {
125    for (auto& event_fd : selection.event_fds) {
126      pollfd poll_fd;
127      event_fd->PreparePollForMmapData(&poll_fd);
128      pollfds->push_back(poll_fd);
129    }
130  }
131}
132
133bool EventSelectionSet::MmapEventFiles(size_t mmap_pages) {
134  for (auto& selection : selections_) {
135    for (auto& event_fd : selection.event_fds) {
136      if (!event_fd->MmapContent(mmap_pages)) {
137        return false;
138      }
139    }
140  }
141  return true;
142}
143
144static bool ReadMmapEventDataForFd(std::unique_ptr<EventFd>& event_fd,
145                                   std::function<bool(const char*, size_t)> callback,
146                                   bool* have_data) {
147  *have_data = false;
148  while (true) {
149    char* data;
150    size_t size = event_fd->GetAvailableMmapData(&data);
151    if (size == 0) {
152      break;
153    }
154    if (!callback(data, size)) {
155      return false;
156    }
157    *have_data = true;
158    event_fd->DiscardMmapData(size);
159  }
160  return true;
161}
162
163bool EventSelectionSet::ReadMmapEventData(std::function<bool(const char*, size_t)> callback) {
164  for (auto& selection : selections_) {
165    for (auto& event_fd : selection.event_fds) {
166      while (true) {
167        bool have_data;
168        if (!ReadMmapEventDataForFd(event_fd, callback, &have_data)) {
169          return false;
170        }
171        if (!have_data) {
172          break;
173        }
174      }
175    }
176  }
177  return true;
178}
179
180std::string EventSelectionSet::FindEventFileNameById(uint64_t id) {
181  for (auto& selection : selections_) {
182    for (auto& event_fd : selection.event_fds) {
183      if (event_fd->Id() == id) {
184        return event_fd->Name();
185      }
186    }
187  }
188  return "";
189}
190
191EventSelectionSet::EventSelection* EventSelectionSet::FindSelectionByType(
192    const EventType& event_type) {
193  for (auto& selection : selections_) {
194    if (selection.event_type->name == event_type.name) {
195      return &selection;
196    }
197  }
198  return nullptr;
199}
200
201const perf_event_attr& EventSelectionSet::FindEventAttrByType(const EventType& event_type) {
202  return FindSelectionByType(event_type)->event_attr;
203}
204
205const std::vector<std::unique_ptr<EventFd>>& EventSelectionSet::FindEventFdsByType(
206    const EventType& event_type) {
207  return FindSelectionByType(event_type)->event_fds;
208}
209