@@ -377,38 +377,6 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
377
377
return 0 ;
378
378
}
379
379
380
- static void perf_pmu_assign_str (char * name , const char * field , char * * old_str ,
381
- char * * new_str )
382
- {
383
- if (!* old_str )
384
- goto set_new ;
385
-
386
- if (* new_str ) { /* Have new string, check with old */
387
- if (strcasecmp (* old_str , * new_str ))
388
- pr_debug ("alias %s differs in field '%s'\n" ,
389
- name , field );
390
- zfree (old_str );
391
- } else /* Nothing new --> keep old string */
392
- return ;
393
- set_new :
394
- * old_str = * new_str ;
395
- * new_str = NULL ;
396
- }
397
-
398
- static void perf_pmu_update_alias (struct perf_pmu_alias * old ,
399
- struct perf_pmu_alias * newalias )
400
- {
401
- perf_pmu_assign_str (old -> name , "desc" , & old -> desc , & newalias -> desc );
402
- perf_pmu_assign_str (old -> name , "long_desc" , & old -> long_desc ,
403
- & newalias -> long_desc );
404
- perf_pmu_assign_str (old -> name , "topic" , & old -> topic , & newalias -> topic );
405
- perf_pmu_assign_str (old -> name , "value" , & old -> str , & newalias -> str );
406
- old -> scale = newalias -> scale ;
407
- old -> per_pkg = newalias -> per_pkg ;
408
- old -> snapshot = newalias -> snapshot ;
409
- memcpy (old -> unit , newalias -> unit , sizeof (old -> unit ));
410
- }
411
-
412
380
/* Delete an alias entry. */
413
381
static void perf_pmu_free_alias (struct perf_pmu_alias * newalias )
414
382
{
@@ -432,26 +400,58 @@ static void perf_pmu__del_aliases(struct perf_pmu *pmu)
432
400
}
433
401
}
434
402
435
- /* Merge an alias, search in alias list. If this name is already
436
- * present merge both of them to combine all information.
437
- */
438
- static bool perf_pmu_merge_alias (struct perf_pmu * pmu ,
439
- struct perf_pmu_alias * newalias )
403
+ static struct perf_pmu_alias * perf_pmu__find_alias (const struct perf_pmu * pmu , const char * name )
440
404
{
441
- struct perf_pmu_alias * a ;
405
+ struct perf_pmu_alias * alias ;
442
406
443
- list_for_each_entry (a , & pmu -> aliases , list ) {
444
- if (!strcasecmp (newalias -> name , a -> name )) {
445
- if (newalias -> pmu_name && a -> pmu_name &&
446
- !strcasecmp (newalias -> pmu_name , a -> pmu_name )) {
447
- continue ;
448
- }
449
- perf_pmu_update_alias (a , newalias );
450
- perf_pmu_free_alias (newalias );
451
- return true;
452
- }
407
+ list_for_each_entry (alias , & pmu -> aliases , list ) {
408
+ if (!strcasecmp (alias -> name , name ))
409
+ return alias ;
453
410
}
454
- return false;
411
+ return NULL ;
412
+ }
413
+
414
+ static bool assign_str (const char * name , const char * field , char * * old_str ,
415
+ const char * new_str )
416
+ {
417
+ if (!* old_str && new_str ) {
418
+ * old_str = strdup (new_str );
419
+ return true;
420
+ }
421
+
422
+ if (!new_str || !strcasecmp (* old_str , new_str ))
423
+ return false; /* Nothing to update. */
424
+
425
+ pr_debug ("alias %s differs in field '%s' ('%s' != '%s')\n" ,
426
+ name , field , * old_str , new_str );
427
+ zfree (old_str );
428
+ * old_str = strdup (new_str );
429
+ return true;
430
+ }
431
+
432
+ static int update_alias (const struct pmu_event * pe ,
433
+ const struct pmu_events_table * table __maybe_unused ,
434
+ void * vdata )
435
+ {
436
+ struct perf_pmu_alias * alias = vdata ;
437
+ int ret = 0 ;
438
+
439
+ assign_str (pe -> name , "desc" , & alias -> desc , pe -> desc );
440
+ assign_str (pe -> name , "long_desc" , & alias -> long_desc , pe -> long_desc );
441
+ assign_str (pe -> name , "topic" , & alias -> topic , pe -> topic );
442
+ alias -> per_pkg = pe -> perpkg ;
443
+ if (assign_str (pe -> name , "value" , & alias -> str , pe -> event )) {
444
+ parse_events_terms__purge (& alias -> terms );
445
+ ret = parse_events_terms (& alias -> terms , pe -> event , /*input=*/ NULL );
446
+ }
447
+ if (!ret && pe -> unit ) {
448
+ char * unit ;
449
+
450
+ ret = perf_pmu__convert_scale (pe -> unit , & unit , & alias -> scale );
451
+ if (!ret )
452
+ snprintf (alias -> unit , sizeof (alias -> unit ), "%s" , unit );
453
+ }
454
+ return ret ;
455
455
}
456
456
457
457
static int perf_pmu__new_alias (struct perf_pmu * pmu , int dirfd , const char * name ,
@@ -465,6 +465,11 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
465
465
const char * long_desc = NULL , * topic = NULL , * unit = NULL , * pmu_name = NULL ;
466
466
bool deprecated = false, perpkg = false;
467
467
468
+ if (perf_pmu__find_alias (pmu , name )) {
469
+ /* Alias was already created/loaded. */
470
+ return 0 ;
471
+ }
472
+
468
473
if (pe ) {
469
474
long_desc = pe -> long_desc ;
470
475
topic = pe -> topic ;
@@ -492,27 +497,6 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
492
497
return ret ;
493
498
}
494
499
495
- /* Scan event and remove leading zeroes, spaces, newlines, some
496
- * platforms have terms specified as
497
- * event=0x0091 (read from files ../<PMU>/events/<FILE>
498
- * and terms specified as event=0x91 (read from JSON files).
499
- *
500
- * Rebuild string to make alias->str member comparable.
501
- */
502
- memset (newval , 0 , sizeof (newval ));
503
- ret = 0 ;
504
- list_for_each_entry (term , & alias -> terms , list ) {
505
- if (ret )
506
- ret += scnprintf (newval + ret , sizeof (newval ) - ret ,
507
- "," );
508
- if (term -> type_val == PARSE_EVENTS__TERM_TYPE_NUM )
509
- ret += scnprintf (newval + ret , sizeof (newval ) - ret ,
510
- "%s=%#x" , term -> config , term -> val .num );
511
- else if (term -> type_val == PARSE_EVENTS__TERM_TYPE_STR )
512
- ret += scnprintf (newval + ret , sizeof (newval ) - ret ,
513
- "%s=%s" , term -> config , term -> val .str );
514
- }
515
-
516
500
alias -> name = strdup (name );
517
501
if (dirfd >= 0 ) {
518
502
/*
@@ -528,17 +512,43 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
528
512
alias -> long_desc = long_desc ? strdup (long_desc ) :
529
513
desc ? strdup (desc ) : NULL ;
530
514
alias -> topic = topic ? strdup (topic ) : NULL ;
515
+ alias -> pmu_name = pmu_name ? strdup (pmu_name ) : NULL ;
531
516
if (unit ) {
532
- if (perf_pmu__convert_scale (unit , (char * * )& unit , & alias -> scale ) < 0 )
517
+ if (perf_pmu__convert_scale (unit , (char * * )& unit , & alias -> scale ) < 0 ) {
518
+ perf_pmu_free_alias (alias );
533
519
return -1 ;
520
+ }
534
521
snprintf (alias -> unit , sizeof (alias -> unit ), "%s" , unit );
535
522
}
536
- alias -> str = strdup (newval );
537
- alias -> pmu_name = pmu_name ? strdup (pmu_name ) : NULL ;
523
+ if (!pe ) {
524
+ /* Update an event from sysfs with json data. */
525
+ const struct pmu_events_table * table = perf_pmu__find_events_table (pmu );
538
526
539
- if (!perf_pmu_merge_alias (pmu , alias ))
540
- list_add_tail (& alias -> list , & pmu -> aliases );
527
+ if (table )
528
+ pmu_events_table__find_event (table , pmu , name , update_alias , alias );
529
+ }
541
530
531
+ /* Scan event and remove leading zeroes, spaces, newlines, some
532
+ * platforms have terms specified as
533
+ * event=0x0091 (read from files ../<PMU>/events/<FILE>
534
+ * and terms specified as event=0x91 (read from JSON files).
535
+ *
536
+ * Rebuild string to make alias->str member comparable.
537
+ */
538
+ ret = 0 ;
539
+ list_for_each_entry (term , & alias -> terms , list ) {
540
+ if (ret )
541
+ ret += scnprintf (newval + ret , sizeof (newval ) - ret ,
542
+ "," );
543
+ if (term -> type_val == PARSE_EVENTS__TERM_TYPE_NUM )
544
+ ret += scnprintf (newval + ret , sizeof (newval ) - ret ,
545
+ "%s=%#x" , term -> config , term -> val .num );
546
+ else if (term -> type_val == PARSE_EVENTS__TERM_TYPE_STR )
547
+ ret += scnprintf (newval + ret , sizeof (newval ) - ret ,
548
+ "%s=%s" , term -> config , term -> val .str );
549
+ }
550
+ alias -> str = strdup (newval );
551
+ list_add_tail (& alias -> list , & pmu -> aliases );
542
552
return 0 ;
543
553
}
544
554
@@ -944,6 +954,9 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
944
954
INIT_LIST_HEAD (& pmu -> format );
945
955
INIT_LIST_HEAD (& pmu -> aliases );
946
956
INIT_LIST_HEAD (& pmu -> caps );
957
+ pmu -> name = strdup (name );
958
+ if (!pmu -> name )
959
+ goto err ;
947
960
/*
948
961
* The pmu data we store & need consists of the pmu
949
962
* type value and format definitions. Load both right
@@ -962,9 +975,6 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
962
975
}
963
976
pmu -> is_core = is_pmu_core (name );
964
977
pmu -> cpus = pmu_cpumask (dirfd , name , pmu -> is_core );
965
- pmu -> name = strdup (name );
966
- if (!pmu -> name )
967
- goto err ;
968
978
969
979
/* Read type, and ensure that type value is successfully assigned (return 1) */
970
980
if (perf_pmu__scan_file_at (pmu , dirfd , "type" , "%u" , & type ) != 1 )
@@ -1357,17 +1367,6 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
1357
1367
return perf_pmu__config_terms (pmu , attr , head_terms , zero , err );
1358
1368
}
1359
1369
1360
- static struct perf_pmu_alias * perf_pmu__find_alias (const struct perf_pmu * pmu , const char * str )
1361
- {
1362
- struct perf_pmu_alias * alias ;
1363
-
1364
- list_for_each_entry (alias , & pmu -> aliases , list ) {
1365
- if (!strcasecmp (alias -> name , str ))
1366
- return alias ;
1367
- }
1368
- return NULL ;
1369
- }
1370
-
1371
1370
static struct perf_pmu_alias * pmu_find_alias (struct perf_pmu * pmu ,
1372
1371
struct parse_events_term * term )
1373
1372
{
0 commit comments