Deleted Added
full compact
pmcstat.c (186425) pmcstat.c (203790)
1/*-
2 * Copyright (c) 2003-2008, Joseph Koshy
3 * Copyright (c) 2007 The FreeBSD Foundation
4 * All rights reserved.
5 *
6 * Portions of this software were developed by A. Joseph Koshy under
7 * sponsorship from the FreeBSD Foundation and Google, Inc.
8 *

--- 15 unchanged lines hidden (view full) ---

24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2003-2008, Joseph Koshy
3 * Copyright (c) 2007 The FreeBSD Foundation
4 * All rights reserved.
5 *
6 * Portions of this software were developed by A. Joseph Koshy under
7 * sponsorship from the FreeBSD Foundation and Google, Inc.
8 *

--- 15 unchanged lines hidden (view full) ---

24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/usr.sbin/pmcstat/pmcstat.c 186425 2008-12-23 12:08:06Z jkoshy $");
32__FBSDID("$FreeBSD: head/usr.sbin/pmcstat/pmcstat.c 203790 2010-02-11 22:51:44Z fabient $");
33
34#include <sys/types.h>
35#include <sys/event.h>
36#include <sys/param.h>
37#include <sys/queue.h>
38#include <sys/socket.h>
39#include <sys/stat.h>
40#include <sys/sysctl.h>
41#include <sys/time.h>
42#include <sys/ttycom.h>
43#include <sys/user.h>
44#include <sys/wait.h>
45
46#include <assert.h>
33
34#include <sys/types.h>
35#include <sys/event.h>
36#include <sys/param.h>
37#include <sys/queue.h>
38#include <sys/socket.h>
39#include <sys/stat.h>
40#include <sys/sysctl.h>
41#include <sys/time.h>
42#include <sys/ttycom.h>
43#include <sys/user.h>
44#include <sys/wait.h>
45
46#include <assert.h>
47#include <curses.h>
47#include <err.h>
48#include <errno.h>
49#include <fcntl.h>
50#include <kvm.h>
51#include <libgen.h>
52#include <limits.h>
53#include <math.h>
54#include <pmc.h>

--- 46 unchanged lines hidden (view full) ---

101 *
102 * After this point normal processing can happen.
103 */
104
105/* Globals */
106
107int pmcstat_interrupt = 0;
108int pmcstat_displayheight = DEFAULT_DISPLAY_HEIGHT;
48#include <err.h>
49#include <errno.h>
50#include <fcntl.h>
51#include <kvm.h>
52#include <libgen.h>
53#include <limits.h>
54#include <math.h>
55#include <pmc.h>

--- 46 unchanged lines hidden (view full) ---

102 *
103 * After this point normal processing can happen.
104 */
105
106/* Globals */
107
108int pmcstat_interrupt = 0;
109int pmcstat_displayheight = DEFAULT_DISPLAY_HEIGHT;
110int pmcstat_displaywidth = DEFAULT_DISPLAY_WIDTH;
109int pmcstat_sockpair[NSOCKPAIRFD];
110int pmcstat_kq;
111kvm_t *pmcstat_kvm;
112struct kinfo_proc *pmcstat_plist;
111int pmcstat_sockpair[NSOCKPAIRFD];
112int pmcstat_kq;
113kvm_t *pmcstat_kvm;
114struct kinfo_proc *pmcstat_plist;
115struct pmcstat_args args;
113
114void
116
117void
115pmcstat_attach_pmcs(struct pmcstat_args *a)
118pmcstat_attach_pmcs(void)
116{
117 struct pmcstat_ev *ev;
118 struct pmcstat_target *pt;
119 int count;
120
121 /* Attach all process PMCs to target processes. */
122 count = 0;
119{
120 struct pmcstat_ev *ev;
121 struct pmcstat_target *pt;
122 int count;
123
124 /* Attach all process PMCs to target processes. */
125 count = 0;
123 STAILQ_FOREACH(ev, &a->pa_events, ev_next) {
126 STAILQ_FOREACH(ev, &args.pa_events, ev_next) {
124 if (PMC_IS_SYSTEM_MODE(ev->ev_mode))
125 continue;
127 if (PMC_IS_SYSTEM_MODE(ev->ev_mode))
128 continue;
126 SLIST_FOREACH(pt, &a->pa_targets, pt_next)
129 SLIST_FOREACH(pt, &args.pa_targets, pt_next)
127 if (pmc_attach(ev->ev_pmcid, pt->pt_pid) == 0)
128 count++;
129 else if (errno != ESRCH)
130 err(EX_OSERR, "ERROR: cannot attach pmc "
131 "\"%s\" to process %d", ev->ev_name,
132 (int) pt->pt_pid);
133 }
134
135 if (count == 0)
136 errx(EX_DATAERR, "ERROR: No processes were attached to.");
137}
138
139
140void
130 if (pmc_attach(ev->ev_pmcid, pt->pt_pid) == 0)
131 count++;
132 else if (errno != ESRCH)
133 err(EX_OSERR, "ERROR: cannot attach pmc "
134 "\"%s\" to process %d", ev->ev_name,
135 (int) pt->pt_pid);
136 }
137
138 if (count == 0)
139 errx(EX_DATAERR, "ERROR: No processes were attached to.");
140}
141
142
143void
141pmcstat_cleanup(struct pmcstat_args *a)
144pmcstat_cleanup(void)
142{
143 struct pmcstat_ev *ev, *tmp;
144
145 /* release allocated PMCs. */
145{
146 struct pmcstat_ev *ev, *tmp;
147
148 /* release allocated PMCs. */
146 STAILQ_FOREACH_SAFE(ev, &a->pa_events, ev_next, tmp)
149 STAILQ_FOREACH_SAFE(ev, &args.pa_events, ev_next, tmp)
147 if (ev->ev_pmcid != PMC_ID_INVALID) {
148 if (pmc_stop(ev->ev_pmcid) < 0)
149 err(EX_OSERR, "ERROR: cannot stop pmc 0x%x "
150 "\"%s\"", ev->ev_pmcid, ev->ev_name);
151 if (pmc_release(ev->ev_pmcid) < 0)
152 err(EX_OSERR, "ERROR: cannot release pmc "
153 "0x%x \"%s\"", ev->ev_pmcid, ev->ev_name);
154 free(ev->ev_name);
155 free(ev->ev_spec);
150 if (ev->ev_pmcid != PMC_ID_INVALID) {
151 if (pmc_stop(ev->ev_pmcid) < 0)
152 err(EX_OSERR, "ERROR: cannot stop pmc 0x%x "
153 "\"%s\"", ev->ev_pmcid, ev->ev_name);
154 if (pmc_release(ev->ev_pmcid) < 0)
155 err(EX_OSERR, "ERROR: cannot release pmc "
156 "0x%x \"%s\"", ev->ev_pmcid, ev->ev_name);
157 free(ev->ev_name);
158 free(ev->ev_spec);
156 STAILQ_REMOVE(&a->pa_events, ev, pmcstat_ev, ev_next);
159 STAILQ_REMOVE(&args.pa_events, ev, pmcstat_ev, ev_next);
157 free(ev);
158 }
159
160 /* de-configure the log file if present. */
160 free(ev);
161 }
162
163 /* de-configure the log file if present. */
161 if (a->pa_flags & (FLAG_HAS_PIPE | FLAG_HAS_OUTPUT_LOGFILE))
164 if (args.pa_flags & (FLAG_HAS_PIPE | FLAG_HAS_OUTPUT_LOGFILE))
162 (void) pmc_configure_logfile(-1);
163
165 (void) pmc_configure_logfile(-1);
166
164 if (a->pa_logparser) {
165 pmclog_close(a->pa_logparser);
166 a->pa_logparser = NULL;
167 if (args.pa_logparser) {
168 pmclog_close(args.pa_logparser);
169 args.pa_logparser = NULL;
167 }
168
170 }
171
169 if (a->pa_flags & (FLAG_HAS_PIPE | FLAG_HAS_OUTPUT_LOGFILE))
170 pmcstat_shutdown_logging(a);
172 if (args.pa_flags & (FLAG_HAS_PIPE | FLAG_HAS_OUTPUT_LOGFILE))
173 pmcstat_shutdown_logging();
171}
172
173void
174}
175
176void
174pmcstat_clone_event_descriptor(struct pmcstat_args *a, struct pmcstat_ev *ev,
177pmcstat_clone_event_descriptor(struct pmcstat_ev *ev,
175 uint32_t cpumask)
176{
177 int cpu;
178 struct pmcstat_ev *ev_clone;
179
180 while ((cpu = ffs(cpumask)) > 0) {
181 cpu--;
182

--- 6 unchanged lines hidden (view full) ---

189 ev_clone->ev_cumulative = ev->ev_cumulative;
190 ev_clone->ev_flags = ev->ev_flags;
191 ev_clone->ev_mode = ev->ev_mode;
192 ev_clone->ev_name = strdup(ev->ev_name);
193 ev_clone->ev_pmcid = ev->ev_pmcid;
194 ev_clone->ev_saved = ev->ev_saved;
195 ev_clone->ev_spec = strdup(ev->ev_spec);
196
178 uint32_t cpumask)
179{
180 int cpu;
181 struct pmcstat_ev *ev_clone;
182
183 while ((cpu = ffs(cpumask)) > 0) {
184 cpu--;
185

--- 6 unchanged lines hidden (view full) ---

192 ev_clone->ev_cumulative = ev->ev_cumulative;
193 ev_clone->ev_flags = ev->ev_flags;
194 ev_clone->ev_mode = ev->ev_mode;
195 ev_clone->ev_name = strdup(ev->ev_name);
196 ev_clone->ev_pmcid = ev->ev_pmcid;
197 ev_clone->ev_saved = ev->ev_saved;
198 ev_clone->ev_spec = strdup(ev->ev_spec);
199
197 STAILQ_INSERT_TAIL(&a->pa_events, ev_clone, ev_next);
200 STAILQ_INSERT_TAIL(&args.pa_events, ev_clone, ev_next);
198
199 cpumask &= ~(1 << cpu);
200 }
201}
202
203void
201
202 cpumask &= ~(1 << cpu);
203 }
204}
205
206void
204pmcstat_create_process(struct pmcstat_args *a)
207pmcstat_create_process(void)
205{
206 char token;
207 pid_t pid;
208 struct kevent kev;
209 struct pmcstat_target *pt;
210
211 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pmcstat_sockpair) < 0)
212 err(EX_OSERR, "ERROR: cannot create socket pair");

