Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf tp_pmu: Factor existing tracepoint logic to new file

Start the creation of a tracepoint PMU abstraction. Tracepoint events
don't follow the regular sysfs perf conventions. Eventually the new
PMU abstraction will bridge the gap so tracepoint events look more
like regular perf ones.

Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: https://lore.kernel.org/r/20250725185202.68671-5-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>

authored by

Ian Rogers and committed by
Namhyung Kim
d002aab8 6e9fa413

+172 -108
+1
tools/perf/util/Build
··· 88 88 perf-util-y += drm_pmu.o 89 89 perf-util-y += hwmon_pmu.o 90 90 perf-util-y += tool_pmu.o 91 + perf-util-y += tp_pmu.o 91 92 perf-util-y += svghelper.o 92 93 perf-util-y += trace-event-info.o 93 94 perf-util-y += trace-event-scripting.o
+2 -19
tools/perf/util/evsel.c
··· 60 60 #include "drm_pmu.h" 61 61 #include "hwmon_pmu.h" 62 62 #include "tool_pmu.h" 63 + #include "tp_pmu.h" 63 64 #include "rlimit.h" 64 65 #include "../perf-sys.h" 65 66 #include "util/parse-branch-options.h" ··· 573 572 return NULL; 574 573 } 575 574 576 - static int trace_event__id(const char *sys, const char *name) 577 - { 578 - char *tp_dir = get_events_file(sys); 579 - char path[PATH_MAX]; 580 - int id, err; 581 - 582 - if (!tp_dir) 583 - return -1; 584 - 585 - scnprintf(path, PATH_MAX, "%s/%s/id", tp_dir, name); 586 - put_events_file(tp_dir); 587 - err = filename__read_int(path, &id); 588 - if (err) 589 - return err; 590 - 591 - return id; 592 - } 593 - 594 575 /* 595 576 * Returns pointer with encoded error via <linux/err.h> interface. 596 577 */ ··· 606 623 event_attr_init(&attr); 607 624 608 625 if (format) { 609 - id = trace_event__id(sys, name); 626 + id = tp_pmu__id(sys, name); 610 627 if (id < 0) { 611 628 err = id; 612 629 goto out_free;
+62 -89
tools/perf/util/parse-events.c
··· 17 17 #include "string2.h" 18 18 #include "strbuf.h" 19 19 #include "debug.h" 20 - #include <api/fs/tracing_path.h> 21 - #include <api/io_dir.h> 22 20 #include <perf/cpumap.h> 23 21 #include <util/parse-events-bison.h> 24 22 #include <util/parse-events-flex.h> 25 23 #include "pmu.h" 26 24 #include "pmus.h" 25 + #include "tp_pmu.h" 27 26 #include "asm/bug.h" 28 27 #include "ui/ui.h" 29 28 #include "util/parse-branch-options.h" ··· 32 33 #include "util/stat.h" 33 34 #include "util/util.h" 34 35 #include "tracepoint.h" 36 + #include <api/fs/tracing_path.h> 35 37 36 38 #define MAX_NAME_LEN 100 37 39 ··· 599 599 return 0; 600 600 } 601 601 602 - static int add_tracepoint_multi_event(struct parse_events_state *parse_state, 603 - struct list_head *list, 604 - const char *sys_name, const char *evt_name, 605 - struct parse_events_error *err, 606 - struct parse_events_terms *head_config, YYLTYPE *loc) 602 + struct add_tracepoint_multi_args { 603 + struct parse_events_state *parse_state; 604 + struct list_head *list; 605 + const char *sys_glob; 606 + const char *evt_glob; 607 + struct parse_events_error *err; 608 + struct parse_events_terms *head_config; 609 + YYLTYPE *loc; 610 + int found; 611 + }; 612 + 613 + static int add_tracepoint_multi_event_cb(void *state, const char *sys_name, const char *evt_name) 607 614 { 608 - char *evt_path; 609 - struct io_dirent64 *evt_ent; 610 - struct io_dir evt_dir; 611 - int ret = 0, found = 0; 615 + struct add_tracepoint_multi_args *args = state; 616 + int ret; 612 617 613 - evt_path = get_events_file(sys_name); 614 - if (!evt_path) { 615 - tracepoint_error(err, errno, sys_name, evt_name, loc->first_column); 616 - return -1; 617 - } 618 - io_dir__init(&evt_dir, open(evt_path, O_CLOEXEC | O_DIRECTORY | O_RDONLY)); 619 - if (evt_dir.dirfd < 0) { 620 - put_events_file(evt_path); 621 - tracepoint_error(err, errno, sys_name, evt_name, loc->first_column); 622 - return -1; 623 - } 618 + if (!strglobmatch(evt_name, args->evt_glob)) 619 + return 0; 624 620 625 - while (!ret && (evt_ent = io_dir__readdir(&evt_dir))) { 626 - if (!strcmp(evt_ent->d_name, ".") 627 - || !strcmp(evt_ent->d_name, "..") 628 - || !strcmp(evt_ent->d_name, "enable") 629 - || !strcmp(evt_ent->d_name, "filter")) 630 - continue; 621 + args->found++; 622 + ret = add_tracepoint(args->parse_state, args->list, sys_name, evt_name, 623 + args->err, args->head_config, args->loc); 631 624 632 - if (!strglobmatch(evt_ent->d_name, evt_name)) 633 - continue; 634 - 635 - found++; 636 - 637 - ret = add_tracepoint(parse_state, list, sys_name, evt_ent->d_name, 638 - err, head_config, loc); 639 - } 640 - 641 - if (!found) { 642 - tracepoint_error(err, ENOENT, sys_name, evt_name, loc->first_column); 643 - ret = -1; 644 - } 645 - 646 - put_events_file(evt_path); 647 - close(evt_dir.dirfd); 648 625 return ret; 649 626 } 650 627 651 - static int add_tracepoint_event(struct parse_events_state *parse_state, 652 - struct list_head *list, 653 - const char *sys_name, const char *evt_name, 654 - struct parse_events_error *err, 655 - struct parse_events_terms *head_config, YYLTYPE *loc) 628 + static int add_tracepoint_multi_event(struct add_tracepoint_multi_args *args, const char *sys_name) 656 629 { 657 - return strpbrk(evt_name, "*?") ? 658 - add_tracepoint_multi_event(parse_state, list, sys_name, evt_name, 659 - err, head_config, loc) : 660 - add_tracepoint(parse_state, list, sys_name, evt_name, 661 - err, head_config, loc); 630 + if (strpbrk(args->evt_glob, "*?") == NULL) { 631 + /* Not a glob. */ 632 + args->found++; 633 + return add_tracepoint(args->parse_state, args->list, sys_name, args->evt_glob, 634 + args->err, args->head_config, args->loc); 635 + } 636 + 637 + return tp_pmu__for_each_tp_event(sys_name, args, add_tracepoint_multi_event_cb); 638 + } 639 + 640 + static int add_tracepoint_multi_sys_cb(void *state, const char *sys_name) 641 + { 642 + struct add_tracepoint_multi_args *args = state; 643 + 644 + if (!strglobmatch(sys_name, args->sys_glob)) 645 + return 0; 646 + 647 + return add_tracepoint_multi_event(args, sys_name); 662 648 } 663 649 664 650 static int add_tracepoint_multi_sys(struct parse_events_state *parse_state, 665 651 struct list_head *list, 666 - const char *sys_name, const char *evt_name, 652 + const char *sys_glob, const char *evt_glob, 667 653 struct parse_events_error *err, 668 654 struct parse_events_terms *head_config, YYLTYPE *loc) 669 655 { 670 - struct io_dirent64 *events_ent; 671 - struct io_dir events_dir; 672 - int ret = 0; 673 - char *events_dir_path = get_tracing_file("events"); 656 + struct add_tracepoint_multi_args args = { 657 + .parse_state = parse_state, 658 + .list = list, 659 + .sys_glob = sys_glob, 660 + .evt_glob = evt_glob, 661 + .err = err, 662 + .head_config = head_config, 663 + .loc = loc, 664 + .found = 0, 665 + }; 666 + int ret; 674 667 675 - if (!events_dir_path) { 676 - tracepoint_error(err, errno, sys_name, evt_name, loc->first_column); 677 - return -1; 668 + if (strpbrk(sys_glob, "*?") == NULL) { 669 + /* Not a glob. */ 670 + ret = add_tracepoint_multi_event(&args, sys_glob); 671 + } else { 672 + ret = tp_pmu__for_each_tp_sys(&args, add_tracepoint_multi_sys_cb); 678 673 } 679 - io_dir__init(&events_dir, open(events_dir_path, O_CLOEXEC | O_DIRECTORY | O_RDONLY)); 680 - put_events_file(events_dir_path); 681 - if (events_dir.dirfd < 0) { 682 - tracepoint_error(err, errno, sys_name, evt_name, loc->first_column); 683 - return -1; 674 + if (args.found == 0) { 675 + tracepoint_error(err, ENOENT, sys_glob, evt_glob, loc->first_column); 676 + return -ENOENT; 684 677 } 685 - 686 - while (!ret && (events_ent = io_dir__readdir(&events_dir))) { 687 - if (!strcmp(events_ent->d_name, ".") 688 - || !strcmp(events_ent->d_name, "..") 689 - || !strcmp(events_ent->d_name, "enable") 690 - || !strcmp(events_ent->d_name, "header_event") 691 - || !strcmp(events_ent->d_name, "header_page")) 692 - continue; 693 - 694 - if (!strglobmatch(events_ent->d_name, sys_name)) 695 - continue; 696 - 697 - ret = add_tracepoint_event(parse_state, list, events_ent->d_name, 698 - evt_name, err, head_config, loc); 699 - } 700 - close(events_dir.dirfd); 701 678 return ret; 702 679 } 703 680 ··· 1383 1406 return -EINVAL; 1384 1407 } 1385 1408 1386 - if (strpbrk(sys, "*?")) 1387 - return add_tracepoint_multi_sys(parse_state, list, sys, event, 1388 - err, head_config, loc); 1389 - else 1390 - return add_tracepoint_event(parse_state, list, sys, event, 1391 - err, head_config, loc); 1409 + return add_tracepoint_multi_sys(parse_state, list, sys, event, 1410 + err, head_config, loc); 1392 1411 } 1393 1412 1394 1413 static int __parse_events_add_numeric(struct parse_events_state *parse_state,
+95
tools/perf/util/tp_pmu.c
··· 1 + // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 + #include "tp_pmu.h" 3 + #include <api/fs/fs.h> 4 + #include <api/fs/tracing_path.h> 5 + #include <api/io_dir.h> 6 + #include <linux/kernel.h> 7 + #include <errno.h> 8 + #include <string.h> 9 + 10 + int tp_pmu__id(const char *sys, const char *name) 11 + { 12 + char *tp_dir = get_events_file(sys); 13 + char path[PATH_MAX]; 14 + int id, err; 15 + 16 + if (!tp_dir) 17 + return -1; 18 + 19 + scnprintf(path, PATH_MAX, "%s/%s/id", tp_dir, name); 20 + put_events_file(tp_dir); 21 + err = filename__read_int(path, &id); 22 + if (err) 23 + return err; 24 + 25 + return id; 26 + } 27 + 28 + 29 + int tp_pmu__for_each_tp_event(const char *sys, void *state, tp_event_callback cb) 30 + { 31 + char *evt_path; 32 + struct io_dirent64 *evt_ent; 33 + struct io_dir evt_dir; 34 + int ret = 0; 35 + 36 + evt_path = get_events_file(sys); 37 + if (!evt_path) 38 + return -errno; 39 + 40 + io_dir__init(&evt_dir, open(evt_path, O_CLOEXEC | O_DIRECTORY | O_RDONLY)); 41 + if (evt_dir.dirfd < 0) { 42 + ret = -errno; 43 + put_events_file(evt_path); 44 + return ret; 45 + } 46 + put_events_file(evt_path); 47 + 48 + while (!ret && (evt_ent = io_dir__readdir(&evt_dir))) { 49 + if (!strcmp(evt_ent->d_name, ".") 50 + || !strcmp(evt_ent->d_name, "..") 51 + || !strcmp(evt_ent->d_name, "enable") 52 + || !strcmp(evt_ent->d_name, "filter")) 53 + continue; 54 + 55 + ret = cb(state, sys, evt_ent->d_name); 56 + if (ret) 57 + break; 58 + } 59 + close(evt_dir.dirfd); 60 + return ret; 61 + } 62 + 63 + int tp_pmu__for_each_tp_sys(void *state, tp_sys_callback cb) 64 + { 65 + struct io_dirent64 *events_ent; 66 + struct io_dir events_dir; 67 + int ret = 0; 68 + char *events_dir_path = get_tracing_file("events"); 69 + 70 + if (!events_dir_path) 71 + return -errno; 72 + 73 + io_dir__init(&events_dir, open(events_dir_path, O_CLOEXEC | O_DIRECTORY | O_RDONLY)); 74 + if (events_dir.dirfd < 0) { 75 + ret = -errno; 76 + put_events_file(events_dir_path); 77 + return ret; 78 + } 79 + put_events_file(events_dir_path); 80 + 81 + while (!ret && (events_ent = io_dir__readdir(&events_dir))) { 82 + if (!strcmp(events_ent->d_name, ".") || 83 + !strcmp(events_ent->d_name, "..") || 84 + !strcmp(events_ent->d_name, "enable") || 85 + !strcmp(events_ent->d_name, "header_event") || 86 + !strcmp(events_ent->d_name, "header_page")) 87 + continue; 88 + 89 + ret = cb(state, events_ent->d_name); 90 + if (ret) 91 + break; 92 + } 93 + close(events_dir.dirfd); 94 + return ret; 95 + }
+12
tools/perf/util/tp_pmu.h
··· 1 + /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 + #ifndef __TP_PMU_H 3 + #define __TP_PMU_H 4 + 5 + typedef int (*tp_sys_callback)(void *state, const char *sys_name); 6 + typedef int (*tp_event_callback)(void *state, const char *sys_name, const char *evt_name); 7 + 8 + int tp_pmu__id(const char *sys, const char *name); 9 + int tp_pmu__for_each_tp_event(const char *sys, void *state, tp_event_callback cb); 10 + int tp_pmu__for_each_tp_sys(void *state, tp_sys_callback cb); 11 + 12 + #endif /* __TP_PMU_H */