@@ -250,13 +250,34 @@ __add_event(struct list_head *list, int *idx,
250250 struct perf_event_attr * attr ,
251251 bool init_attr ,
252252 const char * name , const char * metric_id , struct perf_pmu * pmu ,
253- struct list_head * config_terms , bool auto_merge_stats ,
253+ struct list_head * config_terms , struct evsel * first_wildcard_match ,
254254 struct perf_cpu_map * cpu_list , u64 alternate_hw_config )
255255{
256256 struct evsel * evsel ;
257257 bool is_pmu_core ;
258258 struct perf_cpu_map * cpus ;
259259
260+ /*
261+ * Ensure the first_wildcard_match's PMU matches that of the new event
262+ * being added. Otherwise try to match with another event further down
263+ * the evlist.
264+ */
265+ if (first_wildcard_match ) {
266+ struct evsel * pos = list_prev_entry (first_wildcard_match , core .node );
267+
268+ first_wildcard_match = NULL ;
269+ list_for_each_entry_continue (pos , list , core .node ) {
270+ if (perf_pmu__name_no_suffix_match (pos -> pmu , pmu -> name )) {
271+ first_wildcard_match = pos ;
272+ break ;
273+ }
274+ if (pos -> pmu -> is_core && (!pmu || pmu -> is_core )) {
275+ first_wildcard_match = pos ;
276+ break ;
277+ }
278+ }
279+ }
280+
260281 if (pmu ) {
261282 is_pmu_core = pmu -> is_core ;
262283 cpus = perf_cpu_map__get (perf_cpu_map__is_empty (cpu_list ) ? pmu -> cpus : cpu_list );
@@ -293,9 +314,9 @@ __add_event(struct list_head *list, int *idx,
293314 evsel -> core .own_cpus = perf_cpu_map__get (cpus );
294315 evsel -> core .requires_cpu = pmu ? pmu -> is_uncore : false;
295316 evsel -> core .is_pmu_core = is_pmu_core ;
296- evsel -> auto_merge_stats = auto_merge_stats ;
297317 evsel -> pmu = pmu ;
298318 evsel -> alternate_hw_config = alternate_hw_config ;
319+ evsel -> first_wildcard_match = first_wildcard_match ;
299320
300321 if (name )
301322 evsel -> name = strdup (name );
@@ -318,7 +339,7 @@ struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr,
318339{
319340 return __add_event (/*list=*/ NULL , & idx , attr , /*init_attr=*/ false, name ,
320341 metric_id , pmu , /*config_terms=*/ NULL ,
321- /*auto_merge_stats =*/ false , /*cpu_list=*/ NULL ,
342+ /*first_wildcard_match =*/ NULL , /*cpu_list=*/ NULL ,
322343 /*alternate_hw_config=*/ PERF_COUNT_HW_MAX );
323344}
324345
@@ -329,7 +350,7 @@ static int add_event(struct list_head *list, int *idx,
329350{
330351 return __add_event (list , idx , attr , /*init_attr*/ true, name , metric_id ,
331352 /*pmu=*/ NULL , config_terms ,
332- /*auto_merge_stats =*/ false , /*cpu_list=*/ NULL ,
353+ /*first_wildcard_match =*/ NULL , /*cpu_list=*/ NULL ,
333354 alternate_hw_config ) ? 0 : - ENOMEM ;
334355}
335356
@@ -454,7 +475,7 @@ bool parse_events__filter_pmu(const struct parse_events_state *parse_state,
454475static int parse_events_add_pmu (struct parse_events_state * parse_state ,
455476 struct list_head * list , struct perf_pmu * pmu ,
456477 const struct parse_events_terms * const_parsed_terms ,
457- bool auto_merge_stats , u64 alternate_hw_config );
478+ struct evsel * first_wildcard_match , u64 alternate_hw_config );
458479
459480int parse_events_add_cache (struct list_head * list , int * idx , const char * name ,
460481 struct parse_events_state * parse_state ,
@@ -466,6 +487,7 @@ int parse_events_add_cache(struct list_head *list, int *idx, const char *name,
466487 const char * metric_id = get_config_metric_id (parsed_terms );
467488 struct perf_cpu_map * cpus = get_config_cpu (parsed_terms );
468489 int ret = 0 ;
490+ struct evsel * first_wildcard_match = NULL ;
469491
470492 while ((pmu = perf_pmus__scan (pmu )) != NULL ) {
471493 LIST_HEAD (config_terms );
@@ -481,10 +503,13 @@ int parse_events_add_cache(struct list_head *list, int *idx, const char *name,
481503 */
482504 ret = parse_events_add_pmu (parse_state , list , pmu ,
483505 parsed_terms ,
484- perf_pmu__auto_merge_stats ( pmu ) ,
506+ first_wildcard_match ,
485507 /*alternate_hw_config=*/ PERF_COUNT_HW_MAX );
486508 if (ret )
487509 goto out_err ;
510+ if (first_wildcard_match == NULL )
511+ first_wildcard_match =
512+ container_of (list -> prev , struct evsel , core .node );
488513 continue ;
489514 }
490515
@@ -515,10 +540,12 @@ int parse_events_add_cache(struct list_head *list, int *idx, const char *name,
515540 }
516541
517542 if (__add_event (list , idx , & attr , /*init_attr*/ true, config_name ?: name ,
518- metric_id , pmu , & config_terms , /*auto_merge_stats=*/ false ,
543+ metric_id , pmu , & config_terms , first_wildcard_match ,
519544 cpus , /*alternate_hw_config=*/ PERF_COUNT_HW_MAX ) == NULL )
520545 ret = - ENOMEM ;
521546
547+ if (first_wildcard_match == NULL )
548+ first_wildcard_match = container_of (list -> prev , struct evsel , core .node );
522549 free_config_terms (& config_terms );
523550 if (ret )
524551 goto out_err ;
@@ -1387,7 +1414,8 @@ int parse_events_add_tracepoint(struct parse_events_state *parse_state,
13871414static int __parse_events_add_numeric (struct parse_events_state * parse_state ,
13881415 struct list_head * list ,
13891416 struct perf_pmu * pmu , u32 type , u32 extended_type ,
1390- u64 config , const struct parse_events_terms * head_config )
1417+ u64 config , const struct parse_events_terms * head_config ,
1418+ struct evsel * first_wildcard_match )
13911419{
13921420 struct perf_event_attr attr ;
13931421 LIST_HEAD (config_terms );
@@ -1416,7 +1444,7 @@ static int __parse_events_add_numeric(struct parse_events_state *parse_state,
14161444 metric_id = get_config_metric_id (head_config );
14171445 cpus = get_config_cpu (head_config );
14181446 ret = __add_event (list , & parse_state -> idx , & attr , /*init_attr*/ true, name ,
1419- metric_id , pmu , & config_terms , /*auto_merge_stats=*/ false ,
1447+ metric_id , pmu , & config_terms , first_wildcard_match ,
14201448 cpus , /*alternate_hw_config=*/ PERF_COUNT_HW_MAX ) ? 0 : - ENOMEM ;
14211449 perf_cpu_map__put (cpus );
14221450 free_config_terms (& config_terms );
@@ -1434,6 +1462,7 @@ int parse_events_add_numeric(struct parse_events_state *parse_state,
14341462
14351463 /* Wildcards on numeric values are only supported by core PMUs. */
14361464 if (wildcard && perf_pmus__supports_extended_type ()) {
1465+ struct evsel * first_wildcard_match = NULL ;
14371466 while ((pmu = perf_pmus__scan_core (pmu )) != NULL ) {
14381467 int ret ;
14391468
@@ -1443,15 +1472,20 @@ int parse_events_add_numeric(struct parse_events_state *parse_state,
14431472
14441473 ret = __parse_events_add_numeric (parse_state , list , pmu ,
14451474 type , pmu -> type ,
1446- config , head_config );
1475+ config , head_config ,
1476+ first_wildcard_match );
14471477 if (ret )
14481478 return ret ;
1479+ if (first_wildcard_match == NULL )
1480+ first_wildcard_match =
1481+ container_of (list -> prev , struct evsel , core .node );
14491482 }
14501483 if (found_supported )
14511484 return 0 ;
14521485 }
14531486 return __parse_events_add_numeric (parse_state , list , perf_pmus__find_by_type (type ),
1454- type , /*extended_type=*/ 0 , config , head_config );
1487+ type , /*extended_type=*/ 0 , config , head_config ,
1488+ /*first_wildcard_match=*/ NULL );
14551489}
14561490
14571491static bool config_term_percore (struct list_head * config_terms )
@@ -1469,7 +1503,7 @@ static bool config_term_percore(struct list_head *config_terms)
14691503static int parse_events_add_pmu (struct parse_events_state * parse_state ,
14701504 struct list_head * list , struct perf_pmu * pmu ,
14711505 const struct parse_events_terms * const_parsed_terms ,
1472- bool auto_merge_stats , u64 alternate_hw_config )
1506+ struct evsel * first_wildcard_match , u64 alternate_hw_config )
14731507{
14741508 struct perf_event_attr attr ;
14751509 struct perf_pmu_info info ;
@@ -1506,7 +1540,7 @@ static int parse_events_add_pmu(struct parse_events_state *parse_state,
15061540 evsel = __add_event (list , & parse_state -> idx , & attr ,
15071541 /*init_attr=*/ true, /*name=*/ NULL ,
15081542 /*metric_id=*/ NULL , pmu ,
1509- /*config_terms=*/ NULL , auto_merge_stats ,
1543+ /*config_terms=*/ NULL , first_wildcard_match ,
15101544 /*cpu_list=*/ NULL , alternate_hw_config );
15111545 return evsel ? 0 : - ENOMEM ;
15121546 }
@@ -1577,7 +1611,7 @@ static int parse_events_add_pmu(struct parse_events_state *parse_state,
15771611 evsel = __add_event (list , & parse_state -> idx , & attr , /*init_attr=*/ true,
15781612 get_config_name (& parsed_terms ),
15791613 get_config_metric_id (& parsed_terms ), pmu ,
1580- & config_terms , auto_merge_stats , term_cpu , alternate_hw_config );
1614+ & config_terms , first_wildcard_match , term_cpu , alternate_hw_config );
15811615 perf_cpu_map__put (term_cpu );
15821616 if (!evsel ) {
15831617 parse_events_terms__exit (& parsed_terms );
@@ -1614,6 +1648,7 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
16141648 int ok = 0 ;
16151649 const char * config ;
16161650 struct parse_events_terms parsed_terms ;
1651+ struct evsel * first_wildcard_match = NULL ;
16171652
16181653 * listp = NULL ;
16191654
@@ -1646,17 +1681,14 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
16461681 INIT_LIST_HEAD (list );
16471682
16481683 while ((pmu = perf_pmus__scan (pmu )) != NULL ) {
1649- bool auto_merge_stats ;
1650-
16511684 if (parse_events__filter_pmu (parse_state , pmu ))
16521685 continue ;
16531686
16541687 if (!perf_pmu__have_event (pmu , event_name ))
16551688 continue ;
16561689
1657- auto_merge_stats = perf_pmu__auto_merge_stats (pmu );
16581690 if (!parse_events_add_pmu (parse_state , list , pmu ,
1659- & parsed_terms , auto_merge_stats , hw_config )) {
1691+ & parsed_terms , first_wildcard_match , hw_config )) {
16601692 struct strbuf sb ;
16611693
16621694 strbuf_init (& sb , /*hint=*/ 0 );
@@ -1665,11 +1697,13 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
16651697 strbuf_release (& sb );
16661698 ok ++ ;
16671699 }
1700+ if (first_wildcard_match == NULL )
1701+ first_wildcard_match = container_of (list -> prev , struct evsel , core .node );
16681702 }
16691703
16701704 if (parse_state -> fake_pmu ) {
16711705 if (!parse_events_add_pmu (parse_state , list , perf_pmus__fake_pmu (), & parsed_terms ,
1672- /*auto_merge_stats=*/ true , hw_config )) {
1706+ first_wildcard_match , hw_config )) {
16731707 struct strbuf sb ;
16741708
16751709 strbuf_init (& sb , /*hint=*/ 0 );
@@ -1700,6 +1734,7 @@ int parse_events_multi_pmu_add_or_add_pmu(struct parse_events_state *parse_state
17001734 struct perf_pmu * pmu ;
17011735 int ok = 0 ;
17021736 char * help ;
1737+ struct evsel * first_wildcard_match = NULL ;
17031738
17041739 * listp = malloc (sizeof (* * listp ));
17051740 if (!* listp )
@@ -1710,14 +1745,14 @@ int parse_events_multi_pmu_add_or_add_pmu(struct parse_events_state *parse_state
17101745 /* Attempt to add to list assuming event_or_pmu is a PMU name. */
17111746 pmu = perf_pmus__find (event_or_pmu );
17121747 if (pmu && !parse_events_add_pmu (parse_state , * listp , pmu , const_parsed_terms ,
1713- /*auto_merge_stats=*/ false ,
1748+ first_wildcard_match ,
17141749 /*alternate_hw_config=*/ PERF_COUNT_HW_MAX ))
17151750 return 0 ;
17161751
17171752 if (parse_state -> fake_pmu ) {
17181753 if (!parse_events_add_pmu (parse_state , * listp , perf_pmus__fake_pmu (),
17191754 const_parsed_terms ,
1720- /*auto_merge_stats=*/ false ,
1755+ first_wildcard_match ,
17211756 /*alternate_hw_config=*/ PERF_COUNT_HW_MAX ))
17221757 return 0 ;
17231758 }
@@ -1727,15 +1762,16 @@ int parse_events_multi_pmu_add_or_add_pmu(struct parse_events_state *parse_state
17271762 while ((pmu = perf_pmus__scan (pmu )) != NULL ) {
17281763 if (!parse_events__filter_pmu (parse_state , pmu ) &&
17291764 perf_pmu__wildcard_match (pmu , event_or_pmu )) {
1730- bool auto_merge_stats = perf_pmu__auto_merge_stats (pmu );
1731-
17321765 if (!parse_events_add_pmu (parse_state , * listp , pmu ,
17331766 const_parsed_terms ,
1734- auto_merge_stats ,
1767+ first_wildcard_match ,
17351768 /*alternate_hw_config=*/ PERF_COUNT_HW_MAX )) {
17361769 ok ++ ;
17371770 parse_state -> wild_card_pmus = true;
17381771 }
1772+ if (first_wildcard_match == NULL )
1773+ first_wildcard_match =
1774+ container_of ((* listp )-> prev , struct evsel , core .node );
17391775 }
17401776 }
17411777 if (ok )
0 commit comments