--- 11 unchanged lines hidden (view full) ---

224 err(EX_OSERR, "ERROR (child): cannot write token");
225
226 /* Wait for our parent to signal us to start. */
227 if (read(pmcstat_sockpair[CHILDSOCKET], &token, 1) < 0)
228 err(EX_OSERR, "ERROR (child): cannot read token");
229 (void) close(pmcstat_sockpair[CHILDSOCKET]);
230
231 /* exec() the program requested */
208{
209 char token;
210 pid_t pid;
211 struct kevent kev;
212 struct pmcstat_target *pt;
213
214 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pmcstat_sockpair) < 0)
215 err(EX_OSERR, "ERROR: cannot create socket pair");

--- 11 unchanged lines hidden (view full) ---

227 err(EX_OSERR, "ERROR (child): cannot write token");
228
229 /* Wait for our parent to signal us to start. */
230 if (read(pmcstat_sockpair[CHILDSOCKET], &token, 1) < 0)
231 err(EX_OSERR, "ERROR (child): cannot read token");
232 (void) close(pmcstat_sockpair[CHILDSOCKET]);
233
234 /* exec() the program requested */
232 execvp(*a->pa_argv, a->pa_argv);
235 execvp(*args.pa_argv, args.pa_argv);
233 /* and if that fails, notify the parent */
234 kill(getppid(), SIGCHLD);
236 /* and if that fails, notify the parent */
237 kill(getppid(), SIGCHLD);
235 err(EX_OSERR, "ERROR: execvp \"%s\" failed", *a->pa_argv);
238 err(EX_OSERR, "ERROR: execvp \"%s\" failed", *args.pa_argv);
236 /*NOTREACHED*/
237
238 default: /* parent */
239 (void) close(pmcstat_sockpair[CHILDSOCKET]);
240 break;
241 }
242
243 /* Ask to be notified via a kevent when the target process exits. */
244 EV_SET(&kev, pid, EVFILT_PROC, EV_ADD|EV_ONESHOT, NOTE_EXIT, 0,
245 NULL);
246 if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
247 err(EX_OSERR, "ERROR: cannot monitor child process %d", pid);
248
249 if ((pt = malloc(sizeof(*pt))) == NULL)
250 errx(EX_SOFTWARE, "ERROR: Out of memory.");
251
252 pt->pt_pid = pid;
239 /*NOTREACHED*/
240
241 default: /* parent */
242 (void) close(pmcstat_sockpair[CHILDSOCKET]);
243 break;
244 }
245
246 /* Ask to be notified via a kevent when the target process exits. */
247 EV_SET(&kev, pid, EVFILT_PROC, EV_ADD|EV_ONESHOT, NOTE_EXIT, 0,
248 NULL);
249 if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
250 err(EX_OSERR, "ERROR: cannot monitor child process %d", pid);
251
252 if ((pt = malloc(sizeof(*pt))) == NULL)
253 errx(EX_SOFTWARE, "ERROR: Out of memory.");
254
255 pt->pt_pid = pid;
253 SLIST_INSERT_HEAD(&a->pa_targets, pt, pt_next);
256 SLIST_INSERT_HEAD(&args.pa_targets, pt, pt_next);
254
255 /* Wait for the child to signal that its ready to go. */
256 if (read(pmcstat_sockpair[PARENTSOCKET], &token, 1) < 0)
257 err(EX_OSERR, "ERROR (parent): cannot read token");
258
259 return;
260}
261
262void
257
258 /* Wait for the child to signal that its ready to go. */
259 if (read(pmcstat_sockpair[PARENTSOCKET], &token, 1) < 0)
260 err(EX_OSERR, "ERROR (parent): cannot read token");
261
262 return;
263}
264
265void
263pmcstat_find_targets(struct pmcstat_args *a, const char *spec)
266pmcstat_find_targets(const char *spec)
264{
265 int n, nproc, pid, rv;
266 struct pmcstat_target *pt;
267 char errbuf[_POSIX2_LINE_MAX], *end;
268 static struct kinfo_proc *kp;
269 regex_t reg;
270 regmatch_t regmatch;
271
272 /* First check if we've been given a process id. */
273 pid = strtol(spec, &end, 0);
274 if (end != spec && pid >= 0) {
275 if ((pt = malloc(sizeof(*pt))) == NULL)
276 goto outofmemory;
277 pt->pt_pid = pid;
267{
268 int n, nproc, pid, rv;
269 struct pmcstat_target *pt;
270 char errbuf[_POSIX2_LINE_MAX], *end;
271 static struct kinfo_proc *kp;
272 regex_t reg;
273 regmatch_t regmatch;
274
275 /* First check if we've been given a process id. */
276 pid = strtol(spec, &end, 0);
277 if (end != spec && pid >= 0) {
278 if ((pt = malloc(sizeof(*pt))) == NULL)
279 goto outofmemory;
280 pt->pt_pid = pid;
278 SLIST_INSERT_HEAD(&a->pa_targets, pt, pt_next);
281 SLIST_INSERT_HEAD(&args.pa_targets, pt, pt_next);
279 return;
280 }
281
282 /* Otherwise treat arg as a regular expression naming processes. */
283 if (pmcstat_kvm == NULL) {
284 if ((pmcstat_kvm = kvm_openfiles(NULL, "/dev/null", NULL, 0,
285 errbuf)) == NULL)
286 err(EX_OSERR, "ERROR: Cannot open kernel \"%s\"",

--- 10 unchanged lines hidden (view full) ---

297 spec, errbuf);
298 }
299
300 for (n = 0, kp = pmcstat_plist; n < nproc; n++, kp++) {
301 if ((rv = regexec(&reg, kp->ki_comm, 1, &regmatch, 0)) == 0) {
302 if ((pt = malloc(sizeof(*pt))) == NULL)
303 goto outofmemory;
304 pt->pt_pid = kp->ki_pid;
282 return;
283 }
284
285 /* Otherwise treat arg as a regular expression naming processes. */
286 if (pmcstat_kvm == NULL) {
287 if ((pmcstat_kvm = kvm_openfiles(NULL, "/dev/null", NULL, 0,
288 errbuf)) == NULL)
289 err(EX_OSERR, "ERROR: Cannot open kernel \"%s\"",

--- 10 unchanged lines hidden (view full) ---

300 spec, errbuf);
301 }
302
303 for (n = 0, kp = pmcstat_plist; n < nproc; n++, kp++) {
304 if ((rv = regexec(&reg, kp->ki_comm, 1, &regmatch, 0)) == 0) {
305 if ((pt = malloc(sizeof(*pt))) == NULL)
306 goto outofmemory;
307 pt->pt_pid = kp->ki_pid;
305 SLIST_INSERT_HEAD(&a->pa_targets, pt, pt_next);
308 SLIST_INSERT_HEAD(&args.pa_targets, pt, pt_next);
306 } else if (rv != REG_NOMATCH) {
307 regerror(rv, &reg, errbuf, sizeof(errbuf));
308 errx(EX_SOFTWARE, "ERROR: Regex evalation failed: %s",
309 errbuf);
310 }
311 }
312
313 regfree(&reg);

--- 24 unchanged lines hidden (view full) ---

338 cpumask |= (1 << cpu);
339 s = end + strspn(end, ", \t");
340 } while (*s);
341
342 return (cpumask);
343}
344
345void
309 } else if (rv != REG_NOMATCH) {
310 regerror(rv, &reg, errbuf, sizeof(errbuf));
311 errx(EX_SOFTWARE, "ERROR: Regex evalation failed: %s",
312 errbuf);
313 }
314 }
315
316 regfree(&reg);

--- 24 unchanged lines hidden (view full) ---

