|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* task_inherit.c - example of a task counting event in a tree of child processes
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
* Copyright (c) 2009 Google, Inc
|
|
Packit Service |
a1973e |
* Contributed by Stephane Eranian <eranian@gmail.com>
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
Packit Service |
a1973e |
* of this software and associated documentation files (the "Software"), to deal
|
|
Packit Service |
a1973e |
* in the Software without restriction, including without limitation the rights
|
|
Packit Service |
a1973e |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
Packit Service |
a1973e |
* of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
Packit Service |
a1973e |
* subject to the following conditions:
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
* The above copyright notice and this permission notice shall be included in all
|
|
Packit Service |
a1973e |
* copies or substantial portions of the Software.
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
Packit Service |
a1973e |
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
Packit Service |
a1973e |
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
Packit Service |
a1973e |
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
Packit Service |
a1973e |
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
Packit Service |
a1973e |
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
#include <sys/types.h>
|
|
Packit Service |
a1973e |
#include <inttypes.h>
|
|
Packit Service |
a1973e |
#include <stdio.h>
|
|
Packit Service |
a1973e |
#include <stdlib.h>
|
|
Packit Service |
a1973e |
#include <unistd.h>
|
|
Packit Service |
a1973e |
#include <string.h>
|
|
Packit Service |
a1973e |
#include <stdarg.h>
|
|
Packit Service |
a1973e |
#include <signal.h>
|
|
Packit Service |
a1973e |
#include <sys/wait.h>
|
|
Packit Service |
a1973e |
#include <locale.h>
|
|
Packit Service |
a1973e |
#include <err.h>
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#include "perf_util.h"
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
#define MAX_GROUPS 256
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
typedef struct {
|
|
Packit Service |
a1973e |
const char *events[MAX_GROUPS];
|
|
Packit Service |
a1973e |
int num_groups;
|
|
Packit Service |
a1973e |
int format_group;
|
|
Packit Service |
a1973e |
int inherit;
|
|
Packit Service |
a1973e |
int print;
|
|
Packit Service |
a1973e |
int pin;
|
|
Packit Service |
a1973e |
pid_t pid;
|
|
Packit Service |
a1973e |
} options_t;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static options_t options;
|
|
Packit Service |
a1973e |
static volatile int quit;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
child(char **arg)
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* execute the requested command
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
execvp(arg[0], arg);
|
|
Packit Service |
a1973e |
errx(1, "cannot exec: %s\n", arg[0]);
|
|
Packit Service |
a1973e |
/* not reached */
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
read_groups(perf_event_desc_t *fds, int num)
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
uint64_t *values = NULL;
|
|
Packit Service |
a1973e |
size_t new_sz, sz = 0;
|
|
Packit Service |
a1973e |
int i, evt;
|
|
Packit Service |
a1973e |
ssize_t ret;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* { u64 nr;
|
|
Packit Service |
a1973e |
* { u64 time_enabled; } && PERF_FORMAT_ENABLED
|
|
Packit Service |
a1973e |
* { u64 time_running; } && PERF_FORMAT_RUNNING
|
|
Packit Service |
a1973e |
* { u64 value;
|
|
Packit Service |
a1973e |
* { u64 id; } && PERF_FORMAT_ID
|
|
Packit Service |
a1973e |
* } cntr[nr];
|
|
Packit Service |
a1973e |
* } && PERF_FORMAT_GROUP
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
* we do not use FORMAT_ID in this program
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for (evt = 0; evt < num; ) {
|
|
Packit Service |
a1973e |
int num_evts_to_read;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (options.format_group) {
|
|
Packit Service |
a1973e |
num_evts_to_read = perf_get_group_nevents(fds, num, evt);
|
|
Packit Service |
a1973e |
new_sz = sizeof(uint64_t) * (3 + num_evts_to_read);
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
num_evts_to_read = 1;
|
|
Packit Service |
a1973e |
new_sz = sizeof(uint64_t) * 3;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (new_sz > sz) {
|
|
Packit Service |
a1973e |
sz = new_sz;
|
|
Packit Service |
a1973e |
values = realloc(values, sz);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (!values)
|
|
Packit Service |
a1973e |
err(1, "cannot allocate memory for values\n");
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ret = read(fds[evt].fd, values, new_sz);
|
|
Packit Service |
a1973e |
if (ret != (ssize_t)new_sz) { /* unsigned */
|
|
Packit Service |
a1973e |
if (ret == -1)
|
|
Packit Service |
a1973e |
err(1, "cannot read values event %s", fds[evt].name);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* likely pinned and could not be loaded */
|
|
Packit Service |
a1973e |
warnx("could not read event %d, tried to read %zu bytes, but got %zd",
|
|
Packit Service |
a1973e |
evt, new_sz, ret);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* propagate to save area
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
for (i = evt; i < (evt + num_evts_to_read); i++) {
|
|
Packit Service |
a1973e |
if (options.format_group)
|
|
Packit Service |
a1973e |
values[0] = values[3 + (i - evt)];
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* scaling because we may be sharing the PMU and
|
|
Packit Service |
a1973e |
* thus may be multiplexed
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
fds[i].values[0] = values[0];
|
|
Packit Service |
a1973e |
fds[i].values[1] = values[1];
|
|
Packit Service |
a1973e |
fds[i].values[2] = values[2];
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
evt += num_evts_to_read;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if (values)
|
|
Packit Service |
a1973e |
free(values);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
print_counts(perf_event_desc_t *fds, int num)
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
double ratio;
|
|
Packit Service |
a1973e |
uint64_t val, delta;
|
|
Packit Service |
a1973e |
int i;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
read_groups(fds, num);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for(i=0; i < num; i++) {
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
val = perf_scale(fds[i].values);
|
|
Packit Service |
a1973e |
delta = perf_scale_delta(fds[i].values, fds[i].prev_values);
|
|
Packit Service |
a1973e |
ratio = perf_scale_ratio(fds[i].values);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* separate groups */
|
|
Packit Service |
a1973e |
if (perf_is_group_leader(fds, i))
|
|
Packit Service |
a1973e |
putchar('\n');
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (options.print)
|
|
Packit Service |
a1973e |
printf("%'20"PRIu64" %'20"PRIu64" %s (%.2f%% scaling, ena=%'"PRIu64", run=%'"PRIu64")\n",
|
|
Packit Service |
a1973e |
val,
|
|
Packit Service |
a1973e |
delta,
|
|
Packit Service |
a1973e |
fds[i].name,
|
|
Packit Service |
a1973e |
(1.0-ratio)*100.0,
|
|
Packit Service |
a1973e |
fds[i].values[1],
|
|
Packit Service |
a1973e |
fds[i].values[2]);
|
|
Packit Service |
a1973e |
else
|
|
Packit Service |
a1973e |
printf("%'20"PRIu64" %s (%.2f%% scaling, ena=%'"PRIu64", run=%'"PRIu64")\n",
|
|
Packit Service |
a1973e |
val,
|
|
Packit Service |
a1973e |
fds[i].name,
|
|
Packit Service |
a1973e |
(1.0-ratio)*100.0,
|
|
Packit Service |
a1973e |
fds[i].values[1],
|
|
Packit Service |
a1973e |
fds[i].values[2]);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
fds[i].prev_values[0] = fds[i].values[0];
|
|
Packit Service |
a1973e |
fds[i].prev_values[1] = fds[i].values[1];
|
|
Packit Service |
a1973e |
fds[i].prev_values[2] = fds[i].values[2];
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static void sig_handler(int n)
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
quit = 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
parent(char **arg)
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
perf_event_desc_t *fds = NULL;
|
|
Packit Service |
a1973e |
int status, ret, i, num_fds = 0, grp, group_fd;
|
|
Packit Service |
a1973e |
int ready[2], go[2];
|
|
Packit Service |
a1973e |
char buf;
|
|
Packit Service |
a1973e |
pid_t pid;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
go[0] = go[1] = -1;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (pfm_initialize() != PFM_SUCCESS)
|
|
Packit Service |
a1973e |
errx(1, "libpfm initialization failed");
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for (grp = 0; grp < options.num_groups; grp++) {
|
|
Packit Service |
a1973e |
int ret;
|
|
Packit Service |
a1973e |
ret = perf_setup_list_events(options.events[grp], &fds, &num_fds);
|
|
Packit Service |
a1973e |
if (ret || !num_fds)
|
|
Packit Service |
a1973e |
exit(1);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
pid = options.pid;
|
|
Packit Service |
a1973e |
if (!pid) {
|
|
Packit Service |
a1973e |
ret = pipe(ready);
|
|
Packit Service |
a1973e |
if (ret)
|
|
Packit Service |
a1973e |
err(1, "cannot create pipe ready");
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
ret = pipe(go);
|
|
Packit Service |
a1973e |
if (ret)
|
|
Packit Service |
a1973e |
err(1, "cannot create pipe go");
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* Create the child task
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
if ((pid=fork()) == -1)
|
|
Packit Service |
a1973e |
err(1, "Cannot fork process");
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* and launch the child code
|
|
Packit Service |
a1973e |
*
|
|
Packit Service |
a1973e |
* The pipe is used to avoid a race condition
|
|
Packit Service |
a1973e |
* between for() and exec(). We need the pid
|
|
Packit Service |
a1973e |
* of the new tak but we want to start measuring
|
|
Packit Service |
a1973e |
* at the first user level instruction. Thus we
|
|
Packit Service |
a1973e |
* need to prevent exec until we have attached
|
|
Packit Service |
a1973e |
* the events.
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
if (pid == 0) {
|
|
Packit Service |
a1973e |
close(ready[0]);
|
|
Packit Service |
a1973e |
close(go[1]);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* let the parent know we exist
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
close(ready[1]);
|
|
Packit Service |
a1973e |
if (read(go[0], &buf, 1) == -1)
|
|
Packit Service |
a1973e |
err(1, "unable to read go_pipe");
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
exit(child(arg));
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
close(ready[1]);
|
|
Packit Service |
a1973e |
close(go[0]);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (read(ready[0], &buf, 1) == -1)
|
|
Packit Service |
a1973e |
err(1, "unable to read child_ready_pipe");
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
close(ready[0]);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for(i=0; i < num_fds; i++) {
|
|
Packit Service |
a1973e |
int is_group_leader; /* boolean */
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
is_group_leader = perf_is_group_leader(fds, i);
|
|
Packit Service |
a1973e |
if (is_group_leader) {
|
|
Packit Service |
a1973e |
/* this is the group leader */
|
|
Packit Service |
a1973e |
group_fd = -1;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
group_fd = fds[fds[i].group_leader].fd;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/*
|
|
Packit Service |
a1973e |
* create leader disabled with enable_on-exec
|
|
Packit Service |
a1973e |
*/
|
|
Packit Service |
a1973e |
if (!options.pid) {
|
|
Packit Service |
a1973e |
fds[i].hw.disabled = is_group_leader;
|
|
Packit Service |
a1973e |
fds[i].hw.enable_on_exec = is_group_leader;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
fds[i].hw.read_format = PERF_FORMAT_SCALE;
|
|
Packit Service |
a1973e |
/* request timing information necessary for scaling counts */
|
|
Packit Service |
a1973e |
if (is_group_leader && options.format_group)
|
|
Packit Service |
a1973e |
fds[i].hw.read_format |= PERF_FORMAT_GROUP;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (options.inherit)
|
|
Packit Service |
a1973e |
fds[i].hw.inherit = 1;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (options.pin && is_group_leader)
|
|
Packit Service |
a1973e |
fds[i].hw.pinned = 1;
|
|
Packit Service |
a1973e |
fds[i].fd = perf_event_open(&fds[i].hw, pid, -1, group_fd, 0);
|
|
Packit Service |
a1973e |
if (fds[i].fd == -1) {
|
|
Packit Service |
a1973e |
warn("cannot attach event%d %s", i, fds[i].name);
|
|
Packit Service |
a1973e |
goto error;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (!options.pid && go[1] > -1)
|
|
Packit Service |
a1973e |
close(go[1]);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
if (options.print) {
|
|
Packit Service |
a1973e |
if (!options.pid) {
|
|
Packit Service |
a1973e |
while(waitpid(pid, &status, WNOHANG) == 0) {
|
|
Packit Service |
a1973e |
sleep(1);
|
|
Packit Service |
a1973e |
print_counts(fds, num_fds);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
while(quit == 0) {
|
|
Packit Service |
a1973e |
sleep(1);
|
|
Packit Service |
a1973e |
print_counts(fds, num_fds);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
if (!options.pid)
|
|
Packit Service |
a1973e |
waitpid(pid, &status, 0);
|
|
Packit Service |
a1973e |
else
|
|
Packit Service |
a1973e |
pause();
|
|
Packit Service |
a1973e |
print_counts(fds, num_fds);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
for(i=0; i < num_fds; i++)
|
|
Packit Service |
a1973e |
close(fds[i].fd);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
perf_free_fds(fds, num_fds);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* free libpfm resources cleanly */
|
|
Packit Service |
a1973e |
pfm_terminate();
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return 0;
|
|
Packit Service |
a1973e |
error:
|
|
Packit Service |
a1973e |
free(fds);
|
|
Packit Service |
a1973e |
if (!options.pid)
|
|
Packit Service |
a1973e |
kill(SIGKILL, pid);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
/* free libpfm resources cleanly */
|
|
Packit Service |
a1973e |
pfm_terminate();
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return -1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
static void
|
|
Packit Service |
a1973e |
usage(void)
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
printf("usage: task [-h] [-i] [-g] [-p] [-P] [-t pid] [-e event1,event2,...] cmd\n"
|
|
Packit Service |
a1973e |
"-h\t\tget help\n"
|
|
Packit Service |
a1973e |
"-i\t\tinherit across fork\n"
|
|
Packit Service |
a1973e |
"-f\t\tuse PERF_FORMAT_GROUP for reading up counts (experimental, not working)\n"
|
|
Packit Service |
a1973e |
"-p\t\tprint counts every second\n"
|
|
Packit Service |
a1973e |
"-P\t\tpin events\n"
|
|
Packit Service |
a1973e |
"-t pid\tmeasure existing pid\n"
|
|
Packit Service |
a1973e |
"-e ev,ev\tgroup of events to measure (multiple -e switches are allowed)\n"
|
|
Packit Service |
a1973e |
);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
int
|
|
Packit Service |
a1973e |
main(int argc, char **argv)
|
|
Packit Service |
a1973e |
{
|
|
Packit Service |
a1973e |
int c;
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
setlocale(LC_ALL, "");
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
while ((c=getopt(argc, argv,"+he:ifpPt:")) != -1) {
|
|
Packit Service |
a1973e |
switch(c) {
|
|
Packit Service |
a1973e |
case 'e':
|
|
Packit Service |
a1973e |
if (options.num_groups < MAX_GROUPS) {
|
|
Packit Service |
a1973e |
options.events[options.num_groups++] = optarg;
|
|
Packit Service |
a1973e |
} else {
|
|
Packit Service |
a1973e |
errx(1, "you cannot specify more than %d groups.\n",
|
|
Packit Service |
a1973e |
MAX_GROUPS);
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
case 'f':
|
|
Packit Service |
a1973e |
options.format_group = 1;
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
case 'p':
|
|
Packit Service |
a1973e |
options.print = 1;
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
case 'P':
|
|
Packit Service |
a1973e |
options.pin = 1;
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
case 'i':
|
|
Packit Service |
a1973e |
options.inherit = 1;
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
case 't':
|
|
Packit Service |
a1973e |
options.pid = atoi(optarg);
|
|
Packit Service |
a1973e |
break;
|
|
Packit Service |
a1973e |
case 'h':
|
|
Packit Service |
a1973e |
usage();
|
|
Packit Service |
a1973e |
exit(0);
|
|
Packit Service |
a1973e |
default:
|
|
Packit Service |
a1973e |
errx(1, "unknown error");
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if (options.num_groups == 0) {
|
|
Packit Service |
a1973e |
options.events[0] = "cycles,instructions";
|
|
Packit Service |
a1973e |
options.num_groups = 1;
|
|
Packit Service |
a1973e |
}
|
|
Packit Service |
a1973e |
if (!argv[optind] && !options.pid)
|
|
Packit Service |
a1973e |
errx(1, "you must specify a command to execute or a thread to attach to\n");
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
signal(SIGINT, sig_handler);
|
|
Packit Service |
a1973e |
|
|
Packit Service |
a1973e |
return parent(argv+optind);
|
|
Packit Service |
a1973e |
}
|