3737 */
3838static LIST_HEAD (core_pmus );
3939static 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 ;
4257
43- static void pmu_read_sysfs (bool core_only );
58+ static void pmu_read_sysfs (unsigned int to_read_pmus );
4459
4560size_t pmu_name_len_no_suffix (const char * str )
4661{
@@ -102,8 +117,7 @@ void perf_pmus__destroy(void)
102117
103118 perf_pmu__delete (pmu );
104119 }
105- read_sysfs_core_pmus = false;
106- read_sysfs_all_pmus = false;
120+ read_pmu_types = 0 ;
107121}
108122
109123static struct perf_pmu * pmu_find (const char * name )
@@ -129,6 +143,7 @@ struct perf_pmu *perf_pmus__find(const char *name)
129143 struct perf_pmu * pmu ;
130144 int dirfd ;
131145 bool core_pmu ;
146+ unsigned int to_read_pmus = 0 ;
132147
133148 /*
134149 * Once PMU is loaded it stays in the list,
@@ -139,27 +154,39 @@ struct perf_pmu *perf_pmus__find(const char *name)
139154 if (pmu )
140155 return pmu ;
141156
142- if (read_sysfs_all_pmus )
157+ if (read_pmu_types == PERF_TOOL_PMU_TYPE_ALL_MASK )
143158 return NULL ;
144159
145160 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 ) )
147162 return NULL ;
148163
149164 dirfd = perf_pmu__event_source_devices_fd ();
150165 pmu = perf_pmu__lookup (core_pmu ? & core_pmus : & other_pmus , dirfd , name ,
151166 /*eager_load=*/ false);
152167 close (dirfd );
153168
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 );
160180 pmu = pmu_find (name );
181+ if (pmu )
182+ return pmu ;
161183 }
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 );
163190}
164191
165192static 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)
176203 if (pmu )
177204 return pmu ;
178205
179- if (read_sysfs_all_pmus )
206+ if (read_pmu_types == PERF_TOOL_PMU_TYPE_ALL_MASK )
180207 return NULL ;
181208
182209 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 ) )
184211 return NULL ;
185212
186213 return perf_pmu__lookup (core_pmu ? & core_pmus : & other_pmus , dirfd , name ,
@@ -197,52 +224,60 @@ static int pmus_cmp(void *priv __maybe_unused,
197224}
198225
199226/* 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 )
201228{
202- int fd ;
203- DIR * dir ;
204- struct dirent * dent ;
205229 struct perf_pmu * tool_pmu ;
206230
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. */
208233 return ;
234+ }
209235
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 ;
213241
214- dir = fdopendir (fd );
215- if (!dir ) {
216- close (fd );
217- return ;
218- }
242+ if (fd < 0 )
243+ goto skip_pe_pmus ;
219244
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+ }
228250
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 )) {
231264 if (!perf_pmu__create_placeholder_core_pmu (& core_pmus ))
232265 pr_err ("Failure to set up any core PMUs\n" );
233266 }
234267 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 ) {
236271 tool_pmu = perf_pmus__tool_pmu ();
237272 list_add_tail (& tool_pmu -> list , & other_pmus );
238- perf_pmus__read_hwmon_pmus (& other_pmus );
239273 }
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+
240278 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 ;
246281}
247282
248283static 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)
263298
264299struct perf_pmu * perf_pmus__find_by_type (unsigned int type )
265300{
301+ unsigned int to_read_pmus ;
266302 struct perf_pmu * pmu = __perf_pmus__find_by_type (type );
267303
268- if (pmu || read_sysfs_all_pmus )
304+ if (pmu || ( read_pmu_types == PERF_TOOL_PMU_TYPE_ALL_MASK ) )
269305 return pmu ;
270306
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 );
272316 pmu = __perf_pmus__find_by_type (type );
273317 return pmu ;
274318}
@@ -282,7 +326,7 @@ struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu)
282326 bool use_core_pmus = !pmu || pmu -> is_core ;
283327
284328 if (!pmu ) {
285- pmu_read_sysfs (/*core_only=*/ false );
329+ pmu_read_sysfs (PERF_TOOL_PMU_TYPE_ALL_MASK );
286330 pmu = list_prepare_entry (pmu , & core_pmus , list );
287331 }
288332 if (use_core_pmus ) {
@@ -300,7 +344,7 @@ struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu)
300344struct perf_pmu * perf_pmus__scan_core (struct perf_pmu * pmu )
301345{
302346 if (!pmu ) {
303- pmu_read_sysfs (/*core_only=*/ true );
347+ pmu_read_sysfs (PERF_TOOL_PMU_TYPE_PE_CORE_MASK );
304348 return list_first_entry_or_null (& core_pmus , typeof (* pmu ), list );
305349 }
306350 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)
316360 const char * last_pmu_name = (pmu && pmu -> name ) ? pmu -> name : "" ;
317361
318362 if (!pmu ) {
319- pmu_read_sysfs (/*core_only=*/ false );
363+ pmu_read_sysfs (PERF_TOOL_PMU_TYPE_ALL_MASK );
320364 pmu = list_prepare_entry (pmu , & core_pmus , list );
321365 } else
322366 last_pmu_name_len = pmu_name_len_no_suffix (pmu -> name ?: "" );
0 commit comments