37
37
*/
38
38
static LIST_HEAD (core_pmus );
39
39
static LIST_HEAD (other_pmus );
40
- static bool read_sysfs_core_pmus ;
41
- static bool read_sysfs_all_pmus ;
40
+ enum perf_tool_pmu_type {
41
+ PERF_TOOL_PMU_TYPE_PE_CORE ,
42
+ PERF_TOOL_PMU_TYPE_PE_OTHER ,
43
+ PERF_TOOL_PMU_TYPE_TOOL ,
44
+ PERF_TOOL_PMU_TYPE_HWMON ,
45
+
46
+ #define PERF_TOOL_PMU_TYPE_PE_CORE_MASK (1 << PERF_TOOL_PMU_TYPE_PE_CORE)
47
+ #define PERF_TOOL_PMU_TYPE_PE_OTHER_MASK (1 << PERF_TOOL_PMU_TYPE_PE_OTHER )
48
+ #define PERF_TOOL_PMU_TYPE_TOOL_MASK (1 << PERF_TOOL_PMU_TYPE_TOOL )
49
+ #define PERF_TOOL_PMU_TYPE_HWMON_MASK (1 << PERF_TOOL_PMU_TYPE_HWMON )
50
+
51
+ #define PERF_TOOL_PMU_TYPE_ALL_MASK (PERF_TOOL_PMU_TYPE_PE_CORE_MASK | \
52
+ PERF_TOOL_PMU_TYPE_PE_OTHER_MASK | \
53
+ PERF_TOOL_PMU_TYPE_TOOL_MASK | \
54
+ PERF_TOOL_PMU_TYPE_HWMON_MASK )
55
+ };
56
+ static unsigned int read_pmu_types ;
42
57
43
- static void pmu_read_sysfs (bool core_only );
58
+ static void pmu_read_sysfs (unsigned int to_read_pmus );
44
59
45
60
size_t pmu_name_len_no_suffix (const char * str )
46
61
{
@@ -102,8 +117,7 @@ void perf_pmus__destroy(void)
102
117
103
118
perf_pmu__delete (pmu );
104
119
}
105
- read_sysfs_core_pmus = false;
106
- read_sysfs_all_pmus = false;
120
+ read_pmu_types = 0 ;
107
121
}
108
122
109
123
static struct perf_pmu * pmu_find (const char * name )
@@ -129,6 +143,7 @@ struct perf_pmu *perf_pmus__find(const char *name)
129
143
struct perf_pmu * pmu ;
130
144
int dirfd ;
131
145
bool core_pmu ;
146
+ unsigned int to_read_pmus = 0 ;
132
147
133
148
/*
134
149
* Once PMU is loaded it stays in the list,
@@ -139,27 +154,39 @@ struct perf_pmu *perf_pmus__find(const char *name)
139
154
if (pmu )
140
155
return pmu ;
141
156
142
- if (read_sysfs_all_pmus )
157
+ if (read_pmu_types == PERF_TOOL_PMU_TYPE_ALL_MASK )
143
158
return NULL ;
144
159
145
160
core_pmu = is_pmu_core (name );
146
- if (core_pmu && read_sysfs_core_pmus )
161
+ if (core_pmu && ( read_pmu_types & PERF_TOOL_PMU_TYPE_PE_CORE_MASK ) )
147
162
return NULL ;
148
163
149
164
dirfd = perf_pmu__event_source_devices_fd ();
150
165
pmu = perf_pmu__lookup (core_pmu ? & core_pmus : & other_pmus , dirfd , name ,
151
166
/*eager_load=*/ false);
152
167
close (dirfd );
153
168
154
- if (!pmu ) {
155
- /*
156
- * Looking up an inidividual PMU failed. This may mean name is
157
- * an alias, so read the PMUs from sysfs and try to find again.
158
- */
159
- pmu_read_sysfs (core_pmu );
169
+ if (pmu )
170
+ return pmu ;
171
+
172
+ /* Looking up an individual perf event PMU failed, check if a tool PMU should be read. */
173
+ if (!strncmp (name , "hwmon_" , 6 ))
174
+ to_read_pmus |= PERF_TOOL_PMU_TYPE_HWMON_MASK ;
175
+ else if (!strcmp (name , "tool" ))
176
+ to_read_pmus |= PERF_TOOL_PMU_TYPE_TOOL_MASK ;
177
+
178
+ if (to_read_pmus ) {
179
+ pmu_read_sysfs (to_read_pmus );
160
180
pmu = pmu_find (name );
181
+ if (pmu )
182
+ return pmu ;
161
183
}
162
- return pmu ;
184
+ /* Read all necessary PMUs from sysfs and see if the PMU is found. */
185
+ to_read_pmus = PERF_TOOL_PMU_TYPE_PE_CORE_MASK ;
186
+ if (!core_pmu )
187
+ to_read_pmus |= PERF_TOOL_PMU_TYPE_PE_OTHER_MASK ;
188
+ pmu_read_sysfs (to_read_pmus );
189
+ return pmu_find (name );
163
190
}
164
191
165
192
static struct perf_pmu * perf_pmu__find2 (int dirfd , const char * name )
@@ -176,11 +203,11 @@ static struct perf_pmu *perf_pmu__find2(int dirfd, const char *name)
176
203
if (pmu )
177
204
return pmu ;
178
205
179
- if (read_sysfs_all_pmus )
206
+ if (read_pmu_types == PERF_TOOL_PMU_TYPE_ALL_MASK )
180
207
return NULL ;
181
208
182
209
core_pmu = is_pmu_core (name );
183
- if (core_pmu && read_sysfs_core_pmus )
210
+ if (core_pmu && ( read_pmu_types & PERF_TOOL_PMU_TYPE_PE_CORE_MASK ) )
184
211
return NULL ;
185
212
186
213
return perf_pmu__lookup (core_pmu ? & core_pmus : & other_pmus , dirfd , name ,
@@ -197,52 +224,60 @@ static int pmus_cmp(void *priv __maybe_unused,
197
224
}
198
225
199
226
/* Add all pmus in sysfs to pmu list: */
200
- static void pmu_read_sysfs (bool core_only )
227
+ static void pmu_read_sysfs (unsigned int to_read_types )
201
228
{
202
- int fd ;
203
- DIR * dir ;
204
- struct dirent * dent ;
205
229
struct perf_pmu * tool_pmu ;
206
230
207
- if (read_sysfs_all_pmus || (core_only && read_sysfs_core_pmus ))
231
+ if ((read_pmu_types & to_read_types ) == to_read_types ) {
232
+ /* All requested PMU types have been read. */
208
233
return ;
234
+ }
209
235
210
- fd = perf_pmu__event_source_devices_fd ();
211
- if (fd < 0 )
212
- return ;
236
+ if (to_read_types & (PERF_TOOL_PMU_TYPE_PE_CORE_MASK | PERF_TOOL_PMU_TYPE_PE_OTHER_MASK )) {
237
+ int fd = perf_pmu__event_source_devices_fd ();
238
+ DIR * dir ;
239
+ struct dirent * dent ;
240
+ bool core_only = (to_read_types & PERF_TOOL_PMU_TYPE_PE_OTHER_MASK ) == 0 ;
213
241
214
- dir = fdopendir (fd );
215
- if (!dir ) {
216
- close (fd );
217
- return ;
218
- }
242
+ if (fd < 0 )
243
+ goto skip_pe_pmus ;
219
244
220
- while ((dent = readdir (dir ))) {
221
- if (!strcmp (dent -> d_name , "." ) || !strcmp (dent -> d_name , ".." ))
222
- continue ;
223
- if (core_only && !is_pmu_core (dent -> d_name ))
224
- continue ;
225
- /* add to static LIST_HEAD(core_pmus) or LIST_HEAD(other_pmus): */
226
- perf_pmu__find2 (fd , dent -> d_name );
227
- }
245
+ dir = fdopendir (fd );
246
+ if (!dir ) {
247
+ close (fd );
248
+ goto skip_pe_pmus ;
249
+ }
228
250
229
- closedir (dir );
230
- if (list_empty (& core_pmus )) {
251
+ while ((dent = readdir (dir ))) {
252
+ if (!strcmp (dent -> d_name , "." ) || !strcmp (dent -> d_name , ".." ))
253
+ continue ;
254
+ if (core_only && !is_pmu_core (dent -> d_name ))
255
+ continue ;
256
+ /* add to static LIST_HEAD(core_pmus) or LIST_HEAD(other_pmus): */
257
+ perf_pmu__find2 (fd , dent -> d_name );
258
+ }
259
+
260
+ closedir (dir );
261
+ }
262
+ skip_pe_pmus :
263
+ if ((to_read_types & PERF_TOOL_PMU_TYPE_PE_CORE_MASK ) && list_empty (& core_pmus )) {
231
264
if (!perf_pmu__create_placeholder_core_pmu (& core_pmus ))
232
265
pr_err ("Failure to set up any core PMUs\n" );
233
266
}
234
267
list_sort (NULL , & core_pmus , pmus_cmp );
235
- if (!core_only ) {
268
+
269
+ if ((to_read_types & PERF_TOOL_PMU_TYPE_TOOL_MASK ) != 0 &&
270
+ (read_pmu_types & PERF_TOOL_PMU_TYPE_TOOL_MASK ) == 0 ) {
236
271
tool_pmu = perf_pmus__tool_pmu ();
237
272
list_add_tail (& tool_pmu -> list , & other_pmus );
238
- perf_pmus__read_hwmon_pmus (& other_pmus );
239
273
}
274
+ if ((to_read_types & PERF_TOOL_PMU_TYPE_HWMON_MASK ) != 0 &&
275
+ (read_pmu_types & PERF_TOOL_PMU_TYPE_HWMON_MASK ) == 0 )
276
+ perf_pmus__read_hwmon_pmus (& other_pmus );
277
+
240
278
list_sort (NULL , & other_pmus , pmus_cmp );
241
- if (!list_empty (& core_pmus )) {
242
- read_sysfs_core_pmus = true;
243
- if (!core_only )
244
- read_sysfs_all_pmus = true;
245
- }
279
+
280
+ read_pmu_types |= to_read_types ;
246
281
}
247
282
248
283
static struct perf_pmu * __perf_pmus__find_by_type (unsigned int type )
@@ -263,12 +298,21 @@ static struct perf_pmu *__perf_pmus__find_by_type(unsigned int type)
263
298
264
299
struct perf_pmu * perf_pmus__find_by_type (unsigned int type )
265
300
{
301
+ unsigned int to_read_pmus ;
266
302
struct perf_pmu * pmu = __perf_pmus__find_by_type (type );
267
303
268
- if (pmu || read_sysfs_all_pmus )
304
+ if (pmu || ( read_pmu_types == PERF_TOOL_PMU_TYPE_ALL_MASK ) )
269
305
return pmu ;
270
306
271
- pmu_read_sysfs (/*core_only=*/ false);
307
+ if (type >= PERF_PMU_TYPE_PE_START && type <= PERF_PMU_TYPE_PE_END ) {
308
+ to_read_pmus = PERF_TOOL_PMU_TYPE_PE_CORE_MASK |
309
+ PERF_TOOL_PMU_TYPE_PE_OTHER_MASK ;
310
+ } else if (type >= PERF_PMU_TYPE_HWMON_START && type <= PERF_PMU_TYPE_HWMON_END ) {
311
+ to_read_pmus = PERF_TOOL_PMU_TYPE_HWMON_MASK ;
312
+ } else {
313
+ to_read_pmus = PERF_TOOL_PMU_TYPE_TOOL_MASK ;
314
+ }
315
+ pmu_read_sysfs (to_read_pmus );
272
316
pmu = __perf_pmus__find_by_type (type );
273
317
return pmu ;
274
318
}
@@ -282,7 +326,7 @@ struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu)
282
326
bool use_core_pmus = !pmu || pmu -> is_core ;
283
327
284
328
if (!pmu ) {
285
- pmu_read_sysfs (/*core_only=*/ false );
329
+ pmu_read_sysfs (PERF_TOOL_PMU_TYPE_ALL_MASK );
286
330
pmu = list_prepare_entry (pmu , & core_pmus , list );
287
331
}
288
332
if (use_core_pmus ) {
@@ -300,7 +344,7 @@ struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu)
300
344
struct perf_pmu * perf_pmus__scan_core (struct perf_pmu * pmu )
301
345
{
302
346
if (!pmu ) {
303
- pmu_read_sysfs (/*core_only=*/ true );
347
+ pmu_read_sysfs (PERF_TOOL_PMU_TYPE_PE_CORE_MASK );
304
348
return list_first_entry_or_null (& core_pmus , typeof (* pmu ), list );
305
349
}
306
350
list_for_each_entry_continue (pmu , & core_pmus , list )
@@ -316,7 +360,7 @@ static struct perf_pmu *perf_pmus__scan_skip_duplicates(struct perf_pmu *pmu)
316
360
const char * last_pmu_name = (pmu && pmu -> name ) ? pmu -> name : "" ;
317
361
318
362
if (!pmu ) {
319
- pmu_read_sysfs (/*core_only=*/ false );
363
+ pmu_read_sysfs (PERF_TOOL_PMU_TYPE_ALL_MASK );
320
364
pmu = list_prepare_entry (pmu , & core_pmus , list );
321
365
} else
322
366
last_pmu_name_len = pmu_name_len_no_suffix (pmu -> name ?: "" );
0 commit comments