diff options
author | Tom Zanussi <tzanussi@gmail.com> | 2010-04-02 00:59:15 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-04-14 05:56:05 -0400 |
commit | 8dc58101f2c838355d44402aa77646649d10dbec (patch) | |
tree | d4cc08cccfec56d37dee4c4b2383ffe56d176494 /tools/perf/util/header.c | |
parent | c05556421742eb47f80301767653a4bcb19de9de (diff) |
perf: Add pipe-specific header read/write and event processing code
This patch makes several changes to allow the perf event stream
to be sent and received over a pipe:
- adds pipe-specific versions of the header read/write code
- adds pipe-specific version of the event processing code
- adds a range of event types to be used for header or other
pseudo events, above the range used by the kernel
- checks the return value of event handlers, which they can use
to skip over large events during event processing rather than actually
reading them into event objects.
- unifies the multiple do_read() functions and updates its
users.
Note that none of these changes affect the existing perf data
file format or processing - this code only comes into play if
perf output is sent to stdout (or is read from stdin).
Signed-off-by: Tom Zanussi <tzanussi@gmail.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Cc: fweisbec@gmail.com
Cc: rostedt@goodmis.org
Cc: k-keiichi@bx.jp.nec.com
Cc: acme@ghostprotocols.net
LKML-Reference: <1270184365-8281-2-git-send-email-tzanussi@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util/header.c')
-rw-r--r-- | tools/perf/util/header.c | 78 |
1 files changed, 60 insertions, 18 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 6c9aa16ee51f..8d05337d1a59 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -427,6 +427,25 @@ out_free: | |||
427 | return err; | 427 | return err; |
428 | } | 428 | } |
429 | 429 | ||
430 | int perf_header__write_pipe(int fd) | ||
431 | { | ||
432 | struct perf_pipe_file_header f_header; | ||
433 | int err; | ||
434 | |||
435 | f_header = (struct perf_pipe_file_header){ | ||
436 | .magic = PERF_MAGIC, | ||
437 | .size = sizeof(f_header), | ||
438 | }; | ||
439 | |||
440 | err = do_write(fd, &f_header, sizeof(f_header)); | ||
441 | if (err < 0) { | ||
442 | pr_debug("failed to write perf pipe header\n"); | ||
443 | return err; | ||
444 | } | ||
445 | |||
446 | return 0; | ||
447 | } | ||
448 | |||
430 | int perf_header__write(struct perf_header *self, int fd, bool at_exit) | 449 | int perf_header__write(struct perf_header *self, int fd, bool at_exit) |
431 | { | 450 | { |
432 | struct perf_file_header f_header; | 451 | struct perf_file_header f_header; |
@@ -518,25 +537,10 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit) | |||
518 | return 0; | 537 | return 0; |
519 | } | 538 | } |
520 | 539 | ||
521 | static int do_read(int fd, void *buf, size_t size) | ||
522 | { | ||
523 | while (size) { | ||
524 | int ret = read(fd, buf, size); | ||
525 | |||
526 | if (ret <= 0) | ||
527 | return -1; | ||
528 | |||
529 | size -= ret; | ||
530 | buf += ret; | ||
531 | } | ||
532 | |||
533 | return 0; | ||
534 | } | ||
535 | |||
536 | static int perf_header__getbuffer64(struct perf_header *self, | 540 | static int perf_header__getbuffer64(struct perf_header *self, |
537 | int fd, void *buf, size_t size) | 541 | int fd, void *buf, size_t size) |
538 | { | 542 | { |
539 | if (do_read(fd, buf, size)) | 543 | if (do_read(fd, buf, size) <= 0) |
540 | return -1; | 544 | return -1; |
541 | 545 | ||
542 | if (self->needs_swap) | 546 | if (self->needs_swap) |
@@ -592,7 +596,7 @@ int perf_file_header__read(struct perf_file_header *self, | |||
592 | { | 596 | { |
593 | lseek(fd, 0, SEEK_SET); | 597 | lseek(fd, 0, SEEK_SET); |
594 | 598 | ||
595 | if (do_read(fd, self, sizeof(*self)) || | 599 | if (do_read(fd, self, sizeof(*self)) <= 0 || |
596 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) | 600 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) |
597 | return -1; | 601 | return -1; |
598 | 602 | ||
@@ -662,13 +666,51 @@ static int perf_file_section__process(struct perf_file_section *self, | |||
662 | return 0; | 666 | return 0; |
663 | } | 667 | } |
664 | 668 | ||
665 | int perf_header__read(struct perf_header *self, int fd) | 669 | static int perf_file_header__read_pipe(struct perf_pipe_file_header *self, |
670 | struct perf_header *ph, int fd) | ||
666 | { | 671 | { |
672 | if (do_read(fd, self, sizeof(*self)) <= 0 || | ||
673 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) | ||
674 | return -1; | ||
675 | |||
676 | if (self->size != sizeof(*self)) { | ||
677 | u64 size = bswap_64(self->size); | ||
678 | |||
679 | if (size != sizeof(*self)) | ||
680 | return -1; | ||
681 | |||
682 | ph->needs_swap = true; | ||
683 | } | ||
684 | |||
685 | return 0; | ||
686 | } | ||
687 | |||
688 | static int perf_header__read_pipe(struct perf_session *session, int fd) | ||
689 | { | ||
690 | struct perf_header *self = &session->header; | ||
691 | struct perf_pipe_file_header f_header; | ||
692 | |||
693 | if (perf_file_header__read_pipe(&f_header, self, fd) < 0) { | ||
694 | pr_debug("incompatible file format\n"); | ||
695 | return -EINVAL; | ||
696 | } | ||
697 | |||
698 | session->fd = fd; | ||
699 | |||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | int perf_header__read(struct perf_session *session, int fd) | ||
704 | { | ||
705 | struct perf_header *self = &session->header; | ||
667 | struct perf_file_header f_header; | 706 | struct perf_file_header f_header; |
668 | struct perf_file_attr f_attr; | 707 | struct perf_file_attr f_attr; |
669 | u64 f_id; | 708 | u64 f_id; |
670 | int nr_attrs, nr_ids, i, j; | 709 | int nr_attrs, nr_ids, i, j; |
671 | 710 | ||
711 | if (session->fd_pipe) | ||
712 | return perf_header__read_pipe(session, fd); | ||
713 | |||
672 | if (perf_file_header__read(&f_header, self, fd) < 0) { | 714 | if (perf_file_header__read(&f_header, self, fd) < 0) { |
673 | pr_debug("incompatible file format\n"); | 715 | pr_debug("incompatible file format\n"); |
674 | return -EINVAL; | 716 | return -EINVAL; |