Imported Upstream version 1.0.0
[platform/upstream/oprofile.git] / libperf_events / operf_counter.h
1 /**
2  * @file libperf_events/operf_counter.h
3  * C++ class definition that abstracts the user-to-kernel interface
4  * for using Linux Performance Events Subsystem.
5  *
6  * @remark Copyright 2011 OProfile authors
7  * @remark Read the file COPYING
8  *
9  * Created on: Dec 7, 2011
10  * @author Maynard Johnson
11  * (C) Copyright IBM Corp. 2011
12  *
13  * Modified by Maynard Johnson <maynardj@us.ibm.com>
14  * (C) Copyright IBM Corporation 2012, 2014
15  *
16  */
17
18 #ifndef OPERF_COUNTER_H_
19 #define OPERF_COUNTER_H_
20
21 #include <sys/mman.h>
22 #include <unistd.h>
23 #include <sys/syscall.h>
24 #include <stdint.h>
25 #include <poll.h>
26 #include <string>
27 #include <vector>
28 #include <map>
29 #include <stdexcept>
30 #include <limits.h>
31 #include <istream>
32 #include <fstream>
33 #include "operf_event.h"
34 #include "op_cpu_type.h"
35 #include "operf_utils.h"
36
37 extern char * start_time_human_readable;
38
39 class operf_record;
40
41 #define OP_BASIC_SAMPLE_FORMAT (PERF_SAMPLE_ID | PERF_SAMPLE_IP \
42     | PERF_SAMPLE_TID)
43
44 static inline int
45 op_perf_event_open(struct perf_event_attr * attr,
46                       pid_t pid, int cpu, int group_fd,
47                       unsigned long flags)
48 {
49         return syscall(__NR_perf_event_open, attr, pid, cpu,
50                                group_fd, flags);
51 }
52
53 #define OP_PERF_HANDLED_ERROR -101
54 #define OP_PERF_NO_SAMPLE_ID 0xdeadbeefdeadbeefULL
55
56
57 class operf_counter {
58 public:
59         operf_counter(operf_event_t & evt, bool enable_on_exec, bool callgraph,
60                       bool separate_by_cpu, bool inherit, int event_number);
61         ~operf_counter();
62         int perf_event_open(pid_t pid, int cpu, operf_record * pr, bool print_error);
63         const struct perf_event_attr * the_attr(void) const { return &attr; }
64         int get_fd(void) const { return fd; }
65         int get_id(void) const { return id; }
66         int get_evt_num(void) const { return evt_num; }
67         const std::string get_event_name(void) const { return event_name; }
68
69 private:
70         struct perf_event_attr attr;
71         int fd;
72         int id;
73         int evt_num;
74         std::string event_name;
75 };
76
77
78 class operf_record {
79 public:
80         /* For system-wide profiling, set sys_wide=true, the_pid=-1, and pid_running=false.
81          * For single app profiling, set sys_wide=false, the_pid=<processID-to-profile>,
82          * and pid_running=true if profiling an already active process; otherwise false.
83          */
84         operf_record(int output_fd, bool sys_wide, pid_t the_pid, bool pid_running,
85                      std::vector<operf_event_t> & evts, OP_perf_utils::vmlinux_info_t vi,
86                      bool callgraph, bool separate_by_cpu, bool output_fd_is_file,
87                      int _convert_read_pipe, int _convert_write_pipe);
88         ~operf_record();
89         void recordPerfData(void);
90         int out_fd(void) const { return output_fd; }
91         void add_to_total(int n) { total_bytes_recorded += n; }
92         void add_process(struct comm_event proc) { procs[proc.tid] = proc; }
93         unsigned int get_total_bytes_recorded(void) const { return total_bytes_recorded; }
94         void register_perf_event_id(unsigned counter, u64 id, perf_event_attr evt_attr);
95         bool get_valid(void) { return valid; }
96
97 private:
98         void create(std::string outfile, std::vector<operf_event_t> & evts);
99         void setup(void);
100         int prepareToRecord(void);
101         int _prepare_to_record_one_fd(int idx, int fd);
102         int _start_recoding_new_thread(pid_t id);
103         void record_process_info(void);
104         void write_op_header_info(void);
105         int _write_header_to_file(void);
106         int _write_header_to_pipe(void);
107         int output_fd;
108         int read_comm_pipe;
109         int write_comm_pipe;
110         bool write_to_file;
111         // Array of size 'num_cpus_used_for_perf_event_open * num_pids * num_events'
112         struct pollfd * poll_data;
113         std::vector<struct mmap_data> samples_array;
114         int num_cpus;
115         pid_t pid_to_profile;
116         /* When doing --pid or --system-wide profiling, we'll obtain process information
117          * for all processes to be profiled (including forked/cloned processes) and store
118          * that information in a collection of type 'comm_event'.  We'll use this collection
119          * for synthesizing PERF_RECORD_COMM events into the profile data stream.
120          */
121         std::map<u32, struct comm_event> procs;
122         bool pid_started;
123         bool system_wide;
124         bool callgraph;
125         bool separate_cpu;
126         std::vector<operf_counter> perfCounters;
127         unsigned int total_bytes_recorded;
128         int poll_count;
129         struct OP_header opHeader;
130         std::vector<operf_event_t> evts;
131         bool valid;
132         std::string vmlinux_file;
133         u64 kernel_start, kernel_end;
134 };
135
136 class operf_read {
137 public:
138         operf_read(std::vector<operf_event_t> & _evts)
139         : sample_data_fd(-1), inputFname(""), evts(_evts), cpu_type(CPU_NO_GOOD)
140           { valid = syswide = false;
141           write_comm_pipe = read_comm_pipe = 1;
142           post_profiling_pipe = -1; }
143         void init(int sample_data_pipe_fd, std::string input_filename, std::string samples_dir, op_cpu cputype,
144                   bool systemwide, int _record_write_pipe, int _record_read_pipe,
145                   int _post_profiling_pipe);
146         ~operf_read();
147         int readPerfHeader(void);
148         unsigned int convertPerfData(void);
149         bool is_valid(void) {return valid; }
150         int get_eventnum_by_perf_event_id(u64 id) const;
151         inline const operf_event_t * get_event_by_counter(u32 counter) { return &evts[counter]; }
152         int get_write_comm_pipe(void) { return write_comm_pipe; }
153         int get_read_comm_pipe(void)  { return read_comm_pipe; }
154         void add_sample_id_to_opHeader(u64 sample_id);
155
156 private:
157         int sample_data_fd;
158         int write_comm_pipe;
159         int read_comm_pipe;
160         int post_profiling_pipe;
161         std::string inputFname;
162         std::string sampledir;
163         std::ifstream istrm;
164         struct OP_header opHeader;
165         std::vector<operf_event_t> & evts;
166         bool valid;
167         bool syswide;
168         op_cpu cpu_type;
169         int _read_header_info_with_ifstream(void);
170         int _read_perf_header_from_file(void);
171         int _read_perf_header_from_pipe(void);
172 };
173
174
175 #endif /* OPERF_COUNTER_H_ */