builtin-trace.c (58cea307432e3376293e6b2be88d1f6e6e99274a) | builtin-trace.c (c24ff998fc420891f17d73acab6766823d492175) |
---|---|
1#include <traceevent/event-parse.h> 2#include "builtin.h" 3#include "util/color.h" 4#include "util/evlist.h" 5#include "util/machine.h" 6#include "util/thread.h" 7#include "util/parse-options.h" 8#include "util/strlist.h" --- 49 unchanged lines hidden (view full) --- 58 size_t printed = fprintf(fp, "("); 59 60 if (duration >= 1.0) 61 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration); 62 else if (duration >= 0.01) 63 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration); 64 else 65 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration); | 1#include <traceevent/event-parse.h> 2#include "builtin.h" 3#include "util/color.h" 4#include "util/evlist.h" 5#include "util/machine.h" 6#include "util/thread.h" 7#include "util/parse-options.h" 8#include "util/strlist.h" --- 49 unchanged lines hidden (view full) --- 58 size_t printed = fprintf(fp, "("); 59 60 if (duration >= 1.0) 61 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration); 62 else if (duration >= 0.01) 63 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration); 64 else 65 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration); |
66 return printed + fprintf(stdout, "): "); | 66 return printed + fprintf(fp, "): "); |
67} 68 69struct thread_trace { 70 u64 entry_time; 71 u64 exit_time; 72 bool entry_pending; 73 unsigned long nr_events; 74 char *entry_str; 75 double runtime_ms; 76}; 77 78static struct thread_trace *thread_trace__new(void) 79{ 80 return zalloc(sizeof(struct thread_trace)); 81} 82 | 67} 68 69struct thread_trace { 70 u64 entry_time; 71 u64 exit_time; 72 bool entry_pending; 73 unsigned long nr_events; 74 char *entry_str; 75 double runtime_ms; 76}; 77 78static struct thread_trace *thread_trace__new(void) 79{ 80 return zalloc(sizeof(struct thread_trace)); 81} 82 |
83static struct thread_trace *thread__trace(struct thread *thread) | 83static struct thread_trace *thread__trace(struct thread *thread, FILE *fp) |
84{ 85 struct thread_trace *ttrace; 86 87 if (thread == NULL) 88 goto fail; 89 90 if (thread->priv == NULL) 91 thread->priv = thread_trace__new(); 92 93 if (thread->priv == NULL) 94 goto fail; 95 96 ttrace = thread->priv; 97 ++ttrace->nr_events; 98 99 return ttrace; 100fail: | 84{ 85 struct thread_trace *ttrace; 86 87 if (thread == NULL) 88 goto fail; 89 90 if (thread->priv == NULL) 91 thread->priv = thread_trace__new(); 92 93 if (thread->priv == NULL) 94 goto fail; 95 96 ttrace = thread->priv; 97 ++ttrace->nr_events; 98 99 return ttrace; 100fail: |
101 color_fprintf(stdout, PERF_COLOR_RED, | 101 color_fprintf(fp, PERF_COLOR_RED, |
102 "WARNING: not enough memory, dropping samples!\n"); 103 return NULL; 104} 105 106struct trace { | 102 "WARNING: not enough memory, dropping samples!\n"); 103 return NULL; 104} 105 106struct trace { |
107 struct perf_tool tool; |
|
107 int audit_machine; 108 struct { 109 int max; 110 struct syscall *table; 111 } syscalls; 112 struct perf_record_opts opts; 113 struct machine host; 114 u64 base_time; | 108 int audit_machine; 109 struct { 110 int max; 111 struct syscall *table; 112 } syscalls; 113 struct perf_record_opts opts; 114 struct machine host; 115 u64 base_time; |
116 FILE *output; |
|
115 struct strlist *ev_qualifier; 116 unsigned long nr_events; 117 bool sched; 118 bool multiple_threads; 119 double duration_filter; 120 double runtime_ms; 121}; 122 --- 23 unchanged lines hidden (view full) --- 146 printed += fprintf_duration(duration, fp); 147 148 if (trace->multiple_threads) 149 printed += fprintf(fp, "%d ", thread->tid); 150 151 return printed; 152} 153 | 117 struct strlist *ev_qualifier; 118 unsigned long nr_events; 119 bool sched; 120 bool multiple_threads; 121 double duration_filter; 122 double runtime_ms; 123}; 124 --- 23 unchanged lines hidden (view full) --- 148 printed += fprintf_duration(duration, fp); 149 150 if (trace->multiple_threads) 151 printed += fprintf(fp, "%d ", thread->tid); 152 153 return printed; 154} 155 |
154static int trace__process_event(struct machine *machine, union perf_event *event) | 156static int trace__process_event(struct trace *trace, struct machine *machine, 157 union perf_event *event) |
155{ 156 int ret = 0; 157 158 switch (event->header.type) { 159 case PERF_RECORD_LOST: | 158{ 159 int ret = 0; 160 161 switch (event->header.type) { 162 case PERF_RECORD_LOST: |
160 color_fprintf(stdout, PERF_COLOR_RED, | 163 color_fprintf(trace->output, PERF_COLOR_RED, |
161 "LOST %" PRIu64 " events!\n", event->lost.lost); 162 ret = machine__process_lost_event(machine, event); 163 default: 164 ret = machine__process_event(machine, event); 165 break; 166 } 167 168 return ret; 169} 170 | 164 "LOST %" PRIu64 " events!\n", event->lost.lost); 165 ret = machine__process_lost_event(machine, event); 166 default: 167 ret = machine__process_event(machine, event); 168 break; 169 } 170 171 return ret; 172} 173 |
171static int trace__tool_process(struct perf_tool *tool __maybe_unused, | 174static int trace__tool_process(struct perf_tool *tool, |
172 union perf_event *event, 173 struct perf_sample *sample __maybe_unused, 174 struct machine *machine) 175{ | 175 union perf_event *event, 176 struct perf_sample *sample __maybe_unused, 177 struct machine *machine) 178{ |
176 return trace__process_event(machine, event); | 179 struct trace *trace = container_of(tool, struct trace, tool); 180 return trace__process_event(trace, machine, event); |
177} 178 179static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) 180{ 181 int err = symbol__init(); 182 183 if (err) 184 return err; 185 186 machine__init(&trace->host, "", HOST_KERNEL_ID); 187 machine__create_kernel_maps(&trace->host); 188 189 if (perf_target__has_task(&trace->opts.target)) { | 181} 182 183static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) 184{ 185 int err = symbol__init(); 186 187 if (err) 188 return err; 189 190 machine__init(&trace->host, "", HOST_KERNEL_ID); 191 machine__create_kernel_maps(&trace->host); 192 193 if (perf_target__has_task(&trace->opts.target)) { |
190 err = perf_event__synthesize_thread_map(NULL, evlist->threads, | 194 err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads, |
191 trace__tool_process, 192 &trace->host); 193 } else { | 195 trace__tool_process, 196 &trace->host); 197 } else { |
194 err = perf_event__synthesize_threads(NULL, trace__tool_process, | 198 err = perf_event__synthesize_threads(&trace->tool, trace__tool_process, |
195 &trace->host); 196 } 197 198 if (err) 199 symbol__exit(); 200 201 return err; 202} --- 80 unchanged lines hidden (view full) --- 283 284static struct syscall *trace__syscall_info(struct trace *trace, 285 struct perf_evsel *evsel, 286 struct perf_sample *sample) 287{ 288 int id = perf_evsel__intval(evsel, sample, "id"); 289 290 if (id < 0) { | 199 &trace->host); 200 } 201 202 if (err) 203 symbol__exit(); 204 205 return err; 206} --- 80 unchanged lines hidden (view full) --- 287 288static struct syscall *trace__syscall_info(struct trace *trace, 289 struct perf_evsel *evsel, 290 struct perf_sample *sample) 291{ 292 int id = perf_evsel__intval(evsel, sample, "id"); 293 294 if (id < 0) { |
291 printf("Invalid syscall %d id, skipping...\n", id); | 295 fprintf(trace->output, "Invalid syscall %d id, skipping...\n", id); |
292 return NULL; 293 } 294 295 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) && 296 trace__read_syscall_info(trace, id)) 297 goto out_cant_read; 298 299 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL)) 300 goto out_cant_read; 301 302 return &trace->syscalls.table[id]; 303 304out_cant_read: | 296 return NULL; 297 } 298 299 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) && 300 trace__read_syscall_info(trace, id)) 301 goto out_cant_read; 302 303 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL)) 304 goto out_cant_read; 305 306 return &trace->syscalls.table[id]; 307 308out_cant_read: |
305 printf("Problems reading syscall %d", id); | 309 fprintf(trace->output, "Problems reading syscall %d", id); |
306 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL) | 310 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL) |
307 printf("(%s)", trace->syscalls.table[id].name); 308 puts(" information"); | 311 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name); 312 fputs(" information", trace->output); |
309 return NULL; 310} 311 312static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, 313 struct perf_sample *sample) 314{ 315 char *msg; 316 void *args; --- 4 unchanged lines hidden (view full) --- 321 322 if (sc == NULL) 323 return -1; 324 325 if (sc->filtered) 326 return 0; 327 328 thread = machine__findnew_thread(&trace->host, sample->tid); | 313 return NULL; 314} 315 316static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, 317 struct perf_sample *sample) 318{ 319 char *msg; 320 void *args; --- 4 unchanged lines hidden (view full) --- 325 326 if (sc == NULL) 327 return -1; 328 329 if (sc->filtered) 330 return 0; 331 332 thread = machine__findnew_thread(&trace->host, sample->tid); |
329 ttrace = thread__trace(thread); | 333 ttrace = thread__trace(thread, trace->output); |
330 if (ttrace == NULL) 331 return -1; 332 333 args = perf_evsel__rawptr(evsel, sample, "args"); 334 if (args == NULL) { | 334 if (ttrace == NULL) 335 return -1; 336 337 args = perf_evsel__rawptr(evsel, sample, "args"); 338 if (args == NULL) { |
335 printf("Problems reading syscall arguments\n"); | 339 fprintf(trace->output, "Problems reading syscall arguments\n"); |
336 return -1; 337 } 338 339 ttrace = thread->priv; 340 341 if (ttrace->entry_str == NULL) { 342 ttrace->entry_str = malloc(1024); 343 if (!ttrace->entry_str) 344 return -1; 345 } 346 347 ttrace->entry_time = sample->time; 348 msg = ttrace->entry_str; 349 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name); 350 351 printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed, args); 352 353 if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) { 354 if (!trace->duration_filter) { | 340 return -1; 341 } 342 343 ttrace = thread->priv; 344 345 if (ttrace->entry_str == NULL) { 346 ttrace->entry_str = malloc(1024); 347 if (!ttrace->entry_str) 348 return -1; 349 } 350 351 ttrace->entry_time = sample->time; 352 msg = ttrace->entry_str; 353 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name); 354 355 printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed, args); 356 357 if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) { 358 if (!trace->duration_filter) { |
355 trace__fprintf_entry_head(trace, thread, 1, sample->time, stdout); 356 printf("%-70s\n", ttrace->entry_str); | 359 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output); 360 fprintf(trace->output, "%-70s\n", ttrace->entry_str); |
357 } 358 } else 359 ttrace->entry_pending = true; 360 361 return 0; 362} 363 364static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, --- 7 unchanged lines hidden (view full) --- 372 373 if (sc == NULL) 374 return -1; 375 376 if (sc->filtered) 377 return 0; 378 379 thread = machine__findnew_thread(&trace->host, sample->tid); | 361 } 362 } else 363 ttrace->entry_pending = true; 364 365 return 0; 366} 367 368static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, --- 7 unchanged lines hidden (view full) --- 376 377 if (sc == NULL) 378 return -1; 379 380 if (sc->filtered) 381 return 0; 382 383 thread = machine__findnew_thread(&trace->host, sample->tid); |
380 ttrace = thread__trace(thread); | 384 ttrace = thread__trace(thread, trace->output); |
381 if (ttrace == NULL) 382 return -1; 383 384 ret = perf_evsel__intval(evsel, sample, "ret"); 385 386 ttrace = thread->priv; 387 388 ttrace->exit_time = sample->time; 389 390 if (ttrace->entry_time) { 391 duration = sample->time - ttrace->entry_time; 392 if (trace__filter_duration(trace, duration)) 393 goto out; 394 } else if (trace->duration_filter) 395 goto out; 396 | 385 if (ttrace == NULL) 386 return -1; 387 388 ret = perf_evsel__intval(evsel, sample, "ret"); 389 390 ttrace = thread->priv; 391 392 ttrace->exit_time = sample->time; 393 394 if (ttrace->entry_time) { 395 duration = sample->time - ttrace->entry_time; 396 if (trace__filter_duration(trace, duration)) 397 goto out; 398 } else if (trace->duration_filter) 399 goto out; 400 |
397 trace__fprintf_entry_head(trace, thread, duration, sample->time, stdout); | 401 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output); |
398 399 if (ttrace->entry_pending) { | 402 403 if (ttrace->entry_pending) { |
400 printf("%-70s", ttrace->entry_str); | 404 fprintf(trace->output, "%-70s", ttrace->entry_str); |
401 } else { | 405 } else { |
402 printf(" ... ["); 403 color_fprintf(stdout, PERF_COLOR_YELLOW, "continued"); 404 printf("]: %s()", sc->name); | 406 fprintf(trace->output, " ... ["); 407 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued"); 408 fprintf(trace->output, "]: %s()", sc->name); |
405 } 406 407 if (ret < 0 && sc->fmt && sc->fmt->errmsg) { 408 char bf[256]; 409 const char *emsg = strerror_r(-ret, bf, sizeof(bf)), 410 *e = audit_errno_to_name(-ret); 411 | 409 } 410 411 if (ret < 0 && sc->fmt && sc->fmt->errmsg) { 412 char bf[256]; 413 const char *emsg = strerror_r(-ret, bf, sizeof(bf)), 414 *e = audit_errno_to_name(-ret); 415 |
412 printf(") = -1 %s %s", e, emsg); | 416 fprintf(trace->output, ") = -1 %s %s", e, emsg); |
413 } else if (ret == 0 && sc->fmt && sc->fmt->timeout) | 417 } else if (ret == 0 && sc->fmt && sc->fmt->timeout) |
414 printf(") = 0 Timeout"); | 418 fprintf(trace->output, ") = 0 Timeout"); |
415 else | 419 else |
416 printf(") = %d", ret); | 420 fprintf(trace->output, ") = %d", ret); |
417 | 421 |
418 putchar('\n'); | 422 fputc('\n', trace->output); |
419out: 420 ttrace->entry_pending = false; 421 422 return 0; 423} 424 425static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel, 426 struct perf_sample *sample) 427{ 428 u64 runtime = perf_evsel__intval(evsel, sample, "runtime"); 429 double runtime_ms = (double)runtime / NSEC_PER_MSEC; 430 struct thread *thread = machine__findnew_thread(&trace->host, sample->tid); | 423out: 424 ttrace->entry_pending = false; 425 426 return 0; 427} 428 429static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel, 430 struct perf_sample *sample) 431{ 432 u64 runtime = perf_evsel__intval(evsel, sample, "runtime"); 433 double runtime_ms = (double)runtime / NSEC_PER_MSEC; 434 struct thread *thread = machine__findnew_thread(&trace->host, sample->tid); |
431 struct thread_trace *ttrace = thread__trace(thread); | 435 struct thread_trace *ttrace = thread__trace(thread, trace->output); |
432 433 if (ttrace == NULL) 434 goto out_dump; 435 436 ttrace->runtime_ms += runtime_ms; 437 trace->runtime_ms += runtime_ms; 438 return 0; 439 440out_dump: | 436 437 if (ttrace == NULL) 438 goto out_dump; 439 440 ttrace->runtime_ms += runtime_ms; 441 trace->runtime_ms += runtime_ms; 442 return 0; 443 444out_dump: |
441 printf("%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n", | 445 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n", |
442 evsel->name, 443 perf_evsel__strval(evsel, sample, "comm"), 444 (pid_t)perf_evsel__intval(evsel, sample, "pid"), 445 runtime, 446 perf_evsel__intval(evsel, sample, "vruntime")); 447 return 0; 448} 449 450static int trace__run(struct trace *trace, int argc, const char **argv) 451{ 452 struct perf_evlist *evlist = perf_evlist__new(); 453 struct perf_evsel *evsel; 454 int err = -1, i; 455 unsigned long before; 456 const bool forks = argc > 0; 457 458 if (evlist == NULL) { | 446 evsel->name, 447 perf_evsel__strval(evsel, sample, "comm"), 448 (pid_t)perf_evsel__intval(evsel, sample, "pid"), 449 runtime, 450 perf_evsel__intval(evsel, sample, "vruntime")); 451 return 0; 452} 453 454static int trace__run(struct trace *trace, int argc, const char **argv) 455{ 456 struct perf_evlist *evlist = perf_evlist__new(); 457 struct perf_evsel *evsel; 458 int err = -1, i; 459 unsigned long before; 460 const bool forks = argc > 0; 461 462 if (evlist == NULL) { |
459 printf("Not enough memory to run!\n"); | 463 fprintf(trace->output, "Not enough memory to run!\n"); |
460 goto out; 461 } 462 463 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) || 464 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) { | 464 goto out; 465 } 466 467 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) || 468 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) { |
465 printf("Couldn't read the raw_syscalls tracepoints information!\n"); | 469 fprintf(trace->output, "Couldn't read the raw_syscalls tracepoints information!\n"); |
466 goto out_delete_evlist; 467 } 468 469 if (trace->sched && 470 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", 471 trace__sched_stat_runtime)) { | 470 goto out_delete_evlist; 471 } 472 473 if (trace->sched && 474 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", 475 trace__sched_stat_runtime)) { |
472 printf("Couldn't read the sched_stat_runtime tracepoint information!\n"); | 476 fprintf(trace->output, "Couldn't read the sched_stat_runtime tracepoint information!\n"); |
473 goto out_delete_evlist; 474 } 475 476 err = perf_evlist__create_maps(evlist, &trace->opts.target); 477 if (err < 0) { | 477 goto out_delete_evlist; 478 } 479 480 err = perf_evlist__create_maps(evlist, &trace->opts.target); 481 if (err < 0) { |
478 printf("Problems parsing the target to trace, check your options!\n"); | 482 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n"); |
479 goto out_delete_evlist; 480 } 481 482 err = trace__symbols_init(trace, evlist); 483 if (err < 0) { | 483 goto out_delete_evlist; 484 } 485 486 err = trace__symbols_init(trace, evlist); 487 if (err < 0) { |
484 printf("Problems initializing symbol libraries!\n"); | 488 fprintf(trace->output, "Problems initializing symbol libraries!\n"); |
485 goto out_delete_maps; 486 } 487 488 perf_evlist__config(evlist, &trace->opts); 489 490 signal(SIGCHLD, sig_handler); 491 signal(SIGINT, sig_handler); 492 493 if (forks) { 494 err = perf_evlist__prepare_workload(evlist, &trace->opts.target, 495 argv, false, false); 496 if (err < 0) { | 489 goto out_delete_maps; 490 } 491 492 perf_evlist__config(evlist, &trace->opts); 493 494 signal(SIGCHLD, sig_handler); 495 signal(SIGINT, sig_handler); 496 497 if (forks) { 498 err = perf_evlist__prepare_workload(evlist, &trace->opts.target, 499 argv, false, false); 500 if (err < 0) { |
497 printf("Couldn't run the workload!\n"); | 501 fprintf(trace->output, "Couldn't run the workload!\n"); |
498 goto out_delete_maps; 499 } 500 } 501 502 err = perf_evlist__open(evlist); 503 if (err < 0) { | 502 goto out_delete_maps; 503 } 504 } 505 506 err = perf_evlist__open(evlist); 507 if (err < 0) { |
504 printf("Couldn't create the events: %s\n", strerror(errno)); | 508 fprintf(trace->output, "Couldn't create the events: %s\n", strerror(errno)); |
505 goto out_delete_maps; 506 } 507 508 err = perf_evlist__mmap(evlist, UINT_MAX, false); 509 if (err < 0) { | 509 goto out_delete_maps; 510 } 511 512 err = perf_evlist__mmap(evlist, UINT_MAX, false); 513 if (err < 0) { |
510 printf("Couldn't mmap the events: %s\n", strerror(errno)); | 514 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno)); |
511 goto out_close_evlist; 512 } 513 514 perf_evlist__enable(evlist); 515 516 if (forks) 517 perf_evlist__start_workload(evlist); 518 --- 8 unchanged lines hidden (view full) --- 527 const u32 type = event->header.type; 528 tracepoint_handler handler; 529 struct perf_sample sample; 530 531 ++trace->nr_events; 532 533 err = perf_evlist__parse_sample(evlist, event, &sample); 534 if (err) { | 515 goto out_close_evlist; 516 } 517 518 perf_evlist__enable(evlist); 519 520 if (forks) 521 perf_evlist__start_workload(evlist); 522 --- 8 unchanged lines hidden (view full) --- 531 const u32 type = event->header.type; 532 tracepoint_handler handler; 533 struct perf_sample sample; 534 535 ++trace->nr_events; 536 537 err = perf_evlist__parse_sample(evlist, event, &sample); 538 if (err) { |
535 printf("Can't parse sample, err = %d, skipping...\n", err); | 539 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err); |
536 continue; 537 } 538 539 if (trace->base_time == 0) 540 trace->base_time = sample.time; 541 542 if (type != PERF_RECORD_SAMPLE) { | 540 continue; 541 } 542 543 if (trace->base_time == 0) 544 trace->base_time = sample.time; 545 546 if (type != PERF_RECORD_SAMPLE) { |
543 trace__process_event(&trace->host, event); | 547 trace__process_event(trace, &trace->host, event); |
544 continue; 545 } 546 547 evsel = perf_evlist__id2evsel(evlist, sample.id); 548 if (evsel == NULL) { | 548 continue; 549 } 550 551 evsel = perf_evlist__id2evsel(evlist, sample.id); 552 if (evsel == NULL) { |
549 printf("Unknown tp ID %" PRIu64 ", skipping...\n", sample.id); | 553 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id); |
550 continue; 551 } 552 553 if (sample.raw_data == NULL) { | 554 continue; 555 } 556 557 if (sample.raw_data == NULL) { |
554 printf("%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", | 558 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", |
555 perf_evsel__name(evsel), sample.tid, 556 sample.cpu, sample.raw_size); 557 continue; 558 } 559 560 handler = evsel->handler.func; 561 handler(trace, evsel, &sample); 562 } --- 72 unchanged lines hidden (view full) --- 635 int unset __maybe_unused) 636{ 637 struct trace *trace = opt->value; 638 639 trace->duration_filter = atof(str); 640 return 0; 641} 642 | 559 perf_evsel__name(evsel), sample.tid, 560 sample.cpu, sample.raw_size); 561 continue; 562 } 563 564 handler = evsel->handler.func; 565 handler(trace, evsel, &sample); 566 } --- 72 unchanged lines hidden (view full) --- 639 int unset __maybe_unused) 640{ 641 struct trace *trace = opt->value; 642 643 trace->duration_filter = atof(str); 644 return 0; 645} 646 |
647static int trace__open_output(struct trace *trace, const char *filename) 648{ 649 struct stat st; 650 651 if (!stat(filename, &st) && st.st_size) { 652 char oldname[PATH_MAX]; 653 654 scnprintf(oldname, sizeof(oldname), "%s.old", filename); 655 unlink(oldname); 656 rename(filename, oldname); 657 } 658 659 trace->output = fopen(filename, "w"); 660 661 return trace->output == NULL ? -errno : 0; 662} 663 |
|
643int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) 644{ 645 const char * const trace_usage[] = { 646 "perf trace [<options>] [<command>]", 647 "perf trace [<options>] -- <command> [<options>]", 648 NULL 649 }; 650 struct trace trace = { --- 6 unchanged lines hidden (view full) --- 657 .uid = UINT_MAX, 658 .uses_mmap = true, 659 }, 660 .user_freq = UINT_MAX, 661 .user_interval = ULLONG_MAX, 662 .no_delay = true, 663 .mmap_pages = 1024, 664 }, | 664int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) 665{ 666 const char * const trace_usage[] = { 667 "perf trace [<options>] [<command>]", 668 "perf trace [<options>] -- <command> [<options>]", 669 NULL 670 }; 671 struct trace trace = { --- 6 unchanged lines hidden (view full) --- 678 .uid = UINT_MAX, 679 .uses_mmap = true, 680 }, 681 .user_freq = UINT_MAX, 682 .user_interval = ULLONG_MAX, 683 .no_delay = true, 684 .mmap_pages = 1024, 685 }, |
686 .output = stdout, |
|
665 }; | 687 }; |
688 const char *output_name = NULL; |
|
666 const char *ev_qualifier_str = NULL; 667 const struct option trace_options[] = { 668 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", 669 "list of events to trace"), | 689 const char *ev_qualifier_str = NULL; 690 const struct option trace_options[] = { 691 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", 692 "list of events to trace"), |
693 OPT_STRING('o', "output", &output_name, "file", "output file name"), |
|
670 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid", 671 "trace events on existing process id"), 672 OPT_STRING(0, "tid", &trace.opts.target.tid, "tid", 673 "trace events on existing thread id"), 674 OPT_BOOLEAN(0, "all-cpus", &trace.opts.target.system_wide, 675 "system-wide collection from all CPUs"), 676 OPT_STRING(0, "cpu", &trace.opts.target.cpu_list, "cpu", 677 "list of cpus to monitor"), --- 9 unchanged lines hidden (view full) --- 687 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"), 688 OPT_END() 689 }; 690 int err; 691 char bf[BUFSIZ]; 692 693 argc = parse_options(argc, argv, trace_options, trace_usage, 0); 694 | 694 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid", 695 "trace events on existing process id"), 696 OPT_STRING(0, "tid", &trace.opts.target.tid, "tid", 697 "trace events on existing thread id"), 698 OPT_BOOLEAN(0, "all-cpus", &trace.opts.target.system_wide, 699 "system-wide collection from all CPUs"), 700 OPT_STRING(0, "cpu", &trace.opts.target.cpu_list, "cpu", 701 "list of cpus to monitor"), --- 9 unchanged lines hidden (view full) --- 711 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"), 712 OPT_END() 713 }; 714 int err; 715 char bf[BUFSIZ]; 716 717 argc = parse_options(argc, argv, trace_options, trace_usage, 0); 718 |
719 if (output_name != NULL) { 720 err = trace__open_output(&trace, output_name); 721 if (err < 0) { 722 perror("failed to create output file"); 723 goto out; 724 } 725 } 726 |
|
695 if (ev_qualifier_str != NULL) { 696 trace.ev_qualifier = strlist__new(true, ev_qualifier_str); 697 if (trace.ev_qualifier == NULL) { | 727 if (ev_qualifier_str != NULL) { 728 trace.ev_qualifier = strlist__new(true, ev_qualifier_str); 729 if (trace.ev_qualifier == NULL) { |
698 puts("Not enough memory to parse event qualifier"); 699 return -ENOMEM; | 730 fputs("Not enough memory to parse event qualifier", 731 trace.output); 732 err = -ENOMEM; 733 goto out_close; |
700 } 701 } 702 703 err = perf_target__validate(&trace.opts.target); 704 if (err) { 705 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf)); | 734 } 735 } 736 737 err = perf_target__validate(&trace.opts.target); 738 if (err) { 739 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf)); |
706 printf("%s", bf); 707 return err; | 740 fprintf(trace.output, "%s", bf); 741 goto out_close; |
708 } 709 710 err = perf_target__parse_uid(&trace.opts.target); 711 if (err) { 712 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf)); | 742 } 743 744 err = perf_target__parse_uid(&trace.opts.target); 745 if (err) { 746 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf)); |
713 printf("%s", bf); 714 return err; | 747 fprintf(trace.output, "%s", bf); 748 goto out_close; |
715 } 716 717 if (!argc && perf_target__none(&trace.opts.target)) 718 trace.opts.target.system_wide = true; 719 720 err = trace__run(&trace, argc, argv); 721 722 if (trace.sched && !err) | 749 } 750 751 if (!argc && perf_target__none(&trace.opts.target)) 752 trace.opts.target.system_wide = true; 753 754 err = trace__run(&trace, argc, argv); 755 756 if (trace.sched && !err) |
723 trace__fprintf_thread_summary(&trace, stdout); | 757 trace__fprintf_thread_summary(&trace, trace.output); |
724 | 758 |
759out_close: 760 if (output_name != NULL) 761 fclose(trace.output); 762out: |
|
725 return err; 726} | 763 return err; 764} |