341 cpumask |= (1 << cpu);
342 s = end + strspn(end, ", \t");
343 } while (*s);
344
345 return (cpumask);
346}
347
348void
346pmcstat_kill_process(struct pmcstat_args *a)
349pmcstat_kill_process(void)
347{
348 struct pmcstat_target *pt;
349
350{
351 struct pmcstat_target *pt;
352
350 assert(a->pa_flags & FLAG_HAS_COMMANDLINE);
353 assert(args.pa_flags & FLAG_HAS_COMMANDLINE);
351
352 /*
353 * If a command line was specified, it would be the very first
354 * in the list, before any other processes specified by -t.
355 */
354
355 /*
356 * If a command line was specified, it would be the very first
357 * in the list, before any other processes specified by -t.
358 */
356 pt = SLIST_FIRST(&a->pa_targets);
359 pt = SLIST_FIRST(&args.pa_targets);
357 assert(pt != NULL);
358
359 if (kill(pt->pt_pid, SIGINT) != 0)
360 err(EX_OSERR, "ERROR: cannot signal child process");
361}
362
363void
360 assert(pt != NULL);
361
362 if (kill(pt->pt_pid, SIGINT) != 0)
363 err(EX_OSERR, "ERROR: cannot signal child process");
364}
365
366void
364pmcstat_start_pmcs(struct pmcstat_args *a)
367pmcstat_start_pmcs(void)
365{
366 struct pmcstat_ev *ev;
367
368 STAILQ_FOREACH(ev, &args.pa_events, ev_next) {
369
370 assert(ev->ev_pmcid != PMC_ID_INVALID);
371
372 if (pmc_start(ev->ev_pmcid) < 0) {
373 warn("ERROR: Cannot start pmc 0x%x \"%s\"",
374 ev->ev_pmcid, ev->ev_name);
368{
369 struct pmcstat_ev *ev;
370
371 STAILQ_FOREACH(ev, &args.pa_events, ev_next) {
372
373 assert(ev->ev_pmcid != PMC_ID_INVALID);
374
375 if (pmc_start(ev->ev_pmcid) < 0) {
376 warn("ERROR: Cannot start pmc 0x%x \"%s\"",
377 ev->ev_pmcid, ev->ev_name);
375 pmcstat_cleanup(a);
378 pmcstat_cleanup();
376 exit(EX_OSERR);
377 }
378 }
379
380}
381
382void
379 exit(EX_OSERR);
380 }
381 }
382
383}
384
385void
383pmcstat_print_headers(struct pmcstat_args *a)
386pmcstat_print_headers(void)
384{
385 struct pmcstat_ev *ev;
386 int c, w;
387
387{
388 struct pmcstat_ev *ev;
389 int c, w;
390
388 (void) fprintf(a->pa_printfile, PRINT_HEADER_PREFIX);
391 (void) fprintf(args.pa_printfile, PRINT_HEADER_PREFIX);
389
392
390 STAILQ_FOREACH(ev, &a->pa_events, ev_next) {
393 STAILQ_FOREACH(ev, &args.pa_events, ev_next) {
391 if (PMC_IS_SAMPLING_MODE(ev->ev_mode))
392 continue;
393
394 c = PMC_IS_SYSTEM_MODE(ev->ev_mode) ? 's' : 'p';
395
396 if (ev->ev_fieldskip != 0)
394 if (PMC_IS_SAMPLING_MODE(ev->ev_mode))
395 continue;
396
397 c = PMC_IS_SYSTEM_MODE(ev->ev_mode) ? 's' : 'p';
398
399 if (ev->ev_fieldskip != 0)
397 (void) fprintf(a->pa_printfile, "%*s",
400 (void) fprintf(args.pa_printfile, "%*s",
398 ev->ev_fieldskip, "");
399 w = ev->ev_fieldwidth - ev->ev_fieldskip - 2;
400
401 if (c == 's')
401 ev->ev_fieldskip, "");
402 w = ev->ev_fieldwidth - ev->ev_fieldskip - 2;
403
404 if (c == 's')
402 (void) fprintf(a->pa_printfile, "s/%02d/%-*s ",
405 (void) fprintf(args.pa_printfile, "s/%02d/%-*s ",
403 ev->ev_cpu, w-3, ev->ev_name);
404 else
406 ev->ev_cpu, w-3, ev->ev_name);
407 else
405 (void) fprintf(a->pa_printfile, "p/%*s ", w,
408 (void) fprintf(args.pa_printfile, "p/%*s ", w,
406 ev->ev_name);
407 }
408
409 ev->ev_name);
410 }
411
409 (void) fflush(a->pa_printfile);
412 (void) fflush(args.pa_printfile);
410}
411
412void
413}
414
415void
413pmcstat_print_counters(struct pmcstat_args *a)
416pmcstat_print_counters(void)
414{
415 int extra_width;
416 struct pmcstat_ev *ev;
417 pmc_value_t value;
418
419 extra_width = sizeof(PRINT_HEADER_PREFIX) - 1;
420
417{
418 int extra_width;
419 struct pmcstat_ev *ev;
420 pmc_value_t value;
421
422 extra_width = sizeof(PRINT_HEADER_PREFIX) - 1;
423
421 STAILQ_FOREACH(ev, &a->pa_events, ev_next) {
424 STAILQ_FOREACH(ev, &args.pa_events, ev_next) {
422
423 /* skip sampling mode counters */
424 if (PMC_IS_SAMPLING_MODE(ev->ev_mode))
425 continue;
426
427 if (pmc_read(ev->ev_pmcid, &value) < 0)
428 err(EX_OSERR, "ERROR: Cannot read pmc "
429 "\"%s\"", ev->ev_name);
430
425
426 /* skip sampling mode counters */
427 if (PMC_IS_SAMPLING_MODE(ev->ev_mode))
428 continue;
429
430 if (pmc_read(ev->ev_pmcid, &value) < 0)
431 err(EX_OSERR, "ERROR: Cannot read pmc "
432 "\"%s\"", ev->ev_name);
433
431 (void) fprintf(a->pa_printfile, "%*ju ",
434 (void) fprintf(args.pa_printfile, "%*ju ",
432 ev->ev_fieldwidth + extra_width,
433 (uintmax_t) ev->ev_cumulative ? value :
434 (value - ev->ev_saved));
435
436 if (ev->ev_cumulative == 0)
437 ev->ev_saved = value;
438 extra_width = 0;
439 }
440
435 ev->ev_fieldwidth + extra_width,
436 (uintmax_t) ev->ev_cumulative ? value :
437 (value - ev->ev_saved));
438
439 if (ev->ev_cumulative == 0)
440 ev->ev_saved = value;
441 extra_width = 0;
442 }
443
441 (void) fflush(a->pa_printfile);
444 (void) fflush(args.pa_printfile);
442}
443
444/*
445 * Print output
446 */
447
448void
445}
446
447/*
448 * Print output
449 */
450
451void
449pmcstat_print_pmcs(struct pmcstat_args *a)
452pmcstat_print_pmcs(void)
450{
451 static int linecount = 0;
452
453 /* check if we need to print a header line */
454 if (++linecount > pmcstat_displayheight) {
453{
454 static int linecount = 0;
455
456 /* check if we need to print a header line */
457 if (++linecount > pmcstat_displayheight) {
455 (void) fprintf(a->pa_printfile, "\n");
458 (void) fprintf(args.pa_printfile, "\n");
456 linecount = 1;
457 }
458 if (linecount == 1)
459 linecount = 1;
460 }
461 if (linecount == 1)
459 pmcstat_print_headers(a);
460 (void) fprintf(a->pa_printfile, "\n");
462 pmcstat_print_headers();
463 (void) fprintf(args.pa_printfile, "\n");
461
464
462 pmcstat_print_counters(a);
465 pmcstat_print_counters();
463
464 return;
465}
466
467/*
468 * Do process profiling
469 *
470 * If a pid was specified, attach each allocated PMC to the target

--- 17 unchanged lines hidden (view full) ---

488 errx(EX_USAGE,
489 "[options] [commandline]\n"
490 "\t Measure process and/or system performance using hardware\n"
491 "\t performance monitoring counters.\n"
492 "\t Options include:\n"
493 "\t -C\t\t (toggle) show cumulative counts\n"
494 "\t -D path\t create profiles in directory \"path\"\n"
495 "\t -E\t\t (toggle) show counts at process exit\n"
466
467 return;
468}
469
470/*
471 * Do process profiling
472 *
473 * If a pid was specified, attach each allocated PMC to the target

--- 17 unchanged lines hidden (view full) ---

491 errx(EX_USAGE,
492 "[options] [commandline]\n"
493 "\t Measure process and/or system performance using hardware\n"
494 "\t performance monitoring counters.\n"
495 "\t Options include:\n"
496 "\t -C\t\t (toggle) show cumulative counts\n"
497 "\t -D path\t create profiles in directory \"path\"\n"
498 "\t -E\t\t (toggle) show counts at process exit\n"
499 "\t -F file\t write a system-wide callgraph (Kcachegrind format)"
500 " to \"file\"\n"
496 "\t -G file\t write a system-wide callgraph to \"file\"\n"
497 "\t -M file\t print executable/gmon file map to \"file\"\n"
498 "\t -N\t\t (toggle) capture callchains\n"
499 "\t -O file\t send log output to \"file\"\n"
500 "\t -P spec\t allocate a process-private sampling PMC\n"
501 "\t -R file\t read events from \"file\"\n"
502 "\t -S spec\t allocate a system-wide sampling PMC\n"
501 "\t -G file\t write a system-wide callgraph to \"file\"\n"
502 "\t -M file\t print executable/gmon file map to \"file\"\n"
503 "\t -N\t\t (toggle) capture callchains\n"
504 "\t -O file\t send log output to \"file\"\n"
505 "\t -P spec\t allocate a process-private sampling PMC\n"
506 "\t -R file\t read events from \"file\"\n"
507 "\t -S spec\t allocate a system-wide sampling PMC\n"
508 "\t -T\t\t start in top mode\n"
503 "\t -W\t\t (toggle) show counts per context switch\n"
504 "\t -c cpu-list\t set cpus for subsequent system-wide PMCs\n"
505 "\t -d\t\t (toggle) track descendants\n"
509 "\t -W\t\t (toggle) show counts per context switch\n"
510 "\t -c cpu-list\t set cpus for subsequent system-wide PMCs\n"
511 "\t -d\t\t (toggle) track descendants\n"
512 "\t -f spec\t pass \"spec\" to as plugin option\n"
506 "\t -g\t\t produce gprof(1) compatible profiles\n"
507 "\t -k dir\t\t set the path to the kernel\n"
508 "\t -n rate\t set sampling rate\n"
509 "\t -o file\t send print output to \"file\"\n"
510 "\t -p spec\t allocate a process-private counting PMC\n"
511 "\t -q\t\t suppress verbosity\n"
512 "\t -r fsroot\t specify FS root directory\n"
513 "\t -s spec\t allocate a system-wide counting PMC\n"
514 "\t -t process-spec attach to running processes matching "
515 "\"process-spec\"\n"
516 "\t -v\t\t increase verbosity\n"
517 "\t -w secs\t set printing time interval\n"
518 "\t -z depth\t limit callchain display depth"
519 );
520}
521
522/*
513 "\t -g\t\t produce gprof(1) compatible profiles\n"
514 "\t -k dir\t\t set the path to the kernel\n"
515 "\t -n rate\t set sampling rate\n"
516 "\t -o file\t send print output to \"file\"\n"
517 "\t -p spec\t allocate a process-private counting PMC\n"
518 "\t -q\t\t suppress verbosity\n"
519 "\t -r fsroot\t specify FS root directory\n"
520 "\t -s spec\t allocate a system-wide counting PMC\n"
521 "\t -t process-spec attach to running processes matching "
522 "\"process-spec\"\n"
523 "\t -v\t\t increase verbosity\n"
524 "\t -w secs\t set printing time interval\n"
525 "\t -z depth\t limit callchain display depth"
526 );
527}
528
529/*
530 * At exit handler for top mode
531 */
532
533void
534pmcstat_topexit(void)
535{
536 if (!args.pa_toptty)
537 return;
538
539 /*
540 * Shutdown ncurses.
541 */
542 clrtoeol();
543 refresh();
544 endwin();
545}
546
547/*
523 * Main
524 */
525
526int
527main(int argc, char **argv)
528{
529 double interval;
530 int option, npmc, ncpu, haltedcpus;
531 int c, check_driver_stats, current_cpu, current_sampling_count;
532 int do_callchain, do_descendants, do_logproccsw, do_logprocexit;
533 int do_print;
534 size_t dummy;
535 int graphdepth;
536 int pipefd[2];
537 int use_cumulative_counts;
548 * Main
549 */
550
551int
552main(int argc, char **argv)
553{
554 double interval;
555 int option, npmc, ncpu, haltedcpus;
556 int c, check_driver_stats, current_cpu, current_sampling_count;
557 int do_callchain, do_descendants, do_logproccsw, do_logprocexit;
558 int do_print;
559 size_t dummy;
560 int graphdepth;
561 int pipefd[2];
562 int use_cumulative_counts;
563 short cf, cb;
538 uint32_t cpumask;
539 char *end, *tmp;
540 const char *errmsg, *graphfilename;
541 enum pmcstat_state runstate;
542 struct pmc_driverstats ds_start, ds_end;
543 struct pmcstat_ev *ev;
544 struct sigaction sa;
545 struct kevent kev;

--- 19 unchanged lines hidden (view full) ---

565 args.pa_samplesdir = ".";
566 args.pa_printfile = stderr;
567 args.pa_graphdepth = DEFAULT_CALLGRAPH_DEPTH;
568 args.pa_graphfile = NULL;
569 args.pa_interval = DEFAULT_WAIT_INTERVAL;
570 args.pa_mapfilename = NULL;
571 args.pa_inputpath = NULL;
572 args.pa_outputpath = NULL;
564 uint32_t cpumask;
565 char *end, *tmp;
566 const char *errmsg, *graphfilename;
567 enum pmcstat_state runstate;
568 struct pmc_driverstats ds_start, ds_end;
569 struct pmcstat_ev *ev;
570 struct sigaction sa;
571 struct kevent kev;

--- 19 unchanged lines hidden (view full) ---

591 args.pa_samplesdir = ".";
592 args.pa_printfile = stderr;
593 args.pa_graphdepth = DEFAULT_CALLGRAPH_DEPTH;
594 args.pa_graphfile = NULL;
595 args.pa_interval = DEFAULT_WAIT_INTERVAL;
596 args.pa_mapfilename = NULL;
597 args.pa_inputpath = NULL;
598 args.pa_outputpath = NULL;
599 args.pa_pplugin = PMCSTAT_PL_NONE;
600 args.pa_plugin = PMCSTAT_PL_NONE;
601 args.pa_ctdumpinstr = 1;
602 args.pa_topmode = PMCSTAT_TOP_DELTA;
603 args.pa_toptty = 0;
604 args.pa_topcolor = 0;
605 args.pa_mergepmc = 0;
573 STAILQ_INIT(&args.pa_events);
574 SLIST_INIT(&args.pa_targets);
575 bzero(&ds_start, sizeof(ds_start));
576 bzero(&ds_end, sizeof(ds_end));
577 ev = NULL;
578
579 /*
580 * The initial CPU mask specifies all non-halted CPUS in the

--- 8 unchanged lines hidden (view full) ---

589 if (sysctlbyname("machdep.hlt_cpus", &haltedcpus, &dummy,
590 NULL, 0) < 0)
591 err(EX_OSERR, "ERROR: Cannot determine which CPUs are "
592 "halted");
593 cpumask &= ~haltedcpus;
594 }
595
596 while ((option = getopt(argc, argv,
606 STAILQ_INIT(&args.pa_events);
607 SLIST_INIT(&args.pa_targets);
608 bzero(&ds_start, sizeof(ds_start));
609 bzero(&ds_end, sizeof(ds_end));
610 ev = NULL;
611
612 /*
613 * The initial CPU mask specifies all non-halted CPUS in the

--- 8 unchanged lines hidden (view full) ---

622 if (sysctlbyname("machdep.hlt_cpus", &haltedcpus, &dummy,
623 NULL, 0) < 0)
624 err(EX_OSERR, "ERROR: Cannot determine which CPUs are "
625 "halted");
626 cpumask &= ~haltedcpus;
627 }
628
629 while ((option = getopt(argc, argv,
597 "CD:EG:M:NO:P:R:S:Wc:dgk:m:n:o:p:qr:s:t:vw:z:")) != -1)
630 "CD:EF:G:M:NO:P:R:S:TWc:df:gk:m:n:o:p:qr:s:t:vw:z:")) != -1)
598 switch (option) {
599 case 'C': /* cumulative values */
600 use_cumulative_counts = !use_cumulative_counts;
601 args.pa_required |= FLAG_HAS_COUNTING_PMCS;
602 break;
603
604 case 'c': /* CPU */
605

--- 17 unchanged lines hidden (view full) ---

623 args.pa_required |= FLAG_DO_GPROF;
624 break;
625
626 case 'd': /* toggle descendents */
627 do_descendants = !do_descendants;
628 args.pa_required |= FLAG_HAS_PROCESS_PMCS;
629 break;
630
631 switch (option) {
632 case 'C': /* cumulative values */
633 use_cumulative_counts = !use_cumulative_counts;
634 args.pa_required |= FLAG_HAS_COUNTING_PMCS;
635 break;
636
637 case 'c': /* CPU */
638

--- 17 unchanged lines hidden (view full) ---

656 args.pa_required |= FLAG_DO_GPROF;
657 break;
658
659 case 'd': /* toggle descendents */
660 do_descendants = !do_descendants;
661 args.pa_required |= FLAG_HAS_PROCESS_PMCS;
662 break;
663
664 case 'F': /* produce a system-wide calltree */
665 args.pa_flags |= FLAG_DO_CALLGRAPHS;
666 args.pa_plugin = PMCSTAT_PL_CALLTREE;
667 graphfilename = optarg;
668 break;
669
670 case 'f': /* plugins options */
671 if (args.pa_plugin == PMCSTAT_PL_NONE)
672 err(EX_USAGE, "ERROR: Need -g/-G/-m/-T.");
673 pmcstat_pluginconfigure_log(optarg);
674 break;
675
631 case 'G': /* produce a system-wide callgraph */
632 args.pa_flags |= FLAG_DO_CALLGRAPHS;
676 case 'G': /* produce a system-wide callgraph */
677 args.pa_flags |= FLAG_DO_CALLGRAPHS;
678 args.pa_plugin = PMCSTAT_PL_CALLGRAPH;
633 graphfilename = optarg;
634 break;
635
636 case 'g': /* produce gprof compatible profiles */
637 args.pa_flags |= FLAG_DO_GPROF;
679 graphfilename = optarg;
680 break;
681
682 case 'g': /* produce gprof compatible profiles */
683 args.pa_flags |= FLAG_DO_GPROF;
684 args.pa_pplugin = PMCSTAT_PL_CALLGRAPH;
685 args.pa_plugin = PMCSTAT_PL_GPROF;
638 break;
639
640 case 'k': /* pathname to the kernel */
641 free(args.pa_kernel);
642 args.pa_kernel = strdup(optarg);
643 args.pa_required |= FLAG_DO_ANALYSIS;
644 args.pa_flags |= FLAG_HAS_KERNELPATH;
645 break;
646
647 case 'm':
686 break;
687
688 case 'k': /* pathname to the kernel */
689 free(args.pa_kernel);
690 args.pa_kernel = strdup(optarg);
691 args.pa_required |= FLAG_DO_ANALYSIS;
692 args.pa_flags |= FLAG_HAS_KERNELPATH;
693 break;
694
695 case 'm':
648 args.pa_flags |= FLAG_WANTS_MAPPINGS;
649 graphfilename = optarg;
696 args.pa_flags |= FLAG_DO_ANNOTATE;
697 args.pa_plugin = PMCSTAT_PL_ANNOTATE;
698 graphfilename = optarg;
650 break;
651
652 case 'E': /* log process exit */
653 do_logprocexit = !do_logprocexit;
654 args.pa_required |= (FLAG_HAS_PROCESS_PMCS |
655 FLAG_HAS_COUNTING_PMCS | FLAG_HAS_OUTPUT_LOGFILE);
656 break;
657

--- 69 unchanged lines hidden (view full) ---

727 c = strcspn(optarg, ", \t");
728 ev->ev_name = malloc(c + 1);
729 (void) strncpy(ev->ev_name, optarg, c);
730 *(ev->ev_name + c) = '\0';
731
732 STAILQ_INSERT_TAIL(&args.pa_events, ev, ev_next);
733
734 if (option == 's' || option == 'S')
699 break;
700
701 case 'E': /* log process exit */
702 do_logprocexit = !do_logprocexit;
703 args.pa_required |= (FLAG_HAS_PROCESS_PMCS |
704 FLAG_HAS_COUNTING_PMCS | FLAG_HAS_OUTPUT_LOGFILE);
705 break;
706

--- 69 unchanged lines hidden (view full) ---

776 c = strcspn(optarg, ", \t");
777 ev->ev_name = malloc(c + 1);
778 (void) strncpy(ev->ev_name, optarg, c);
779 *(ev->ev_name + c) = '\0';
780
781 STAILQ_INSERT_TAIL(&args.pa_events, ev, ev_next);
782
783 if (option == 's' || option == 'S')
735 pmcstat_clone_event_descriptor(&args, ev,
784 pmcstat_clone_event_descriptor(ev,
736 cpumask & ~(1 << ev->ev_cpu));
737
738 break;
739
740 case 'n': /* sampling count */
741 current_sampling_count = strtol(optarg, &end, 0);
742 if (*end != '\0' || current_sampling_count <= 0)
743 errx(EX_USAGE,

--- 33 unchanged lines hidden (view full) ---

777 "specified once.");
778 args.pa_inputpath = optarg;
779 if (args.pa_printfile == stderr)
780 args.pa_printfile = stdout;
781 args.pa_flags |= FLAG_READ_LOGFILE;
782 break;
783
784 case 't': /* target pid or process name */
785 cpumask & ~(1 << ev->ev_cpu));
786
787 break;
788
789 case 'n': /* sampling count */
790 current_sampling_count = strtol(optarg, &end, 0);
791 if (*end != '\0' || current_sampling_count <= 0)
792 errx(EX_USAGE,

--- 33 unchanged lines hidden (view full) ---

826 "specified once.");
827 args.pa_inputpath = optarg;
828 if (args.pa_printfile == stderr)
829 args.pa_printfile = stdout;
830 args.pa_flags |= FLAG_READ_LOGFILE;
831 break;
832
833 case 't': /* target pid or process name */
785 pmcstat_find_targets(&args, optarg);
834 pmcstat_find_targets(optarg);
786
787 args.pa_flags |= FLAG_HAS_TARGET;
788 args.pa_required |= FLAG_HAS_PROCESS_PMCS;
789 break;
790
835
836 args.pa_flags |= FLAG_HAS_TARGET;
837 args.pa_required |= FLAG_HAS_PROCESS_PMCS;
838 break;
839
840 case 'T': /* top mode */
841 args.pa_flags |= FLAG_DO_TOP;
842 args.pa_plugin = PMCSTAT_PL_CALLGRAPH;
843 args.pa_ctdumpinstr = 0;
844 args.pa_mergepmc = 1;
845 if (args.pa_printfile == stderr)
846 args.pa_printfile = stdout;
847 break;
848
791 case 'v': /* verbose */
792 args.pa_verbosity++;
793 break;
794
795 case 'w': /* wait interval */
796 interval = strtod(optarg, &end);
797 if (*end != '\0' || interval <= 0)
798 errx(EX_USAGE, "ERROR: Illegal wait interval "
799 "value \"%s\".", optarg);
800 args.pa_flags |= FLAG_HAS_WAIT_INTERVAL;
849 case 'v': /* verbose */
850 args.pa_verbosity++;
851 break;
852
853 case 'w': /* wait interval */
854 interval = strtod(optarg, &end);
855 if (*end != '\0' || interval <= 0)
856 errx(EX_USAGE, "ERROR: Illegal wait interval "
857 "value \"%s\".", optarg);
858 args.pa_flags |= FLAG_HAS_WAIT_INTERVAL;
801 args.pa_required |= FLAG_HAS_COUNTING_PMCS;
802 args.pa_interval = interval;
803 break;
804
805 case 'W': /* toggle LOG_CSW */
806 do_logproccsw = !do_logproccsw;
807 args.pa_required |= (FLAG_HAS_PROCESS_PMCS |
808 FLAG_HAS_COUNTING_PMCS | FLAG_HAS_OUTPUT_LOGFILE);
809 break;

--- 18 unchanged lines hidden (view full) ---

828 args.pa_argv = (argv += optind);
829
830 args.pa_cpumask = cpumask; /* For selecting CPUs using -R. */
831
832 if (argc) /* command line present */
833 args.pa_flags |= FLAG_HAS_COMMANDLINE;
834
835 if (args.pa_flags & (FLAG_DO_GPROF | FLAG_DO_CALLGRAPHS |
859 args.pa_interval = interval;
860 break;
861
862 case 'W': /* toggle LOG_CSW */
863 do_logproccsw = !do_logproccsw;
864 args.pa_required |= (FLAG_HAS_PROCESS_PMCS |
865 FLAG_HAS_COUNTING_PMCS | FLAG_HAS_OUTPUT_LOGFILE);
866 break;

--- 18 unchanged lines hidden (view full) ---

885 args.pa_argv = (argv += optind);
886
887 args.pa_cpumask = cpumask; /* For selecting CPUs using -R. */
888
889 if (argc) /* command line present */
890 args.pa_flags |= FLAG_HAS_COMMANDLINE;
891
892 if (args.pa_flags & (FLAG_DO_GPROF | FLAG_DO_CALLGRAPHS |
836 FLAG_WANTS_MAPPINGS))
893 FLAG_DO_ANNOTATE | FLAG_DO_TOP))
837 args.pa_flags |= FLAG_DO_ANALYSIS;
838
839 /*
840 * Check invocation syntax.
841 */
842
843 /* disallow -O and -R together */
844 if (args.pa_outputpath && args.pa_inputpath)
845 errx(EX_USAGE, "ERROR: options -O and -R are mutually "
846 "exclusive.");
847
848 /* -m option is allowed with -R only. */
894 args.pa_flags |= FLAG_DO_ANALYSIS;
895
896 /*
897 * Check invocation syntax.
898 */
899
900 /* disallow -O and -R together */
901 if (args.pa_outputpath && args.pa_inputpath)
902 errx(EX_USAGE, "ERROR: options -O and -R are mutually "
903 "exclusive.");
904
905 /* -m option is allowed with -R only. */
849 if (args.pa_flags & FLAG_WANTS_MAPPINGS && args.pa_inputpath == NULL)
906 if (args.pa_flags & FLAG_DO_ANNOTATE && args.pa_inputpath == NULL)
850 errx(EX_USAGE, "ERROR: option -m requires an input file");
851
852 /* -m option is not allowed combined with -g or -G. */
907 errx(EX_USAGE, "ERROR: option -m requires an input file");
908
909 /* -m option is not allowed combined with -g or -G. */
853 if (args.pa_flags & FLAG_WANTS_MAPPINGS &&
910 if (args.pa_flags & FLAG_DO_ANNOTATE &&
854 args.pa_flags & (FLAG_DO_GPROF | FLAG_DO_CALLGRAPHS))
855 errx(EX_USAGE, "ERROR: option -m and -g | -G are mutually "
856 "exclusive");
857
858 if (args.pa_flags & FLAG_READ_LOGFILE) {
859 errmsg = NULL;
860 if (args.pa_flags & FLAG_HAS_COMMANDLINE)
861 errmsg = "a command line specification";

--- 37 unchanged lines hidden (view full) ---

899 (args.pa_flags & FLAG_HAS_SYSTEM_PMCS) == 0 &&
900 (args.pa_flags & FLAG_READ_LOGFILE) == 0)
901 errx(EX_USAGE, "ERROR: option -c requires at least one "
902 "system mode PMC to be specified.");
903
904 /* check for counting mode options without a counting PMC */
905 if ((args.pa_required & FLAG_HAS_COUNTING_PMCS) &&
906 (args.pa_flags & FLAG_HAS_COUNTING_PMCS) == 0)
911 args.pa_flags & (FLAG_DO_GPROF | FLAG_DO_CALLGRAPHS))
912 errx(EX_USAGE, "ERROR: option -m and -g | -G are mutually "
913 "exclusive");
914
915 if (args.pa_flags & FLAG_READ_LOGFILE) {
916 errmsg = NULL;
917 if (args.pa_flags & FLAG_HAS_COMMANDLINE)
918 errmsg = "a command line specification";

--- 37 unchanged lines hidden (view full) ---

956 (args.pa_flags & FLAG_HAS_SYSTEM_PMCS) == 0 &&
957 (args.pa_flags & FLAG_READ_LOGFILE) == 0)
958 errx(EX_USAGE, "ERROR: option -c requires at least one "
959 "system mode PMC to be specified.");
960
961 /* check for counting mode options without a counting PMC */
962 if ((args.pa_required & FLAG_HAS_COUNTING_PMCS) &&
963 (args.pa_flags & FLAG_HAS_COUNTING_PMCS) == 0)
907 errx(EX_USAGE, "ERROR: options -C, -W, -o and -w require at "
964 errx(EX_USAGE, "ERROR: options -C, -W and -o require at "
908 "least one counting mode PMC to be specified.");
909
910 /* check for sampling mode options without a sampling PMC spec */
911 if ((args.pa_required & FLAG_HAS_SAMPLING_PMCS) &&
912 (args.pa_flags & FLAG_HAS_SAMPLING_PMCS) == 0)
913 errx(EX_USAGE, "ERROR: options -N, -n and -O require at "
914 "least one sampling mode PMC to be specified.");
915
965 "least one counting mode PMC to be specified.");
966
967 /* check for sampling mode options without a sampling PMC spec */
968 if ((args.pa_required & FLAG_HAS_SAMPLING_PMCS) &&
969 (args.pa_flags & FLAG_HAS_SAMPLING_PMCS) == 0)
970 errx(EX_USAGE, "ERROR: options -N, -n and -O require at "
971 "least one sampling mode PMC to be specified.");
972
916 /* check if -g/-G are being used correctly */
973 /* check if -g/-G/-m/-T are being used correctly */
917 if ((args.pa_flags & FLAG_DO_ANALYSIS) &&
918 !(args.pa_flags & (FLAG_HAS_SAMPLING_PMCS|FLAG_READ_LOGFILE)))
974 if ((args.pa_flags & FLAG_DO_ANALYSIS) &&
975 !(args.pa_flags & (FLAG_HAS_SAMPLING_PMCS|FLAG_READ_LOGFILE)))
919 errx(EX_USAGE, "ERROR: options -g/-G require sampling PMCs "
976 errx(EX_USAGE, "ERROR: options -g/-G/-m/-T require sampling PMCs "
920 "or -R to be specified.");
921
922 /* check if -O was spuriously specified */
923 if ((args.pa_flags & FLAG_HAS_OUTPUT_LOGFILE) &&
924 (args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0)
925 errx(EX_USAGE,
926 "ERROR: option -O is used only with options "
927 "-E, -P, -S and -W.");
928
977 "or -R to be specified.");
978
979 /* check if -O was spuriously specified */
980 if ((args.pa_flags & FLAG_HAS_OUTPUT_LOGFILE) &&
981 (args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0)
982 errx(EX_USAGE,
983 "ERROR: option -O is used only with options "
984 "-E, -P, -S and -W.");
985
929 /* -k kernel path require -g/-G or -R */
986 /* -k kernel path require -g/-G/-m/-T or -R */
930 if ((args.pa_flags & FLAG_HAS_KERNELPATH) &&
931 (args.pa_flags & FLAG_DO_ANALYSIS) == 0 &&
932 (args.pa_flags & FLAG_READ_LOGFILE) == 0)
987 if ((args.pa_flags & FLAG_HAS_KERNELPATH) &&
988 (args.pa_flags & FLAG_DO_ANALYSIS) == 0 &&
989 (args.pa_flags & FLAG_READ_LOGFILE) == 0)
933 errx(EX_USAGE, "ERROR: option -k is only used with -g/-R.");
990 errx(EX_USAGE, "ERROR: option -k is only used with -g/-R/-m/-T.");
934
935 /* -D only applies to gprof output mode (-g) */
936 if ((args.pa_flags & FLAG_HAS_SAMPLESDIR) &&
937 (args.pa_flags & FLAG_DO_GPROF) == 0)
938 errx(EX_USAGE, "ERROR: option -D is only used with -g.");
939
940 /* -M mapfile requires -g or -R */
941 if (args.pa_mapfilename != NULL &&
942 (args.pa_flags & FLAG_DO_GPROF) == 0 &&
943 (args.pa_flags & FLAG_READ_LOGFILE) == 0)
944 errx(EX_USAGE, "ERROR: option -M is only used with -g/-R.");
945
991
992 /* -D only applies to gprof output mode (-g) */
993 if ((args.pa_flags & FLAG_HAS_SAMPLESDIR) &&
994 (args.pa_flags & FLAG_DO_GPROF) == 0)
995 errx(EX_USAGE, "ERROR: option -D is only used with -g.");
996
997 /* -M mapfile requires -g or -R */
998 if (args.pa_mapfilename != NULL &&
999 (args.pa_flags & FLAG_DO_GPROF) == 0 &&
1000 (args.pa_flags & FLAG_READ_LOGFILE) == 0)
1001 errx(EX_USAGE, "ERROR: option -M is only used with -g/-R.");
1002
1003 /* -T is incompatible with -R (replay logfile is a TODO) */
1004 if ((args.pa_flags & FLAG_DO_TOP) &&
1005 (args.pa_flags & FLAG_READ_LOGFILE))
1006 errx(EX_USAGE, "ERROR: option -T is incompatible with -R.");
1007
946 /*
947 * Disallow textual output of sampling PMCs if counting PMCs
948 * have also been asked for, mostly because the combined output
949 * is difficult to make sense of.
950 */
951 if ((args.pa_flags & FLAG_HAS_COUNTING_PMCS) &&
952 (args.pa_flags & FLAG_HAS_SAMPLING_PMCS) &&
953 ((args.pa_flags & FLAG_HAS_OUTPUT_LOGFILE) == 0))

--- 37 unchanged lines hidden (view full) ---

991 args.pa_graphfile = args.pa_printfile;
992 else {
993 args.pa_graphfile = fopen(graphfilename, "w");
994 if (args.pa_graphfile == NULL)
995 err(EX_OSERR, "ERROR: cannot open \"%s\" "
996 "for writing", graphfilename);
997 }
998 }
1008 /*
1009 * Disallow textual output of sampling PMCs if counting PMCs
1010 * have also been asked for, mostly because the combined output
1011 * is difficult to make sense of.
1012 */
1013 if ((args.pa_flags & FLAG_HAS_COUNTING_PMCS) &&
1014 (args.pa_flags & FLAG_HAS_SAMPLING_PMCS) &&
1015 ((args.pa_flags & FLAG_HAS_OUTPUT_LOGFILE) == 0))

--- 37 unchanged lines hidden (view full) ---

1053 args.pa_graphfile = args.pa_printfile;
1054 else {
1055 args.pa_graphfile = fopen(graphfilename, "w");
1056 if (args.pa_graphfile == NULL)
1057 err(EX_OSERR, "ERROR: cannot open \"%s\" "
1058 "for writing", graphfilename);
1059 }
1060 }
999 if (args.pa_flags & FLAG_WANTS_MAPPINGS) {
1061 if (args.pa_flags & FLAG_DO_ANNOTATE) {
1000 args.pa_graphfile = fopen(graphfilename, "w");
1001 if (args.pa_graphfile == NULL)
1002 err(EX_OSERR, "ERROR: cannot open \"%s\" for writing",
1003 graphfilename);
1004 }
1005
1006 /* if we've been asked to process a log file, do that and exit */
1007 if (args.pa_flags & FLAG_READ_LOGFILE) {
1008 /*
1009 * Print the log in textual form if we haven't been
1010 * asked to generate profiling information.
1011 */
1012 if ((args.pa_flags & FLAG_DO_ANALYSIS) == 0)
1013 args.pa_flags |= FLAG_DO_PRINT;
1014
1062 args.pa_graphfile = fopen(graphfilename, "w");
1063 if (args.pa_graphfile == NULL)
1064 err(EX_OSERR, "ERROR: cannot open \"%s\" for writing",
1065 graphfilename);
1066 }
1067
1068 /* if we've been asked to process a log file, do that and exit */
1069 if (args.pa_flags & FLAG_READ_LOGFILE) {
1070 /*
1071 * Print the log in textual form if we haven't been
1072 * asked to generate profiling information.
1073 */
1074 if ((args.pa_flags & FLAG_DO_ANALYSIS) == 0)
1075 args.pa_flags |= FLAG_DO_PRINT;
1076
1015 pmcstat_initialize_logging(&args);
1077 pmcstat_initialize_logging();
1016 args.pa_logfd = pmcstat_open_log(args.pa_inputpath,
1017 PMCSTAT_OPEN_FOR_READ);
1018 if ((args.pa_logparser = pmclog_open(args.pa_logfd)) == NULL)
1019 err(EX_OSERR, "ERROR: Cannot create parser");
1078 args.pa_logfd = pmcstat_open_log(args.pa_inputpath,
1079 PMCSTAT_OPEN_FOR_READ);
1080 if ((args.pa_logparser = pmclog_open(args.pa_logfd)) == NULL)
1081 err(EX_OSERR, "ERROR: Cannot create parser");
1020 pmcstat_process_log(&args);
1021 pmcstat_shutdown_logging(&args);
1082 pmcstat_process_log();
1083 pmcstat_shutdown_logging();
1022 exit(EX_OK);
1023 }
1024
1025 /* otherwise, we've been asked to collect data */
1026 if (pmc_init() < 0)
1027 err(EX_UNAVAILABLE,
1028 "ERROR: Initialization of the pmc(3) library failed");
1029

--- 27 unchanged lines hidden (view full) ---

1057 EV_SET(&kev, pipefd[READPIPEFD], EVFILT_READ, EV_ADD,
1058 0, 0, NULL);
1059
1060 if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
1061 err(EX_OSERR, "ERROR: Cannot register kevent");
1062
1063 args.pa_logfd = pipefd[WRITEPIPEFD];
1064
1084 exit(EX_OK);
1085 }
1086
1087 /* otherwise, we've been asked to collect data */
1088 if (pmc_init() < 0)
1089 err(EX_UNAVAILABLE,
1090 "ERROR: Initialization of the pmc(3) library failed");
1091

--- 27 unchanged lines hidden (view full) ---

1119 EV_SET(&kev, pipefd[READPIPEFD], EVFILT_READ, EV_ADD,
1120 0, 0, NULL);
1121
1122 if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
1123 err(EX_OSERR, "ERROR: Cannot register kevent");
1124
1125 args.pa_logfd = pipefd[WRITEPIPEFD];
1126
1065 args.pa_flags |= (FLAG_HAS_PIPE | FLAG_DO_PRINT);
1127 args.pa_flags |= FLAG_HAS_PIPE;
1128 if ((args.pa_flags & FLAG_DO_TOP) == 0)
1129 args.pa_flags |= FLAG_DO_PRINT;
1066 args.pa_logparser = pmclog_open(pipefd[READPIPEFD]);
1067 }
1068
1069 if (pmc_configure_logfile(args.pa_logfd) < 0)
1070 err(EX_OSERR, "ERROR: Cannot configure log file");
1071 }
1072
1073 /* remember to check for driver errors if we are sampling or logging */

--- 47 unchanged lines hidden (view full) ---

1121 */
1122
1123 if (isatty(fileno(args.pa_printfile))) {
1124
1125 if (ioctl(fileno(args.pa_printfile), TIOCGWINSZ, &ws) < 0)
1126 err(EX_OSERR, "ERROR: Cannot determine window size");
1127
1128 pmcstat_displayheight = ws.ws_row - 1;
1130 args.pa_logparser = pmclog_open(pipefd[READPIPEFD]);
1131 }
1132
1133 if (pmc_configure_logfile(args.pa_logfd) < 0)
1134 err(EX_OSERR, "ERROR: Cannot configure log file");
1135 }
1136
1137 /* remember to check for driver errors if we are sampling or logging */

--- 47 unchanged lines hidden (view full) ---

1185 */
1186
1187 if (isatty(fileno(args.pa_printfile))) {
1188
1189 if (ioctl(fileno(args.pa_printfile), TIOCGWINSZ, &ws) < 0)
1190 err(EX_OSERR, "ERROR: Cannot determine window size");
1191
1192 pmcstat_displayheight = ws.ws_row - 1;
1193 pmcstat_displaywidth = ws.ws_col - 1;
1129
1130 EV_SET(&kev, SIGWINCH, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
1131
1132 if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
1133 err(EX_OSERR, "ERROR: Cannot register kevent for "
1134 "SIGWINCH");
1194
1195 EV_SET(&kev, SIGWINCH, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
1196
1197 if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
1198 err(EX_OSERR, "ERROR: Cannot register kevent for "
1199 "SIGWINCH");
1200
1201 args.pa_toptty = 1;
1135 }
1136
1202 }
1203
1204 /*
1205 * Listen to key input in top mode.
1206 */
1207 if (args.pa_flags & FLAG_DO_TOP) {
1208 EV_SET(&kev, fileno(stdin), EVFILT_READ, EV_ADD, 0, 0, NULL);
1209 if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
1210 err(EX_OSERR, "ERROR: Cannot register kevent");
1211 }
1212
1137 EV_SET(&kev, SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
1138 if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
1139 err(EX_OSERR, "ERROR: Cannot register kevent for SIGINT");
1140
1141 EV_SET(&kev, SIGIO, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
1142 if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
1143 err(EX_OSERR, "ERROR: Cannot register kevent for SIGIO");
1144
1145 /*
1146 * An exec() failure of a forked child is signalled by the
1147 * child sending the parent a SIGCHLD. We don't register an
1148 * actual signal handler for SIGCHLD, but instead use our
1149 * kqueue to pick up the signal.
1150 */
1151 EV_SET(&kev, SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
1152 if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
1153 err(EX_OSERR, "ERROR: Cannot register kevent for SIGCHLD");
1154
1213 EV_SET(&kev, SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
1214 if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
1215 err(EX_OSERR, "ERROR: Cannot register kevent for SIGINT");
1216
1217 EV_SET(&kev, SIGIO, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
1218 if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
1219 err(EX_OSERR, "ERROR: Cannot register kevent for SIGIO");
1220
1221 /*
1222 * An exec() failure of a forked child is signalled by the
1223 * child sending the parent a SIGCHLD. We don't register an
1224 * actual signal handler for SIGCHLD, but instead use our
1225 * kqueue to pick up the signal.
1226 */
1227 EV_SET(&kev, SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
1228 if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
1229 err(EX_OSERR, "ERROR: Cannot register kevent for SIGCHLD");
1230
1155 /* setup a timer if we have counting mode PMCs needing to be printed */
1156 if ((args.pa_flags & FLAG_HAS_COUNTING_PMCS) &&
1157 (args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0) {
1231 /*
1232 * Setup a timer if we have counting mode PMCs needing to be printed or
1233 * top mode plugin is active.
1234 */
1235 if (((args.pa_flags & FLAG_HAS_COUNTING_PMCS) &&
1236 (args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0) ||
1237 (args.pa_flags & FLAG_DO_TOP)) {
1158 EV_SET(&kev, 0, EVFILT_TIMER, EV_ADD, 0,
1159 args.pa_interval * 1000, NULL);
1160
1161 if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
1162 err(EX_OSERR, "ERROR: Cannot register kevent for "
1163 "timer");
1164 }
1165
1166 /* attach PMCs to the target process, starting it if specified */
1167 if (args.pa_flags & FLAG_HAS_COMMANDLINE)
1238 EV_SET(&kev, 0, EVFILT_TIMER, EV_ADD, 0,
1239 args.pa_interval * 1000, NULL);
1240
1241 if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
1242 err(EX_OSERR, "ERROR: Cannot register kevent for "
1243 "timer");
1244 }
1245
1246 /* attach PMCs to the target process, starting it if specified */
1247 if (args.pa_flags & FLAG_HAS_COMMANDLINE)
1168 pmcstat_create_process(&args);
1248 pmcstat_create_process();
1169
1170 if (check_driver_stats && pmc_get_driver_stats(&ds_start) < 0)
1171 err(EX_OSERR, "ERROR: Cannot retrieve driver statistics");
1172
1173 /* Attach process pmcs to the target process. */
1174 if (args.pa_flags & (FLAG_HAS_TARGET | FLAG_HAS_COMMANDLINE)) {
1175 if (SLIST_EMPTY(&args.pa_targets))
1176 errx(EX_DATAERR, "ERROR: No matching target "
1177 "processes.");
1178 if (args.pa_flags & FLAG_HAS_PROCESS_PMCS)
1249
1250 if (check_driver_stats && pmc_get_driver_stats(&ds_start) < 0)
1251 err(EX_OSERR, "ERROR: Cannot retrieve driver statistics");
1252
1253 /* Attach process pmcs to the target process. */
1254 if (args.pa_flags & (FLAG_HAS_TARGET | FLAG_HAS_COMMANDLINE)) {
1255 if (SLIST_EMPTY(&args.pa_targets))
1256 errx(EX_DATAERR, "ERROR: No matching target "
1257 "processes.");
1258 if (args.pa_flags & FLAG_HAS_PROCESS_PMCS)
1179 pmcstat_attach_pmcs(&args);
1259 pmcstat_attach_pmcs();
1180
1181 if (pmcstat_kvm) {
1182 kvm_close(pmcstat_kvm);
1183 pmcstat_kvm = NULL;
1184 }
1185 }
1186
1187 /* start the pmcs */
1260
1261 if (pmcstat_kvm) {
1262 kvm_close(pmcstat_kvm);
1263 pmcstat_kvm = NULL;
1264 }
1265 }
1266
1267 /* start the pmcs */
1188 pmcstat_start_pmcs(&args);
1268 pmcstat_start_pmcs();
1189
1190 /* start the (commandline) process if needed */
1191 if (args.pa_flags & FLAG_HAS_COMMANDLINE)
1192 pmcstat_start_process();
1193
1194 /* initialize logging if printing the configured log */
1269
1270 /* start the (commandline) process if needed */
1271 if (args.pa_flags & FLAG_HAS_COMMANDLINE)
1272 pmcstat_start_process();
1273
1274 /* initialize logging if printing the configured log */
1195 if ((args.pa_flags & FLAG_DO_PRINT) &&
1275 if ((args.pa_flags & (FLAG_DO_PRINT | FLAG_DO_TOP)) &&
1196 (args.pa_flags & (FLAG_HAS_PIPE | FLAG_HAS_OUTPUT_LOGFILE)))
1276 (args.pa_flags & (FLAG_HAS_PIPE | FLAG_HAS_OUTPUT_LOGFILE)))
1197 pmcstat_initialize_logging(&args);
1277 pmcstat_initialize_logging();
1198
1199 /* Handle SIGINT using the kqueue loop */
1200 sa.sa_handler = SIG_IGN;
1201 sa.sa_flags = 0;
1202 (void) sigemptyset(&sa.sa_mask);
1203
1204 if (sigaction(SIGINT, &sa, NULL) < 0)
1205 err(EX_OSERR, "ERROR: Cannot install signal handler");
1206
1207 /*
1278
1279 /* Handle SIGINT using the kqueue loop */
1280 sa.sa_handler = SIG_IGN;
1281 sa.sa_flags = 0;
1282 (void) sigemptyset(&sa.sa_mask);
1283
1284 if (sigaction(SIGINT, &sa, NULL) < 0)
1285 err(EX_OSERR, "ERROR: Cannot install signal handler");
1286
1287 /*
1288 * Setup the top mode display.
1289 */
1290 if (args.pa_flags & FLAG_DO_TOP) {
1291 args.pa_flags &= ~FLAG_DO_PRINT;
1292
1293 if (args.pa_toptty) {
1294 /*
1295 * Init ncurses.
1296 */
1297 initscr();
1298 if(has_colors() == TRUE) {
1299 args.pa_topcolor = 1;
1300 start_color();
1301 use_default_colors();
1302 pair_content(0, &cf, &cb);
1303 init_pair(1, COLOR_RED, cb);
1304 init_pair(2, COLOR_YELLOW, cb);
1305 init_pair(3, COLOR_GREEN, cb);
1306 }
1307 cbreak();
1308 noecho();
1309 nonl();
1310 nodelay(stdscr, 1);
1311 intrflush(stdscr, FALSE);
1312 keypad(stdscr, TRUE);
1313 clear();
1314 atexit(pmcstat_topexit);
1315 }
1316 }
1317
1318 /*
1208 * loop till either the target process (if any) exits, or we
1209 * are killed by a SIGINT.
1210 */
1211 runstate = PMCSTAT_RUNNING;
1212 do_print = 0;
1213 do {
1214 if ((c = kevent(pmcstat_kq, NULL, 0, &kev, 1, NULL)) <= 0) {
1215 if (errno != EINTR)

--- 4 unchanged lines hidden (view full) ---

1220
1221 if (kev.flags & EV_ERROR)
1222 errc(EX_OSERR, kev.data, "ERROR: kevent failed");
1223
1224 switch (kev.filter) {
1225 case EVFILT_PROC: /* target has exited */
1226 if (args.pa_flags & (FLAG_HAS_OUTPUT_LOGFILE |
1227 FLAG_HAS_PIPE))
1319 * loop till either the target process (if any) exits, or we
1320 * are killed by a SIGINT.
1321 */
1322 runstate = PMCSTAT_RUNNING;
1323 do_print = 0;
1324 do {
1325 if ((c = kevent(pmcstat_kq, NULL, 0, &kev, 1, NULL)) <= 0) {
1326 if (errno != EINTR)

--- 4 unchanged lines hidden (view full) ---

1331
1332 if (kev.flags & EV_ERROR)
1333 errc(EX_OSERR, kev.data, "ERROR: kevent failed");
1334
1335 switch (kev.filter) {
1336 case EVFILT_PROC: /* target has exited */
1337 if (args.pa_flags & (FLAG_HAS_OUTPUT_LOGFILE |
1338 FLAG_HAS_PIPE))
1228 runstate = pmcstat_close_log(&args);
1339 runstate = pmcstat_close_log();
1229 else
1230 runstate = PMCSTAT_FINISHED;
1231 do_print = 1;
1232 break;
1233
1234 case EVFILT_READ: /* log file data is present */
1340 else
1341 runstate = PMCSTAT_FINISHED;
1342 do_print = 1;
1343 break;
1344
1345 case EVFILT_READ: /* log file data is present */
1235 runstate = pmcstat_process_log(&args);
1346 if (kev.ident == (unsigned)fileno(stdin)) {
1347 if (pmcstat_keypress_log())
1348 runstate = pmcstat_close_log();
1349 } else
1350 runstate = pmcstat_process_log();
1236 break;
1237
1238 case EVFILT_SIGNAL:
1239 if (kev.ident == SIGCHLD) {
1240 /*
1241 * The child process sends us a
1242 * SIGCHLD if its exec() failed. We
1243 * wait for it to exit and then exit

--- 4 unchanged lines hidden (view full) ---

1248 } else if (kev.ident == SIGIO) {
1249 /*
1250 * We get a SIGIO if a PMC loses all
1251 * of its targets, or if logfile
1252 * writes encounter an error.
1253 */
1254 if (args.pa_flags & (FLAG_HAS_OUTPUT_LOGFILE |
1255 FLAG_HAS_PIPE)) {
1351 break;
1352
1353 case EVFILT_SIGNAL:
1354 if (kev.ident == SIGCHLD) {
1355 /*
1356 * The child process sends us a
1357 * SIGCHLD if its exec() failed. We
1358 * wait for it to exit and then exit

--- 4 unchanged lines hidden (view full) ---

1363 } else if (kev.ident == SIGIO) {
1364 /*
1365 * We get a SIGIO if a PMC loses all
1366 * of its targets, or if logfile
1367 * writes encounter an error.
1368 */
1369 if (args.pa_flags & (FLAG_HAS_OUTPUT_LOGFILE |
1370 FLAG_HAS_PIPE)) {
1256 runstate = pmcstat_close_log(&args);
1371 runstate = pmcstat_close_log();
1257 if (args.pa_flags &
1258 (FLAG_DO_PRINT|FLAG_DO_ANALYSIS))
1372 if (args.pa_flags &
1373 (FLAG_DO_PRINT|FLAG_DO_ANALYSIS))
1259 pmcstat_process_log(&args);
1374 pmcstat_process_log();
1260 }
1261 do_print = 1; /* print PMCs at exit */
1262 runstate = PMCSTAT_FINISHED;
1263 } else if (kev.ident == SIGINT) {
1264 /* Kill the child process if we started it */
1265 if (args.pa_flags & FLAG_HAS_COMMANDLINE)
1375 }
1376 do_print = 1; /* print PMCs at exit */
1377 runstate = PMCSTAT_FINISHED;
1378 } else if (kev.ident == SIGINT) {
1379 /* Kill the child process if we started it */
1380 if (args.pa_flags & FLAG_HAS_COMMANDLINE)
1266 pmcstat_kill_process(&args);
1381 pmcstat_kill_process();
1267 /* Close the pipe to self, if present. */
1268 if (args.pa_flags & FLAG_HAS_PIPE)
1269 (void) close(pipefd[READPIPEFD]);
1270 runstate = PMCSTAT_FINISHED;
1271 } else if (kev.ident == SIGWINCH) {
1272 if (ioctl(fileno(args.pa_printfile),
1273 TIOCGWINSZ, &ws) < 0)
1274 err(EX_OSERR, "ERROR: Cannot determine "
1275 "window size");
1276 pmcstat_displayheight = ws.ws_row - 1;
1382 /* Close the pipe to self, if present. */
1383 if (args.pa_flags & FLAG_HAS_PIPE)
1384 (void) close(pipefd[READPIPEFD]);
1385 runstate = PMCSTAT_FINISHED;
1386 } else if (kev.ident == SIGWINCH) {
1387 if (ioctl(fileno(args.pa_printfile),
1388 TIOCGWINSZ, &ws) < 0)
1389 err(EX_OSERR, "ERROR: Cannot determine "
1390 "window size");
1391 pmcstat_displayheight = ws.ws_row - 1;
1392 pmcstat_displaywidth = ws.ws_col - 1;
1277 } else
1278 assert(0);
1279
1280 break;
1281
1282 case EVFILT_TIMER: /* print out counting PMCs */
1283 do_print = 1;
1284 break;
1285
1286 }
1287
1393 } else
1394 assert(0);
1395
1396 break;
1397
1398 case EVFILT_TIMER: /* print out counting PMCs */
1399 do_print = 1;
1400 break;
1401
1402 }
1403
1288 if (do_print &&
1289 (args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0) {
1290 pmcstat_print_pmcs(&args);
1291 if (runstate == PMCSTAT_FINISHED && /* final newline */
1292 (args.pa_flags & FLAG_DO_PRINT) == 0)
1293 (void) fprintf(args.pa_printfile, "\n");
1404 if (do_print) {
1405 if ((args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0) {
1406 pmcstat_print_pmcs();
1407 if (runstate == PMCSTAT_FINISHED && /* final newline */
1408 (args.pa_flags & FLAG_DO_PRINT) == 0)
1409 (void) fprintf(args.pa_printfile, "\n");
1410 }
1411 if (args.pa_flags & FLAG_DO_TOP)
1412 pmcstat_display_log();
1294 do_print = 0;
1295 }
1296
1297 } while (runstate != PMCSTAT_FINISHED);
1298
1413 do_print = 0;
1414 }
1415
1416 } while (runstate != PMCSTAT_FINISHED);
1417
1418 if ((args.pa_flags & FLAG_DO_TOP) && args.pa_toptty) {
1419 pmcstat_topexit();
1420 args.pa_toptty = 0;
1421 }
1422
1299 /* flush any pending log entries */
1300 if (args.pa_flags & (FLAG_HAS_OUTPUT_LOGFILE | FLAG_HAS_PIPE))
1301 pmc_flush_logfile();
1302
1423 /* flush any pending log entries */
1424 if (args.pa_flags & (FLAG_HAS_OUTPUT_LOGFILE | FLAG_HAS_PIPE))
1425 pmc_flush_logfile();
1426
1303 pmcstat_cleanup(&args);
1427 pmcstat_cleanup();
1304
1305 free(args.pa_kernel);
1306
1307 /* check if the driver lost any samples or events */
1308 if (check_driver_stats) {
1309 if (pmc_get_driver_stats(&ds_end) < 0)
1310 err(EX_OSERR, "ERROR: Cannot retrieve driver "
1311 "statistics");

--- 15 unchanged lines hidden ---
1428
1429 free(args.pa_kernel);
1430
1431 /* check if the driver lost any samples or events */
1432 if (check_driver_stats) {
1433 if (pmc_get_driver_stats(&ds_end) < 0)
1434 err(EX_OSERR, "ERROR: Cannot retrieve driver "
1435 "statistics");

--- 15 unchanged lines hidden ---