It is desirable to be able to specify more than one group on the command line. This change adds the capability of specifying multiple groups via multiple "-e <event>,<event>,.." switches. Each -e switch specifies a new group, and the events contained in that group. If grouping is not desired, the events can be placed in individual -e switches, i.e. -e <event1> -e <event2> ...
Since this becomes the default behavior of "task", there is no longer a need for the "-g" switch, and the need for the read_single() function is eliminated. This change simplifies the group leader handling and unifies the logic so that grouping is always used... only the size and number of groups varies. Signed-off-by: Corey Ashford <cjash...@linux.vnet.ibm.com> --- perf_examples/perf_util.c | 7 +++- perf_examples/perf_util.h | 1 + perf_examples/task.c | 88 +++++++++++++++++++------------------------- 3 files changed, 44 insertions(+), 52 deletions(-) diff --git a/perf_examples/perf_util.c b/perf_examples/perf_util.c index 4de21a8..3853ddf 100644 --- a/perf_examples/perf_util.c +++ b/perf_examples/perf_util.c @@ -34,9 +34,11 @@ int perf_setup_argv_events(char **argv, perf_event_desc_t **fd) { - perf_event_desc_t *fdt = NULL; - int num = 0, max_fd = 0, new_max; + static perf_event_desc_t *fdt = NULL; + static int num = 0, max_fd = 0; + int new_max; int ret; + const int group_leader = num; if (!(argv && fd)) return -1; @@ -72,6 +74,7 @@ perf_setup_argv_events(char **argv, perf_event_desc_t **fd) /* ABI compatibility */ fdt[num].hw.size = sizeof(struct perf_event_attr); fdt[num].name = *argv; + fdt[num].group_leader = group_leader; num++; argv++; } diff --git a/perf_examples/perf_util.h b/perf_examples/perf_util.h index ae5449a..a6e1dc9 100644 --- a/perf_examples/perf_util.h +++ b/perf_examples/perf_util.h @@ -36,6 +36,7 @@ typedef struct { uint64_t id; /* event id kernel */ void *buf; size_t pgmsk; + int group_leader; int fd; } perf_event_desc_t; diff --git a/perf_examples/task.c b/perf_examples/task.c index b29822a..aafd4bc 100644 --- a/perf_examples/task.c +++ b/perf_examples/task.c @@ -35,10 +35,12 @@ #include "perf_util.h" +#define MAX_GROUPS 16 + typedef struct { - const char *events; + const char *events[MAX_GROUPS]; + int num_groups; int inherit; - int group; int print; int pin; pid_t pid; @@ -107,36 +109,11 @@ read_group(perf_event_desc_t *fds, int num) } static void -read_single(perf_event_desc_t *fds, int num) -{ - uint64_t values[3]; - int i, ret; - - for(i=0; i < num; i++) { - - ret = read(fds[i].fd, values, sizeof(values)); - if (ret != sizeof(values)) { /* unsigned */ - if (ret == -1) - err(1, "cannot read values event %s", fds[i].name); - else /* likely pinned and could not be loaded */ - warnx("could not read event%d", i); - } - fds[i].prev_value = fds[i].value; - fds[i].value = perf_scale(values); - fds[i].enabled = values[1]; - fds[i].running = values[2]; - } -} - -static void print_counts(perf_event_desc_t *fds, int num) { int i; - if (options.group) - read_group(fds, num); - else - read_single(fds, num); + read_group(fds, num); for(i=0; i < num; i++) { double ratio; @@ -167,8 +144,8 @@ static void sig_handler(int n) int parent(char **arg) { - perf_event_desc_t *fds; - int status, ret, i, num; + perf_event_desc_t *fds = NULL; + int status, ret, i, num = 0, grp, group_fd; int ready[2], go[2]; char buf; pid_t pid; @@ -176,9 +153,11 @@ parent(char **arg) if (pfm_initialize() != PFM_SUCCESS) errx(1, "libpfm initialization failed"); - num = perf_setup_list_events(options.events, &fds); - if (num < 1) - exit(1); + for (grp = 0; grp < options.num_groups; grp++) { + num = perf_setup_list_events(options.events[grp], &fds); + if (num < 1) + exit(1); + } pid = options.pid; if (!pid) { @@ -233,31 +212,37 @@ parent(char **arg) fds[0].fd = -1; for(i=0; i < num; i++) { + int is_group_leader; /* boolean */ + + if (fds[i].group_leader == i) { + /* this is the group leader */ + group_fd = -1; + is_group_leader = 1; + } else { + group_fd = fds[fds[i].group_leader].fd; + is_group_leader = 0; + } + /* * create leader disabled with enable_on-exec */ if (!options.pid) { - if (options.group) { - fds[i].hw.disabled = !i; - fds[i].hw.enable_on_exec = !i; - } else { - fds[i].hw.disabled = 1; - fds[i].hw.enable_on_exec = 1; - } + fds[i].hw.disabled = is_group_leader; + fds[i].hw.enable_on_exec = is_group_leader; } fds[i].hw.read_format = PERF_FORMAT_SCALE; /* request timing information necessary for scaling counts */ - if (!i && options.group) + if (is_group_leader) fds[0].hw.read_format |= PERF_FORMAT_GROUP; if (options.inherit) fds[i].hw.inherit = 1; - if (options.pin && ((options.group && i== 0) || (!options.group))) + if (options.pin && is_group_leader) fds[i].hw.pinned = 1; - fds[i].fd = perf_event_open(&fds[i].hw, pid, -1, options.group ? fds[0].fd : -1, 0); + fds[i].fd = perf_event_open(&fds[i].hw, pid, -1, group_fd, 0); if (fds[i].fd == -1) { warn("cannot attach event%d %s", i, fds[i].name); goto error; @@ -323,10 +308,12 @@ main(int argc, char **argv) while ((c=getopt(argc, argv,"he:igpPt:")) != -1) { switch(c) { case 'e': - options.events = optarg; - break; - case 'g': - options.group = 1; + if (options.num_groups < MAX_GROUPS) { + options.events[options.num_groups++] = optarg; + } else { + errx(1, "you cannot specify more than %d groups.\n", + MAX_GROUPS); + } break; case 'p': options.print = 1; @@ -347,9 +334,10 @@ main(int argc, char **argv) errx(1, "unknown error"); } } - if (!options.events) - options.events = "PERF_COUNT_HW_CPU_CYCLES,PERF_COUNT_HW_INSTRUCTIONS"; - + if (!options.events) { + options.events[0] = "PERF_COUNT_HW_CPU_CYCLES,PERF_COUNT_HW_INSTRUCTIONS"; + options.num_groups = 1; + } if (!argv[optind] && !options.pid) errx(1, "you must specify a command to execute or a thread to attach to\n"); -- 1.7.0.4 ------------------------------------------------------------------------------ _______________________________________________ perfmon2-devel mailing list perfmon2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/perfmon2-devel