static void print_counts(perf_event_desc_t *fds, int num) { int i; read_groups(fds, num); for(i=0; i < num; i++) { double ratio; uint64_t val; val = fds[i].value - fds[i].prev_value; ratio = 0.0; if (fds[i].enabled) ratio = 1.0 * fds[i].running / fds[i].enabled; /* separate groups */ if (perf_is_group_leader(fds, i)) putchar('\n'); if (fds[i].value < fds[i].prev_value) { printf("inconsistent scaling %s (cur=%'"PRIu64" : prev=%'"PRIu64")\n", fds[i].name, fds[i].value, fds[i].prev_value); continue; } printf("%'20"PRIu64" %s (%.2f%% scaling, ena=%'"PRIu64", run=%'"PRIu64")\n", val, fds[i].name, (1.0-ratio)*100.0, fds[i].enabled, fds[i].running); } }
static void print_counts(perf_event_desc_t *fds, int num) { double ratio; uint64_t val, delta; int i; read_groups(fds, num); for(i=0; i < num; i++) { val = perf_scale(fds[i].values); delta = perf_scale_delta(fds[i].values, fds[i].prev_values); ratio = perf_scale_ratio(fds[i].values); /* separate groups */ if (perf_is_group_leader(fds, i)) putchar('\n'); if (options.print) printf("%'20"PRIu64" %'20"PRIu64" %s (%.2f%% scaling, ena=%'"PRIu64", run=%'"PRIu64")\n", val, delta, fds[i].name, (1.0-ratio)*100.0, fds[i].values[1], fds[i].values[2]); else printf("%'20"PRIu64" %s (%.2f%% scaling, ena=%'"PRIu64", run=%'"PRIu64")\n", val, fds[i].name, (1.0-ratio)*100.0, fds[i].values[1], fds[i].values[2]); fds[i].prev_values[0] = fds[i].values[0]; fds[i].prev_values[1] = fds[i].values[1]; fds[i].prev_values[2] = fds[i].values[2]; } }
int parent(char **arg) { perf_event_desc_t *fds = NULL; int status, ret, i, num_fds = 0, grp, group_fd; int ready[2], go[2]; char buf; pid_t pid; // output_file = fopen(file_name, "w"); //if (chroot("/home/pittdvs/cpu2006/benchspec/CPU2006/464.h264ref/run/run_base_ref_amd64-m64-gcc42-nn.0000")) // err(1, "err on chroot()"); if (pfm_initialize() != PFM_SUCCESS) errx(1, "libpfm initialization failed"); for (grp = 0; grp < options.num_groups; grp++) { int ret; ret = perf_setup_list_events(options.events[grp], &fds, &num_fds); if (ret || !num_fds) exit(1); } pid = options.pid; if (!pid) { ret = pipe(ready); if (ret) err(1, "cannot create pipe ready"); ret = pipe(go); if (ret) err(1, "cannot create pipe go"); /* * Create the child task */ if ((pid=fork()) == -1) err(1, "Cannot fork process"); /* * and launch the child code * * The pipe is used to avoid a race condition * between for() and exec(). We need the pid * of the new tak but we want to start measuring * at the first user level instruction. Thus we * need to prevent exec until we have attached * the events. */ if (pid == 0) { close(ready[0]); close(go[1]); /* * let the parent know we exist */ close(ready[1]); if (read(go[0], &buf, 1) == -1) err(1, "unable to read go_pipe"); exit(child(arg)); } close(ready[1]); close(go[0]); if (read(ready[0], &buf, 1) == -1) err(1, "unable to read child_ready_pipe"); close(ready[0]); } for(i=0; i < num_fds; i++) { int is_group_leader; /* boolean */ is_group_leader = perf_is_group_leader(fds, i); if (is_group_leader) { /* this is the group leader */ group_fd = -1; } else { group_fd = fds[fds[i].group_leader].fd; } /* * create leader disabled with enable_on-exec */ if (!options.pid) { 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 (is_group_leader && options.format_group) fds[i].hw.read_format |= PERF_FORMAT_GROUP; if (options.inherit) fds[i].hw.inherit = 1; if (options.pin && is_group_leader) fds[i].hw.pinned = 1; 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; } } if (!options.pid) close(go[1]); if (options.print) { if (!options.pid) { while(waitpid(pid, &status, WNOHANG) == 0 && quit == 0) { //sleep(1); //usleep(10000); msleep(100); //better_sleep(0.05); // 50ms print_counts(fds, num_fds); } } else { while(quit == 0) { sleep(1); print_counts(fds, num_fds); } } } else { if (!options.pid) waitpid(pid, &status, 0); else pause(); print_counts(fds, num_fds); } for(i=0; i < num_fds; i++) close(fds[i].fd); free(fds); /* free libpfm resources cleanly */ pfm_terminate(); // fclose(output_file); return 0; error: free(fds); if (!options.pid) kill(SIGKILL, pid); /* free libpfm resources cleanly */ pfm_terminate(); // fclose(output_file); return -1; }
void setup_cpu(int cpu, int cfd) { perf_event_desc_t *fds = NULL; int old_total, total = 0, num; int i, j, n, ret, is_lead, group_fd; unsigned long flags; pid_t pid; for(i=0, j=0; i < options.num_groups; i++) { old_total = total; ret = perf_setup_list_events(options.events[i], &fds, &total); if (ret) errx(1, "cannot setup events\n"); all_fds[cpu] = fds; num = total - old_total; options.nevents[i] = num; for(n=0; n < num; n++, j++) { is_lead = perf_is_group_leader(fds, j); if (is_lead) { fds[j].hw.disabled = 1; group_fd = -1; } else { fds[j].hw.disabled = 0; group_fd = fds[fds[j].group_leader].fd; } fds[j].hw.size = sizeof(struct perf_event_attr); if (options.cgroup_name) { flags = PERF_FLAG_PID_CGROUP; pid = cfd; //fds[j].hw.cgroup = 1; //fds[j].hw.cgroup_fd = cfd; } else { flags = 0; pid = -1; } if (options.pin && is_lead) fds[j].hw.pinned = 1; if (options.excl && is_lead) fds[j].hw.exclusive = 1; /* request timing information necessary for scaling counts */ fds[j].hw.read_format = PERF_FORMAT_SCALE; fds[j].fd = perf_event_open(&fds[j].hw, pid, cpu, group_fd, flags); if (fds[j].fd == -1) { if (errno == EACCES) err(1, "you need to be root to run system-wide on this machine"); warn("cannot attach event %s to CPU%ds, skipping it", fds[j].name, cpu); goto error; } } } return; error: for (i=0; i < j; i++) { close(fds[i].fd); fds[i].fd = -1; } }