summaryrefslogtreecommitdiff
path: root/simpleperf/event_fd.h
blob: e4e20ce4738f135a55b9bbb32e0b37bdf87181d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SIMPLE_PERF_EVENT_FD_H_
#define SIMPLE_PERF_EVENT_FD_H_

#include <sys/types.h>

#include <memory>
#include <string>
#include <vector>

#include <android-base/macros.h>

#include "IOEventLoop.h"
#include "perf_event.h"

struct PerfCounter {
  uint64_t value;  // The value of the event specified by the perf_event_file.
  uint64_t time_enabled;  // The enabled time.
  uint64_t time_running;  // The running time.
  uint64_t id;            // The id of the perf_event_file.
};

// EventFd represents an opened perf_event_file.
class EventFd {
 public:
  static std::unique_ptr<EventFd> OpenEventFile(const perf_event_attr& attr,
                                                pid_t tid, int cpu,
                                                EventFd* group_event_fd,
                                                bool report_error = true);

  virtual ~EventFd();

  // Give information about this perf_event_file, like (event_name, tid, cpu).
  std::string Name() const;

  uint64_t Id() const;

  pid_t ThreadId() const { return tid_; }

  int Cpu() const { return cpu_; }

  const perf_event_attr& attr() const { return attr_; }

  // It tells the kernel to start counting and recording events specified by
  // this file.
  bool SetEnableEvent(bool enable);

  bool ReadCounter(PerfCounter* counter);

  // Create mapped buffer used to receive records sent by the kernel.
  // mmap_pages should be power of 2.
  virtual bool CreateMappedBuffer(size_t mmap_pages, bool report_error);

  // Share the mapped buffer used by event_fd. The two EventFds should monitor
  // the same event on the same cpu, but have different thread ids.
  bool ShareMappedBuffer(const EventFd& event_fd, bool report_error);

  bool HasMappedBuffer() const { return mmap_data_buffer_size_ != 0; }
  char* GetMappedBuffer(size_t& buffer_size) {
    buffer_size = mmap_data_buffer_size_;
    return mmap_data_buffer_;
  }

  virtual void DestroyMappedBuffer();

  // Return available data in the kernel buffer.
  std::vector<char> GetAvailableMmapData();
  // Return the size of available data in the buffer, and set data_pos to the first available data
  // position in mmap_data_buffer_.
  virtual size_t GetAvailableMmapDataSize(size_t& data_pos);
  // Discard the size of the data we have read, so the kernel can reuse the space for new data.
  virtual void DiscardMmapData(size_t discard_size);

  // [callback] is called when there is data available in the mapped buffer.
  virtual bool StartPolling(IOEventLoop& loop, const std::function<bool()>& callback);
  virtual bool StopPolling();

 protected:
  EventFd(const perf_event_attr& attr, int perf_event_fd,
          const std::string& event_name, pid_t tid, int cpu)
      : attr_(attr),
        perf_event_fd_(perf_event_fd),
        id_(0),
        event_name_(event_name),
        tid_(tid),
        cpu_(cpu),
        mmap_addr_(nullptr),
        mmap_len_(0),
        mmap_metadata_page_(nullptr),
        mmap_data_buffer_(nullptr),
        mmap_data_buffer_size_(0),
        ioevent_ref_(nullptr),
        last_counter_value_(0) {}

  bool InnerReadCounter(PerfCounter* counter) const;

  const perf_event_attr attr_;
  int perf_event_fd_;
  mutable uint64_t id_;
  const std::string event_name_;
  pid_t tid_;
  int cpu_;

  void* mmap_addr_;
  size_t mmap_len_;
  perf_event_mmap_page* mmap_metadata_page_;  // The first page of mmap_area.
  char* mmap_data_buffer_;  // Starting from the second page of mmap_area,
                            // containing records written by then kernel.
  size_t mmap_data_buffer_size_;

  IOEventRef ioevent_ref_;

  // Used by atrace to generate value difference between two ReadCounter() calls.
  uint64_t last_counter_value_;

  DISALLOW_COPY_AND_ASSIGN(EventFd);
};

bool IsEventAttrSupported(const perf_event_attr& attr);

#endif  // SIMPLE_PERF_EVENT_FD_H_