Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/pmcstat/pmcstat.c
Show First 20 Lines • Show All 491 Lines • ▼ Show 20 Lines | errx(EX_USAGE, | ||||
"\t performance monitoring counters.\n" | "\t performance monitoring counters.\n" | ||||
"\t Options include:\n" | "\t Options include:\n" | ||||
"\t -C\t\t (toggle) show cumulative counts\n" | "\t -C\t\t (toggle) show cumulative counts\n" | ||||
"\t -D path\t create profiles in directory \"path\"\n" | "\t -D path\t create profiles in directory \"path\"\n" | ||||
"\t -E\t\t (toggle) show counts at process exit\n" | "\t -E\t\t (toggle) show counts at process exit\n" | ||||
"\t -F file\t write a system-wide callgraph (Kcachegrind format)" | "\t -F file\t write a system-wide callgraph (Kcachegrind format)" | ||||
" to \"file\"\n" | " to \"file\"\n" | ||||
"\t -G file\t write a system-wide callgraph to \"file\"\n" | "\t -G file\t write a system-wide callgraph to \"file\"\n" | ||||
"\t -K dir-list\t set the paths to check for kernel modules\n" | |||||
wblockUnsubmitted Not Done Inline Actionswblock: ```"\t -K dir-list\t set the search path for kernel modules\n" | |||||
"\t -M file\t print executable/gmon file map to \"file\"\n" | "\t -M file\t print executable/gmon file map to \"file\"\n" | ||||
"\t -N\t\t (toggle) capture callchains\n" | "\t -N\t\t (toggle) capture callchains\n" | ||||
"\t -O file\t send log output to \"file\"\n" | "\t -O file\t send log output to \"file\"\n" | ||||
"\t -P spec\t allocate a process-private sampling PMC\n" | "\t -P spec\t allocate a process-private sampling PMC\n" | ||||
"\t -R file\t read events from \"file\"\n" | "\t -R file\t read events from \"file\"\n" | ||||
"\t -S spec\t allocate a system-wide sampling PMC\n" | "\t -S spec\t allocate a system-wide sampling PMC\n" | ||||
"\t -T\t\t start in top mode\n" | "\t -T\t\t start in top mode\n" | ||||
"\t -W\t\t (toggle) show counts per context switch\n" | "\t -W\t\t (toggle) show counts per context switch\n" | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | main(int argc, char **argv) | ||||
int c, check_driver_stats, current_sampling_count; | int c, check_driver_stats, current_sampling_count; | ||||
int do_callchain, do_descendants, do_logproccsw, do_logprocexit; | int do_callchain, do_descendants, do_logproccsw, do_logprocexit; | ||||
int do_print, do_read; | int do_print, do_read; | ||||
size_t len; | size_t len; | ||||
int graphdepth; | int graphdepth; | ||||
int pipefd[2], rfd; | int pipefd[2], rfd; | ||||
int use_cumulative_counts; | int use_cumulative_counts; | ||||
short cf, cb; | short cf, cb; | ||||
char *end, *tmp; | char *end, *modpath, *mp, *tmp; | ||||
const char *errmsg, *graphfilename; | const char *errmsg, *graphfilename; | ||||
enum pmcstat_state runstate; | enum pmcstat_state runstate; | ||||
struct pmc_driverstats ds_start, ds_end; | struct pmc_driverstats ds_start, ds_end; | ||||
struct pmcstat_ev *ev; | struct pmcstat_ev *ev; | ||||
struct pmcstat_path *pp; | |||||
struct sigaction sa; | struct sigaction sa; | ||||
struct kevent kev; | struct kevent kev; | ||||
struct winsize ws; | struct winsize ws; | ||||
struct stat sb; | struct stat sb; | ||||
char buffer[PATH_MAX]; | char buffer[PATH_MAX]; | ||||
check_driver_stats = 0; | check_driver_stats = 0; | ||||
current_sampling_count = DEFAULT_SAMPLE_COUNT; | current_sampling_count = DEFAULT_SAMPLE_COUNT; | ||||
Show All 21 Lines | main(int argc, char **argv) | ||||
args.pa_ctdumpinstr = 1; | args.pa_ctdumpinstr = 1; | ||||
args.pa_topmode = PMCSTAT_TOP_DELTA; | args.pa_topmode = PMCSTAT_TOP_DELTA; | ||||
args.pa_toptty = 0; | args.pa_toptty = 0; | ||||
args.pa_topcolor = 0; | args.pa_topcolor = 0; | ||||
args.pa_mergepmc = 0; | args.pa_mergepmc = 0; | ||||
args.pa_duration = 0.0; | args.pa_duration = 0.0; | ||||
STAILQ_INIT(&args.pa_events); | STAILQ_INIT(&args.pa_events); | ||||
SLIST_INIT(&args.pa_targets); | SLIST_INIT(&args.pa_targets); | ||||
STAILQ_INIT(&args.pa_modules); | |||||
bzero(&ds_start, sizeof(ds_start)); | bzero(&ds_start, sizeof(ds_start)); | ||||
bzero(&ds_end, sizeof(ds_end)); | bzero(&ds_end, sizeof(ds_end)); | ||||
ev = NULL; | ev = NULL; | ||||
CPU_ZERO(&cpumask); | CPU_ZERO(&cpumask); | ||||
/* Default to using the running system kernel. */ | /* Default to using the running system kernel. */ | ||||
len = 0; | len = 0; | ||||
if (sysctlbyname("kern.bootfile", NULL, &len, NULL, 0) == -1) | if (sysctlbyname("kern.bootfile", NULL, &len, NULL, 0) == -1) | ||||
err(EX_OSERR, "ERROR: Cannot determine path of running kernel"); | err(EX_OSERR, "ERROR: Cannot determine path of running kernel"); | ||||
args.pa_kernel = malloc(len); | args.pa_kernel = malloc(len); | ||||
if (args.pa_kernel == NULL) | if (args.pa_kernel == NULL) | ||||
errx(EX_SOFTWARE, "ERROR: Out of memory."); | errx(EX_SOFTWARE, "ERROR: Out of memory."); | ||||
if (sysctlbyname("kern.bootfile", args.pa_kernel, &len, NULL, 0) == -1) | if (sysctlbyname("kern.bootfile", args.pa_kernel, &len, NULL, 0) == -1) | ||||
err(EX_OSERR, "ERROR: Cannot determine path of running kernel"); | err(EX_OSERR, "ERROR: Cannot determine path of running kernel"); | ||||
len = 0; | |||||
if (sysctlbyname("kern.module_path", NULL, &len, NULL, 0) == -1) | |||||
err(EX_OSERR, | |||||
"ERROR: Cannot determine running kernel module paths"); | |||||
args.pa_module_path = malloc(len); | |||||
if (args.pa_module_path == NULL) | |||||
errx(EX_SOFTWARE, "ERROR: Out of memory."); | |||||
if (sysctlbyname("kern.module_path", args.pa_module_path, &len, NULL, | |||||
0) == -1) | |||||
err(EX_OSERR, | |||||
"ERROR: Cannot determine running kernel module paths"); | |||||
/* | /* | ||||
* The initial CPU mask specifies the root mask of this process | * The initial CPU mask specifies the root mask of this process | ||||
* which is usually all CPUs in the system. | * which is usually all CPUs in the system. | ||||
*/ | */ | ||||
if (cpuset_getaffinity(CPU_LEVEL_ROOT, CPU_WHICH_PID, -1, | if (cpuset_getaffinity(CPU_LEVEL_ROOT, CPU_WHICH_PID, -1, | ||||
sizeof(rootmask), &rootmask) == -1) | sizeof(rootmask), &rootmask) == -1) | ||||
err(EX_OSERR, "ERROR: Cannot determine the root set of CPUs"); | err(EX_OSERR, "ERROR: Cannot determine the root set of CPUs"); | ||||
CPU_COPY(&rootmask, &cpumask); | CPU_COPY(&rootmask, &cpumask); | ||||
while ((option = getopt(argc, argv, | while ((option = getopt(argc, argv, | ||||
"CD:EF:G:M:NO:P:R:S:TWa:c:def:gk:l:m:n:o:p:qr:s:t:vw:z:")) != -1) | "CD:EF:G:K:M:NO:P:R:S:TWa:c:def:gk:l:m:n:o:p:qr:s:t:vw:z:")) != -1) | ||||
switch (option) { | switch (option) { | ||||
case 'a': /* Annotate + callgraph */ | case 'a': /* Annotate + callgraph */ | ||||
args.pa_flags |= FLAG_DO_ANNOTATE; | args.pa_flags |= FLAG_DO_ANNOTATE; | ||||
args.pa_plugin = PMCSTAT_PL_ANNOTATE_CG; | args.pa_plugin = PMCSTAT_PL_ANNOTATE_CG; | ||||
graphfilename = optarg; | graphfilename = optarg; | ||||
break; | break; | ||||
case 'C': /* cumulative values */ | case 'C': /* cumulative values */ | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | case 'k': /* pathname to the kernel */ | ||||
free(args.pa_kernel); | free(args.pa_kernel); | ||||
args.pa_kernel = strdup(optarg); | args.pa_kernel = strdup(optarg); | ||||
if (args.pa_kernel == NULL) | if (args.pa_kernel == NULL) | ||||
errx(EX_SOFTWARE, "ERROR: Out of memory"); | errx(EX_SOFTWARE, "ERROR: Out of memory"); | ||||
args.pa_required |= FLAG_DO_ANALYSIS; | args.pa_required |= FLAG_DO_ANALYSIS; | ||||
args.pa_flags |= FLAG_HAS_KERNELPATH; | args.pa_flags |= FLAG_HAS_KERNELPATH; | ||||
break; | break; | ||||
case 'K': /* paths to kernel modules */ | |||||
free(args.pa_module_path); | |||||
args.pa_module_path = strdup(optarg); | |||||
if (args.pa_module_path == NULL) | |||||
errx(EX_SOFTWARE, "ERROR: Out of memory"); | |||||
break; | |||||
case 'l': /* time duration in seconds */ | case 'l': /* time duration in seconds */ | ||||
duration = strtod(optarg, &end); | duration = strtod(optarg, &end); | ||||
if (*end != '\0' || duration <= 0) | if (*end != '\0' || duration <= 0) | ||||
errx(EX_USAGE, "ERROR: Illegal duration time " | errx(EX_USAGE, "ERROR: Illegal duration time " | ||||
"value \"%s\".", optarg); | "value \"%s\".", optarg); | ||||
args.pa_flags |= FLAG_HAS_DURATION; | args.pa_flags |= FLAG_HAS_DURATION; | ||||
args.pa_duration = duration; | args.pa_duration = duration; | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 382 Lines • ▼ Show 20 Lines | (void) snprintf(buffer, sizeof(buffer), "%s%s", | ||||
args.pa_fsroot, args.pa_kernel); | args.pa_fsroot, args.pa_kernel); | ||||
if (stat(buffer, &sb) < 0) | if (stat(buffer, &sb) < 0) | ||||
err(EX_OSERR, "ERROR: Cannot stat \"%s\"", | err(EX_OSERR, "ERROR: Cannot stat \"%s\"", | ||||
buffer); | buffer); | ||||
if (!S_ISDIR(sb.st_mode)) | if (!S_ISDIR(sb.st_mode)) | ||||
errx(EX_USAGE, | errx(EX_USAGE, | ||||
"ERROR: \"%s\" is not a directory.", | "ERROR: \"%s\" is not a directory.", | ||||
buffer); | buffer); | ||||
} | |||||
/* | |||||
* Build the kernel modules pathname list | |||||
*/ | |||||
mp = args.pa_module_path; | |||||
while ((modpath = strsep(&mp, ":;")) != NULL) { | |||||
Not Done Inline ActionsThe man page says colon-separated, but it would probably be worth telling the user that semicolons can be used also (and that is what kern.module_path uses, for some reason I can't fathom). wblock: The man page says colon-separated, but it would probably be worth telling the user that… | |||||
if (*modpath == '\0') | |||||
continue; | |||||
pp = malloc(sizeof(*pp)); | |||||
if (pp == NULL) | |||||
errx(EX_SOFTWARE, "ERROR: Out of memory."); | |||||
pp->pp_path = modpath; | |||||
STAILQ_INSERT_TAIL(&args.pa_modules, pp, pp_next); | |||||
} | } | ||||
/* | /* | ||||
Not Done Inline ActionsThinking about it, I wonder if this loop should ensure that each path component obtained is a fully qualified path and not relative. stevek: Thinking about it, I wonder if this loop should ensure that each path component obtained is a… | |||||
* If we have a callgraph be created, select the outputfile. | * If we have a callgraph be created, select the outputfile. | ||||
*/ | */ | ||||
if (args.pa_flags & FLAG_DO_CALLGRAPHS) { | if (args.pa_flags & FLAG_DO_CALLGRAPHS) { | ||||
if (strcmp(graphfilename, "-") == 0) | if (strcmp(graphfilename, "-") == 0) | ||||
args.pa_graphfile = args.pa_printfile; | args.pa_graphfile = args.pa_printfile; | ||||
else { | else { | ||||
args.pa_graphfile = fopen(graphfilename, "w"); | args.pa_graphfile = fopen(graphfilename, "w"); | ||||
if (args.pa_graphfile == NULL) | if (args.pa_graphfile == NULL) | ||||
▲ Show 20 Lines • Show All 426 Lines • Show Last 20 Lines |