1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker *
4*288bf522SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker *
8*288bf522SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker *
10*288bf522SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker */
16*288bf522SAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_ALWAYS
17*288bf522SAndroid Build Coastguard Worker #include "event_fd.h"
18*288bf522SAndroid Build Coastguard Worker
19*288bf522SAndroid Build Coastguard Worker #include <cutils/trace.h>
20*288bf522SAndroid Build Coastguard Worker #include <fcntl.h>
21*288bf522SAndroid Build Coastguard Worker #include <stdio.h>
22*288bf522SAndroid Build Coastguard Worker #include <string.h>
23*288bf522SAndroid Build Coastguard Worker #include <sys/ioctl.h>
24*288bf522SAndroid Build Coastguard Worker #include <sys/mman.h>
25*288bf522SAndroid Build Coastguard Worker #include <sys/syscall.h>
26*288bf522SAndroid Build Coastguard Worker #include <sys/types.h>
27*288bf522SAndroid Build Coastguard Worker #include <utils/Trace.h>
28*288bf522SAndroid Build Coastguard Worker #include <atomic>
29*288bf522SAndroid Build Coastguard Worker #include <memory>
30*288bf522SAndroid Build Coastguard Worker
31*288bf522SAndroid Build Coastguard Worker #include <android-base/file.h>
32*288bf522SAndroid Build Coastguard Worker #include <android-base/logging.h>
33*288bf522SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
34*288bf522SAndroid Build Coastguard Worker
35*288bf522SAndroid Build Coastguard Worker #include "environment.h"
36*288bf522SAndroid Build Coastguard Worker #include "event_attr.h"
37*288bf522SAndroid Build Coastguard Worker #include "event_type.h"
38*288bf522SAndroid Build Coastguard Worker #include "perf_event.h"
39*288bf522SAndroid Build Coastguard Worker #include "utils.h"
40*288bf522SAndroid Build Coastguard Worker
41*288bf522SAndroid Build Coastguard Worker namespace simpleperf {
42*288bf522SAndroid Build Coastguard Worker
perf_event_open(const perf_event_attr & attr,pid_t pid,int cpu,int group_fd,unsigned long flags)43*288bf522SAndroid Build Coastguard Worker static int perf_event_open(const perf_event_attr& attr, pid_t pid, int cpu, int group_fd,
44*288bf522SAndroid Build Coastguard Worker unsigned long flags) { // NOLINT
45*288bf522SAndroid Build Coastguard Worker return syscall(__NR_perf_event_open, &attr, pid, cpu, group_fd, flags);
46*288bf522SAndroid Build Coastguard Worker }
47*288bf522SAndroid Build Coastguard Worker
OpenEventFile(const perf_event_attr & attr,pid_t tid,int cpu,EventFd * group_event_fd,const std::string & event_name,bool report_error)48*288bf522SAndroid Build Coastguard Worker std::unique_ptr<EventFd> EventFd::OpenEventFile(const perf_event_attr& attr, pid_t tid, int cpu,
49*288bf522SAndroid Build Coastguard Worker EventFd* group_event_fd,
50*288bf522SAndroid Build Coastguard Worker const std::string& event_name, bool report_error) {
51*288bf522SAndroid Build Coastguard Worker int group_fd = -1;
52*288bf522SAndroid Build Coastguard Worker if (group_event_fd != nullptr) {
53*288bf522SAndroid Build Coastguard Worker group_fd = group_event_fd->perf_event_fd_;
54*288bf522SAndroid Build Coastguard Worker }
55*288bf522SAndroid Build Coastguard Worker perf_event_attr real_attr = attr;
56*288bf522SAndroid Build Coastguard Worker if (attr.freq) {
57*288bf522SAndroid Build Coastguard Worker uint64_t max_sample_freq;
58*288bf522SAndroid Build Coastguard Worker if (GetMaxSampleFrequency(&max_sample_freq) && max_sample_freq < attr.sample_freq) {
59*288bf522SAndroid Build Coastguard Worker static bool warned = false;
60*288bf522SAndroid Build Coastguard Worker if (!warned) {
61*288bf522SAndroid Build Coastguard Worker warned = true;
62*288bf522SAndroid Build Coastguard Worker LOG(INFO) << "Adjust sample freq to max allowed sample freq " << max_sample_freq;
63*288bf522SAndroid Build Coastguard Worker }
64*288bf522SAndroid Build Coastguard Worker real_attr.sample_freq = max_sample_freq;
65*288bf522SAndroid Build Coastguard Worker }
66*288bf522SAndroid Build Coastguard Worker }
67*288bf522SAndroid Build Coastguard Worker int perf_event_fd = perf_event_open(real_attr, tid, cpu, group_fd, 0);
68*288bf522SAndroid Build Coastguard Worker if (perf_event_fd == -1) {
69*288bf522SAndroid Build Coastguard Worker if (report_error) {
70*288bf522SAndroid Build Coastguard Worker PLOG(ERROR) << "open perf_event_file (event " << event_name << ", tid " << tid << ", cpu "
71*288bf522SAndroid Build Coastguard Worker << cpu << ", group_fd " << group_fd << ") failed";
72*288bf522SAndroid Build Coastguard Worker } else {
73*288bf522SAndroid Build Coastguard Worker PLOG(DEBUG) << "open perf_event_file (event " << event_name << ", tid " << tid << ", cpu "
74*288bf522SAndroid Build Coastguard Worker << cpu << ", group_fd " << group_fd << ") failed";
75*288bf522SAndroid Build Coastguard Worker }
76*288bf522SAndroid Build Coastguard Worker return nullptr;
77*288bf522SAndroid Build Coastguard Worker }
78*288bf522SAndroid Build Coastguard Worker if (fcntl(perf_event_fd, F_SETFD, FD_CLOEXEC) == -1) {
79*288bf522SAndroid Build Coastguard Worker if (report_error) {
80*288bf522SAndroid Build Coastguard Worker PLOG(ERROR) << "fcntl(FD_CLOEXEC) for perf_event_file (event " << event_name << ", tid "
81*288bf522SAndroid Build Coastguard Worker << tid << ", cpu " << cpu << ", group_fd " << group_fd << ") failed";
82*288bf522SAndroid Build Coastguard Worker } else {
83*288bf522SAndroid Build Coastguard Worker PLOG(DEBUG) << "fcntl(FD_CLOEXEC) for perf_event_file (event " << event_name << ", tid "
84*288bf522SAndroid Build Coastguard Worker << tid << ", cpu " << cpu << ", group_fd " << group_fd << ") failed";
85*288bf522SAndroid Build Coastguard Worker }
86*288bf522SAndroid Build Coastguard Worker return nullptr;
87*288bf522SAndroid Build Coastguard Worker }
88*288bf522SAndroid Build Coastguard Worker return std::unique_ptr<EventFd>(new EventFd(real_attr, perf_event_fd, event_name, tid, cpu));
89*288bf522SAndroid Build Coastguard Worker }
90*288bf522SAndroid Build Coastguard Worker
~EventFd()91*288bf522SAndroid Build Coastguard Worker EventFd::~EventFd() {
92*288bf522SAndroid Build Coastguard Worker DestroyMappedBuffer();
93*288bf522SAndroid Build Coastguard Worker DestroyAuxBuffer();
94*288bf522SAndroid Build Coastguard Worker close(perf_event_fd_);
95*288bf522SAndroid Build Coastguard Worker }
96*288bf522SAndroid Build Coastguard Worker
Name() const97*288bf522SAndroid Build Coastguard Worker std::string EventFd::Name() const {
98*288bf522SAndroid Build Coastguard Worker return android::base::StringPrintf("perf_event_file(event %s, tid %d, cpu %d)",
99*288bf522SAndroid Build Coastguard Worker event_name_.c_str(), tid_, cpu_);
100*288bf522SAndroid Build Coastguard Worker }
101*288bf522SAndroid Build Coastguard Worker
Id() const102*288bf522SAndroid Build Coastguard Worker uint64_t EventFd::Id() const {
103*288bf522SAndroid Build Coastguard Worker if (id_ == 0) {
104*288bf522SAndroid Build Coastguard Worker if (ioctl(perf_event_fd_, PERF_EVENT_IOC_ID, &id_) != 0) {
105*288bf522SAndroid Build Coastguard Worker // PERF_EVENT_IOC_ID isn't available in kernel <= 3.10. Fallback to read() in this case.
106*288bf522SAndroid Build Coastguard Worker PerfCounter counter;
107*288bf522SAndroid Build Coastguard Worker if (InnerReadCounter(&counter)) {
108*288bf522SAndroid Build Coastguard Worker id_ = counter.id;
109*288bf522SAndroid Build Coastguard Worker } else {
110*288bf522SAndroid Build Coastguard Worker PLOG(WARNING) << "failed to get id of event_fd";
111*288bf522SAndroid Build Coastguard Worker }
112*288bf522SAndroid Build Coastguard Worker }
113*288bf522SAndroid Build Coastguard Worker }
114*288bf522SAndroid Build Coastguard Worker return id_;
115*288bf522SAndroid Build Coastguard Worker }
116*288bf522SAndroid Build Coastguard Worker
SetEnableEvent(bool enable)117*288bf522SAndroid Build Coastguard Worker bool EventFd::SetEnableEvent(bool enable) {
118*288bf522SAndroid Build Coastguard Worker int result = ioctl(perf_event_fd_, enable ? PERF_EVENT_IOC_ENABLE : PERF_EVENT_IOC_DISABLE, 0);
119*288bf522SAndroid Build Coastguard Worker if (result < 0) {
120*288bf522SAndroid Build Coastguard Worker PLOG(ERROR) << "ioctl(" << (enable ? "enable" : "disable") << ")" << Name() << " failed";
121*288bf522SAndroid Build Coastguard Worker return false;
122*288bf522SAndroid Build Coastguard Worker }
123*288bf522SAndroid Build Coastguard Worker return true;
124*288bf522SAndroid Build Coastguard Worker }
125*288bf522SAndroid Build Coastguard Worker
SetFilter(const std::string & filter)126*288bf522SAndroid Build Coastguard Worker bool EventFd::SetFilter(const std::string& filter) {
127*288bf522SAndroid Build Coastguard Worker bool success = ioctl(perf_event_fd_, PERF_EVENT_IOC_SET_FILTER, filter.c_str()) >= 0;
128*288bf522SAndroid Build Coastguard Worker if (!success) {
129*288bf522SAndroid Build Coastguard Worker PLOG(ERROR) << "failed to set filter";
130*288bf522SAndroid Build Coastguard Worker }
131*288bf522SAndroid Build Coastguard Worker return success;
132*288bf522SAndroid Build Coastguard Worker }
133*288bf522SAndroid Build Coastguard Worker
InnerReadCounter(PerfCounter * counter) const134*288bf522SAndroid Build Coastguard Worker bool EventFd::InnerReadCounter(PerfCounter* counter) const {
135*288bf522SAndroid Build Coastguard Worker CHECK(counter != nullptr);
136*288bf522SAndroid Build Coastguard Worker if (!android::base::ReadFully(perf_event_fd_, counter, sizeof(*counter))) {
137*288bf522SAndroid Build Coastguard Worker PLOG(ERROR) << "ReadCounter from " << Name() << " failed";
138*288bf522SAndroid Build Coastguard Worker return false;
139*288bf522SAndroid Build Coastguard Worker }
140*288bf522SAndroid Build Coastguard Worker return true;
141*288bf522SAndroid Build Coastguard Worker }
142*288bf522SAndroid Build Coastguard Worker
ReadCounter(PerfCounter * counter)143*288bf522SAndroid Build Coastguard Worker bool EventFd::ReadCounter(PerfCounter* counter) {
144*288bf522SAndroid Build Coastguard Worker if (!InnerReadCounter(counter)) {
145*288bf522SAndroid Build Coastguard Worker return false;
146*288bf522SAndroid Build Coastguard Worker }
147*288bf522SAndroid Build Coastguard Worker // Trace is always available to systrace if enabled
148*288bf522SAndroid Build Coastguard Worker if (tid_ > 0) {
149*288bf522SAndroid Build Coastguard Worker ATRACE_INT64(
150*288bf522SAndroid Build Coastguard Worker android::base::StringPrintf("%s_tid%d_cpu%d", event_name_.c_str(), tid_, cpu_).c_str(),
151*288bf522SAndroid Build Coastguard Worker counter->value - last_counter_value_);
152*288bf522SAndroid Build Coastguard Worker } else {
153*288bf522SAndroid Build Coastguard Worker ATRACE_INT64(android::base::StringPrintf("%s_cpu%d", event_name_.c_str(), cpu_).c_str(),
154*288bf522SAndroid Build Coastguard Worker counter->value - last_counter_value_);
155*288bf522SAndroid Build Coastguard Worker }
156*288bf522SAndroid Build Coastguard Worker last_counter_value_ = counter->value;
157*288bf522SAndroid Build Coastguard Worker return true;
158*288bf522SAndroid Build Coastguard Worker }
159*288bf522SAndroid Build Coastguard Worker
CreateMappedBuffer(size_t mmap_pages,bool report_error)160*288bf522SAndroid Build Coastguard Worker bool EventFd::CreateMappedBuffer(size_t mmap_pages, bool report_error) {
161*288bf522SAndroid Build Coastguard Worker CHECK(IsPowerOfTwo(mmap_pages));
162*288bf522SAndroid Build Coastguard Worker size_t page_size = sysconf(_SC_PAGE_SIZE);
163*288bf522SAndroid Build Coastguard Worker size_t mmap_len = (mmap_pages + 1) * page_size;
164*288bf522SAndroid Build Coastguard Worker void* mmap_addr = mmap(nullptr, mmap_len, PROT_READ | PROT_WRITE, MAP_SHARED, perf_event_fd_, 0);
165*288bf522SAndroid Build Coastguard Worker if (mmap_addr == MAP_FAILED) {
166*288bf522SAndroid Build Coastguard Worker bool is_perm_error = (errno == EPERM);
167*288bf522SAndroid Build Coastguard Worker if (report_error) {
168*288bf522SAndroid Build Coastguard Worker PLOG(ERROR) << "mmap(" << mmap_pages << ") failed for " << Name();
169*288bf522SAndroid Build Coastguard Worker } else {
170*288bf522SAndroid Build Coastguard Worker PLOG(DEBUG) << "mmap(" << mmap_pages << ") failed for " << Name();
171*288bf522SAndroid Build Coastguard Worker }
172*288bf522SAndroid Build Coastguard Worker if (report_error && is_perm_error) {
173*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "It seems the kernel doesn't allow allocating enough "
174*288bf522SAndroid Build Coastguard Worker << "buffer for dumping samples, consider decreasing mmap pages(-m).";
175*288bf522SAndroid Build Coastguard Worker }
176*288bf522SAndroid Build Coastguard Worker return false;
177*288bf522SAndroid Build Coastguard Worker }
178*288bf522SAndroid Build Coastguard Worker mmap_addr_ = mmap_addr;
179*288bf522SAndroid Build Coastguard Worker mmap_len_ = mmap_len;
180*288bf522SAndroid Build Coastguard Worker mmap_metadata_page_ = reinterpret_cast<perf_event_mmap_page*>(mmap_addr_);
181*288bf522SAndroid Build Coastguard Worker mmap_data_buffer_ = reinterpret_cast<char*>(mmap_addr_) + page_size;
182*288bf522SAndroid Build Coastguard Worker mmap_data_buffer_size_ = mmap_len_ - page_size;
183*288bf522SAndroid Build Coastguard Worker return true;
184*288bf522SAndroid Build Coastguard Worker }
185*288bf522SAndroid Build Coastguard Worker
ShareMappedBuffer(const EventFd & event_fd,bool report_error)186*288bf522SAndroid Build Coastguard Worker bool EventFd::ShareMappedBuffer(const EventFd& event_fd, bool report_error) {
187*288bf522SAndroid Build Coastguard Worker CHECK(!HasMappedBuffer());
188*288bf522SAndroid Build Coastguard Worker CHECK(event_fd.HasMappedBuffer());
189*288bf522SAndroid Build Coastguard Worker int result = ioctl(perf_event_fd_, PERF_EVENT_IOC_SET_OUTPUT, event_fd.perf_event_fd_);
190*288bf522SAndroid Build Coastguard Worker if (result != 0) {
191*288bf522SAndroid Build Coastguard Worker if (report_error) {
192*288bf522SAndroid Build Coastguard Worker PLOG(ERROR) << "failed to share mapped buffer of " << event_fd.perf_event_fd_ << " with "
193*288bf522SAndroid Build Coastguard Worker << perf_event_fd_;
194*288bf522SAndroid Build Coastguard Worker }
195*288bf522SAndroid Build Coastguard Worker return false;
196*288bf522SAndroid Build Coastguard Worker }
197*288bf522SAndroid Build Coastguard Worker return true;
198*288bf522SAndroid Build Coastguard Worker }
199*288bf522SAndroid Build Coastguard Worker
DestroyMappedBuffer()200*288bf522SAndroid Build Coastguard Worker void EventFd::DestroyMappedBuffer() {
201*288bf522SAndroid Build Coastguard Worker if (HasMappedBuffer()) {
202*288bf522SAndroid Build Coastguard Worker munmap(mmap_addr_, mmap_len_);
203*288bf522SAndroid Build Coastguard Worker mmap_addr_ = nullptr;
204*288bf522SAndroid Build Coastguard Worker mmap_len_ = 0;
205*288bf522SAndroid Build Coastguard Worker mmap_metadata_page_ = nullptr;
206*288bf522SAndroid Build Coastguard Worker mmap_data_buffer_ = nullptr;
207*288bf522SAndroid Build Coastguard Worker mmap_data_buffer_size_ = 0;
208*288bf522SAndroid Build Coastguard Worker }
209*288bf522SAndroid Build Coastguard Worker }
210*288bf522SAndroid Build Coastguard Worker
GetAvailableMmapData()211*288bf522SAndroid Build Coastguard Worker std::vector<char> EventFd::GetAvailableMmapData() {
212*288bf522SAndroid Build Coastguard Worker size_t data_pos;
213*288bf522SAndroid Build Coastguard Worker size_t data_size = GetAvailableMmapDataSize(data_pos);
214*288bf522SAndroid Build Coastguard Worker std::vector<char> data(data_size);
215*288bf522SAndroid Build Coastguard Worker if (data_size > 0) {
216*288bf522SAndroid Build Coastguard Worker size_t copy_size = std::min(data_size, mmap_data_buffer_size_ - data_pos);
217*288bf522SAndroid Build Coastguard Worker memcpy(&data[0], mmap_data_buffer_ + data_pos, copy_size);
218*288bf522SAndroid Build Coastguard Worker if (copy_size < data_size) {
219*288bf522SAndroid Build Coastguard Worker memcpy(&data[copy_size], mmap_data_buffer_, data_size - copy_size);
220*288bf522SAndroid Build Coastguard Worker }
221*288bf522SAndroid Build Coastguard Worker DiscardMmapData(data_size);
222*288bf522SAndroid Build Coastguard Worker }
223*288bf522SAndroid Build Coastguard Worker return data;
224*288bf522SAndroid Build Coastguard Worker }
225*288bf522SAndroid Build Coastguard Worker
GetAvailableMmapDataSize(size_t & data_pos)226*288bf522SAndroid Build Coastguard Worker size_t EventFd::GetAvailableMmapDataSize(size_t& data_pos) {
227*288bf522SAndroid Build Coastguard Worker // The mmap_data_buffer is used as a ring buffer between the kernel and
228*288bf522SAndroid Build Coastguard Worker // simpleperf. The kernel continuously writes records to the buffer, and
229*288bf522SAndroid Build Coastguard Worker // simpleperf continuously read records out.
230*288bf522SAndroid Build Coastguard Worker // _________________________________________
231*288bf522SAndroid Build Coastguard Worker // buffer | can write | can read | can write |
232*288bf522SAndroid Build Coastguard Worker // ^ ^
233*288bf522SAndroid Build Coastguard Worker // read_head write_head
234*288bf522SAndroid Build Coastguard Worker //
235*288bf522SAndroid Build Coastguard Worker // So simpleperf can read records in [read_head, write_head), and the kernel
236*288bf522SAndroid Build Coastguard Worker // can write records in [write_head, read_head). The kernel is responsible
237*288bf522SAndroid Build Coastguard Worker // for updating write_head, and simpleperf is responsible for updating
238*288bf522SAndroid Build Coastguard Worker // read_head.
239*288bf522SAndroid Build Coastguard Worker
240*288bf522SAndroid Build Coastguard Worker uint64_t write_head = mmap_metadata_page_->data_head;
241*288bf522SAndroid Build Coastguard Worker uint64_t read_head = mmap_metadata_page_->data_tail;
242*288bf522SAndroid Build Coastguard Worker // The kernel may decrease data_head temporarily (http://b/132446871), making
243*288bf522SAndroid Build Coastguard Worker // write_head < read_head. So check it to avoid available data size underflow.
244*288bf522SAndroid Build Coastguard Worker if (write_head <= read_head) {
245*288bf522SAndroid Build Coastguard Worker // No available data.
246*288bf522SAndroid Build Coastguard Worker return 0;
247*288bf522SAndroid Build Coastguard Worker }
248*288bf522SAndroid Build Coastguard Worker // rmb() used to ensure reading data after reading data_head.
249*288bf522SAndroid Build Coastguard Worker __sync_synchronize();
250*288bf522SAndroid Build Coastguard Worker data_pos = read_head & (mmap_data_buffer_size_ - 1);
251*288bf522SAndroid Build Coastguard Worker return write_head - read_head;
252*288bf522SAndroid Build Coastguard Worker }
253*288bf522SAndroid Build Coastguard Worker
DiscardMmapData(size_t discard_size)254*288bf522SAndroid Build Coastguard Worker void EventFd::DiscardMmapData(size_t discard_size) {
255*288bf522SAndroid Build Coastguard Worker // mb() used to ensure finish reading data before writing data_tail.
256*288bf522SAndroid Build Coastguard Worker __sync_synchronize();
257*288bf522SAndroid Build Coastguard Worker mmap_metadata_page_->data_tail += discard_size;
258*288bf522SAndroid Build Coastguard Worker }
259*288bf522SAndroid Build Coastguard Worker
CreateAuxBuffer(size_t aux_buffer_size,bool report_error)260*288bf522SAndroid Build Coastguard Worker bool EventFd::CreateAuxBuffer(size_t aux_buffer_size, bool report_error) {
261*288bf522SAndroid Build Coastguard Worker CHECK(HasMappedBuffer());
262*288bf522SAndroid Build Coastguard Worker CHECK(IsPowerOfTwo(aux_buffer_size));
263*288bf522SAndroid Build Coastguard Worker mmap_metadata_page_->aux_offset = mmap_len_;
264*288bf522SAndroid Build Coastguard Worker mmap_metadata_page_->aux_size = aux_buffer_size;
265*288bf522SAndroid Build Coastguard Worker mmap_metadata_page_->aux_head = 0;
266*288bf522SAndroid Build Coastguard Worker mmap_metadata_page_->aux_tail = 0;
267*288bf522SAndroid Build Coastguard Worker void* mmap_addr = mmap(nullptr, aux_buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED,
268*288bf522SAndroid Build Coastguard Worker perf_event_fd_, mmap_metadata_page_->aux_offset);
269*288bf522SAndroid Build Coastguard Worker if (mmap_addr == MAP_FAILED) {
270*288bf522SAndroid Build Coastguard Worker if (report_error) {
271*288bf522SAndroid Build Coastguard Worker PLOG(ERROR) << "failed to mmap aux buffer of size " << aux_buffer_size << " for " << Name();
272*288bf522SAndroid Build Coastguard Worker } else {
273*288bf522SAndroid Build Coastguard Worker PLOG(DEBUG) << "failed to mmap aux buffer of size " << aux_buffer_size << " for " << Name();
274*288bf522SAndroid Build Coastguard Worker }
275*288bf522SAndroid Build Coastguard Worker return false;
276*288bf522SAndroid Build Coastguard Worker }
277*288bf522SAndroid Build Coastguard Worker aux_buffer_ = static_cast<char*>(mmap_addr);
278*288bf522SAndroid Build Coastguard Worker aux_buffer_size_ = aux_buffer_size;
279*288bf522SAndroid Build Coastguard Worker return true;
280*288bf522SAndroid Build Coastguard Worker }
281*288bf522SAndroid Build Coastguard Worker
DestroyAuxBuffer()282*288bf522SAndroid Build Coastguard Worker void EventFd::DestroyAuxBuffer() {
283*288bf522SAndroid Build Coastguard Worker if (HasAuxBuffer()) {
284*288bf522SAndroid Build Coastguard Worker munmap(aux_buffer_, aux_buffer_size_);
285*288bf522SAndroid Build Coastguard Worker aux_buffer_ = nullptr;
286*288bf522SAndroid Build Coastguard Worker aux_buffer_size_ = 0;
287*288bf522SAndroid Build Coastguard Worker }
288*288bf522SAndroid Build Coastguard Worker }
289*288bf522SAndroid Build Coastguard Worker
GetAvailableAuxData(char ** buf1,size_t * size1,char ** buf2,size_t * size2)290*288bf522SAndroid Build Coastguard Worker uint64_t EventFd::GetAvailableAuxData(char** buf1, size_t* size1, char** buf2, size_t* size2) {
291*288bf522SAndroid Build Coastguard Worker // Aux buffer is similar to mapped_data_buffer. See comments in GetAvailableMmapData().
292*288bf522SAndroid Build Coastguard Worker uint64_t write_head = mmap_metadata_page_->aux_head;
293*288bf522SAndroid Build Coastguard Worker uint64_t read_head = mmap_metadata_page_->aux_tail;
294*288bf522SAndroid Build Coastguard Worker if (write_head <= read_head) {
295*288bf522SAndroid Build Coastguard Worker *size1 = *size2 = 0;
296*288bf522SAndroid Build Coastguard Worker return 0; // No available data.
297*288bf522SAndroid Build Coastguard Worker }
298*288bf522SAndroid Build Coastguard Worker // rmb() used to ensure reading data after reading aux_head.
299*288bf522SAndroid Build Coastguard Worker __sync_synchronize();
300*288bf522SAndroid Build Coastguard Worker size_t data_pos = read_head & (aux_buffer_size_ - 1);
301*288bf522SAndroid Build Coastguard Worker size_t data_size = write_head - read_head;
302*288bf522SAndroid Build Coastguard Worker *buf1 = aux_buffer_ + data_pos;
303*288bf522SAndroid Build Coastguard Worker if (data_size <= aux_buffer_size_ - data_pos) {
304*288bf522SAndroid Build Coastguard Worker *size1 = data_size;
305*288bf522SAndroid Build Coastguard Worker *size2 = 0;
306*288bf522SAndroid Build Coastguard Worker } else {
307*288bf522SAndroid Build Coastguard Worker *size1 = aux_buffer_size_ - data_pos;
308*288bf522SAndroid Build Coastguard Worker *buf2 = aux_buffer_;
309*288bf522SAndroid Build Coastguard Worker *size2 = data_size - *size1;
310*288bf522SAndroid Build Coastguard Worker }
311*288bf522SAndroid Build Coastguard Worker return read_head;
312*288bf522SAndroid Build Coastguard Worker }
313*288bf522SAndroid Build Coastguard Worker
DiscardAuxData(size_t discard_size)314*288bf522SAndroid Build Coastguard Worker void EventFd::DiscardAuxData(size_t discard_size) {
315*288bf522SAndroid Build Coastguard Worker // mb() used to ensure finish reading data before writing aux_tail.
316*288bf522SAndroid Build Coastguard Worker __sync_synchronize();
317*288bf522SAndroid Build Coastguard Worker mmap_metadata_page_->aux_tail += discard_size;
318*288bf522SAndroid Build Coastguard Worker }
319*288bf522SAndroid Build Coastguard Worker
StartPolling(IOEventLoop & loop,const std::function<bool ()> & callback)320*288bf522SAndroid Build Coastguard Worker bool EventFd::StartPolling(IOEventLoop& loop, const std::function<bool()>& callback) {
321*288bf522SAndroid Build Coastguard Worker ioevent_ref_ = loop.AddReadEvent(perf_event_fd_, callback);
322*288bf522SAndroid Build Coastguard Worker return ioevent_ref_ != nullptr;
323*288bf522SAndroid Build Coastguard Worker }
324*288bf522SAndroid Build Coastguard Worker
StopPolling()325*288bf522SAndroid Build Coastguard Worker bool EventFd::StopPolling() {
326*288bf522SAndroid Build Coastguard Worker return IOEventLoop::DelEvent(ioevent_ref_);
327*288bf522SAndroid Build Coastguard Worker }
328*288bf522SAndroid Build Coastguard Worker
IsEventAttrSupported(const perf_event_attr & attr,const std::string & event_name)329*288bf522SAndroid Build Coastguard Worker bool IsEventAttrSupported(const perf_event_attr& attr, const std::string& event_name) {
330*288bf522SAndroid Build Coastguard Worker return EventFd::OpenEventFile(attr, getpid(), -1, nullptr, event_name, false) != nullptr;
331*288bf522SAndroid Build Coastguard Worker }
332*288bf522SAndroid Build Coastguard Worker
333*288bf522SAndroid Build Coastguard Worker } // namespace simpleperf
334