21
21
22
22
#pragma once
23
23
24
+ #include < lo2s/config.hpp>
25
+ #include < lo2s/error.hpp>
24
26
#include < lo2s/execution_scope.hpp>
27
+ #include < lo2s/perf/util.hpp>
25
28
#include < lo2s/topology.hpp>
26
29
27
30
#include < set>
@@ -48,16 +51,54 @@ struct EventDescription
48
51
{
49
52
EventDescription (const std::string& name, perf_type_id type, std::uint64_t config,
50
53
std::uint64_t config1 = 0 , std::set<Cpu> cpus = std::set<Cpu>(),
51
- double scale = 1 , std::string unit = " #" ,
52
- Availability availability = Availability::UNAVAILABLE)
53
- : name(name), type(type), config(config), config1(config1), scale(scale), unit(unit),
54
- availability (availability), cpus_(cpus)
54
+ double scale = 1 , std::string unit = " #" )
55
+ : name_(name), type_(type), config_(config), config1_(config1), scale_(scale), unit_(unit),
56
+ cpus_ (cpus)
55
57
{
58
+ struct perf_event_attr attr = perf_event_attr ();
59
+
60
+ int proc_fd = perf_event_open (&attr, ExecutionScope (Thread (0 )), -1 , 0 );
61
+ int sys_fd = perf_event_open (&attr, ExecutionScope (*supported_cpus ().begin ()), -1 , 0 );
62
+
63
+ if (sys_fd == -1 && proc_fd == -1 )
64
+ {
65
+ attr.exclude_kernel = 1 ;
66
+ proc_fd = perf_event_open (&attr, ExecutionScope (Thread (0 )), -1 , 0 );
67
+ sys_fd = perf_event_open (&attr, ExecutionScope (*supported_cpus ().begin ()), -1 , 0 );
68
+ }
69
+
70
+ if (sys_fd == -1 && proc_fd == -1 )
71
+ {
72
+ switch (errno)
73
+ {
74
+ case ENOTSUP:
75
+ Log::debug () << " perf event not supported by the running kernel: " << name_;
76
+ break ;
77
+ default :
78
+ Log::debug () << " perf event " << name_
79
+ << " not available: " << std::string (std::strerror (errno));
80
+ break ;
81
+ }
82
+
83
+ availability_ = Availability::UNAVAILABLE;
84
+ }
85
+ else if (sys_fd == -1 )
86
+ {
87
+ availability_ = Availability::PROCESS_MODE;
88
+ }
89
+ else if (proc_fd == -1 )
90
+ {
91
+ availability_ = Availability::SYSTEM_MODE;
92
+ }
93
+ else
94
+ {
95
+ availability_ = Availability::UNIVERSAL;
96
+ }
56
97
}
57
98
58
99
EventDescription ()
59
- : name (" " ), type (static_cast <perf_type_id>(-1 )), config (0 ), config1 (0 ), scale( 1 ), unit( " # " ),
60
- availability (Availability::UNAVAILABLE)
100
+ : name_ (" " ), type_ (static_cast <perf_type_id>(-1 )), config_ (0 ), config1_ (0 ), scale_( 1 ),
101
+ unit_( " # " ), availability_ (Availability::UNAVAILABLE)
61
102
{
62
103
}
63
104
@@ -79,30 +120,106 @@ struct EventDescription
79
120
80
121
friend bool operator ==(const EventDescription& lhs, const EventDescription& rhs)
81
122
{
82
- return (lhs.type == rhs.type ) && (lhs.config == rhs.config ) && (lhs.config1 == rhs.config1 );
123
+ return (lhs.type_ == rhs.type_ ) && (lhs.config_ == rhs.config_ ) &&
124
+ (lhs.config1_ == rhs.config1_ );
83
125
}
84
126
85
127
friend bool operator <(const EventDescription& lhs, const EventDescription& rhs)
86
128
{
87
- if (lhs.type == rhs.type )
129
+ if (lhs.type_ == rhs.type_ )
88
130
{
89
- if (lhs.config == rhs.config )
131
+ if (lhs.config_ == rhs.config_ )
90
132
{
91
- return lhs.config1 < rhs.config1 ;
133
+ return lhs.config1_ < rhs.config1_ ;
92
134
}
93
- return lhs.config < rhs.config ;
135
+ return lhs.config_ < rhs.config_ ;
136
+ }
137
+ return lhs.type_ < rhs.type_ ;
138
+ }
139
+
140
+ struct perf_event_attr perf_event_attr () const
141
+ {
142
+ struct perf_event_attr attr;
143
+ memset (&attr, 0 , sizeof (struct perf_event_attr ));
144
+
145
+ attr.size = sizeof (struct perf_event_attr );
146
+
147
+ attr.type = type_;
148
+ attr.config = config_;
149
+ attr.config1 = config1_;
150
+
151
+ return attr;
152
+ }
153
+
154
+ std::string name () const
155
+ {
156
+ return name_;
157
+ }
158
+
159
+ std::string description () const
160
+ {
161
+ if (availability_ == Availability::UNIVERSAL)
162
+ {
163
+ return name_;
164
+ }
165
+ else if (availability_ == Availability::SYSTEM_MODE)
166
+ {
167
+ return fmt::format (" {} [SYS]" , name_);
168
+ }
169
+ else if (availability_ == Availability::PROCESS_MODE)
170
+ {
171
+ return fmt::format (" {} [PROC]" , name_);
172
+ }
173
+
174
+ return " " ;
175
+ }
176
+
177
+ bool is_valid () const
178
+ {
179
+ return availability_ != Availability::UNAVAILABLE;
180
+ }
181
+
182
+ double scale () const
183
+ {
184
+ return scale_;
185
+ }
186
+
187
+ std::string unit () const
188
+ {
189
+ return unit_;
190
+ }
191
+
192
+ int open_counter (ExecutionScope scope, int group_fd)
193
+ {
194
+ struct perf_event_attr perf_attr = perf_event_attr ();
195
+ perf_attr.sample_period = 0 ;
196
+ perf_attr.exclude_kernel = config ().exclude_kernel ;
197
+ // Needed when scaling multiplexed events, and recognize activation phases
198
+ perf_attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING;
199
+
200
+ #if !defined(USE_HW_BREAKPOINT_COMPAT) && defined(USE_PERF_CLOCKID)
201
+ perf_attr.use_clockid = config ().use_clockid ;
202
+ perf_attr.clockid = config ().clockid ;
203
+ #endif
204
+
205
+ int fd = perf_try_event_open (&perf_attr, scope, group_fd, 0 , config ().cgroup_fd );
206
+ if (fd < 0 )
207
+ {
208
+ Log::error () << " perf_event_open for counter failed" ;
209
+ throw_errno ();
94
210
}
95
- return lhs. type < rhs. type ;
211
+ return fd ;
96
212
}
97
- std::string name;
98
- perf_type_id type;
99
- std::uint64_t config;
100
- std::uint64_t config1;
101
- double scale;
102
- std::string unit;
103
- Availability availability;
104
213
105
214
private:
215
+ std::string name_;
216
+ perf_type_id type_;
217
+ std::uint64_t config_;
218
+ std::uint64_t config1_;
219
+ double scale_;
220
+ std::string unit_;
221
+ Availability availability_;
222
+
106
223
std::set<Cpu> cpus_;
107
224
};
108
225
} // namespace perf
0 commit comments