diff options
author | Frederic Weisbecker <fweisbec@gmail.com> | 2009-10-07 06:47:31 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-10-08 10:56:32 -0400 |
commit | 016e92fbc9ef33689cf654f343a94383d43235e7 (patch) | |
tree | edf9dc21d037ea138300b7e7e32574e6f6f17fb2 /tools/perf/builtin-sched.c | |
parent | 03456a158d9067d2f657bec170506009db81756d (diff) |
perf tools: Unify perf.data mapping and events handling
This librarizes the perf.data file mapping and handling in various
perf tools, roughly reducing the amount of code and fixing the
places that mmap from beginning of the file whereas we want to mmap
from the beginning of the data, leading to page fault because the
mmap window is too small since the trace info are written in the
file too.
TODO:
- convert perf timechart too
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arjan van de Ven <arjan@infradead.org>
LKML-Reference: <20091007104729.GD5043@nowhere>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/builtin-sched.c')
-rw-r--r-- | tools/perf/builtin-sched.c | 140 |
1 files changed, 27 insertions, 113 deletions
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 18871380b015..e1df7055ab82 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include "util/trace-event.h" | 11 | #include "util/trace-event.h" |
12 | 12 | ||
13 | #include "util/debug.h" | 13 | #include "util/debug.h" |
14 | #include "util/data_map.h" | ||
14 | 15 | ||
15 | #include <sys/types.h> | 16 | #include <sys/types.h> |
16 | #include <sys/prctl.h> | 17 | #include <sys/prctl.h> |
@@ -20,9 +21,6 @@ | |||
20 | #include <math.h> | 21 | #include <math.h> |
21 | 22 | ||
22 | static char const *input_name = "perf.data"; | 23 | static char const *input_name = "perf.data"; |
23 | static int input; | ||
24 | static unsigned long page_size; | ||
25 | static unsigned long mmap_window = 32; | ||
26 | 24 | ||
27 | static unsigned long total_comm = 0; | 25 | static unsigned long total_comm = 0; |
28 | 26 | ||
@@ -35,6 +33,9 @@ static u64 sample_type; | |||
35 | static char default_sort_order[] = "avg, max, switch, runtime"; | 33 | static char default_sort_order[] = "avg, max, switch, runtime"; |
36 | static char *sort_order = default_sort_order; | 34 | static char *sort_order = default_sort_order; |
37 | 35 | ||
36 | static char *cwd; | ||
37 | static int cwdlen; | ||
38 | |||
38 | #define PR_SET_NAME 15 /* Set process name */ | 39 | #define PR_SET_NAME 15 /* Set process name */ |
39 | #define MAX_CPUS 4096 | 40 | #define MAX_CPUS 4096 |
40 | 41 | ||
@@ -1594,129 +1595,43 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) | |||
1594 | } | 1595 | } |
1595 | 1596 | ||
1596 | static int | 1597 | static int |
1597 | process_event(event_t *event, unsigned long offset, unsigned long head) | 1598 | process_lost_event(event_t *event __used, |
1599 | unsigned long offset __used, | ||
1600 | unsigned long head __used) | ||
1598 | { | 1601 | { |
1599 | trace_event(event); | 1602 | nr_lost_chunks++; |
1600 | 1603 | nr_lost_events += event->lost.lost; | |
1601 | nr_events++; | ||
1602 | switch (event->header.type) { | ||
1603 | case PERF_RECORD_MMAP: | ||
1604 | return 0; | ||
1605 | case PERF_RECORD_LOST: | ||
1606 | nr_lost_chunks++; | ||
1607 | nr_lost_events += event->lost.lost; | ||
1608 | return 0; | ||
1609 | |||
1610 | case PERF_RECORD_COMM: | ||
1611 | return process_comm_event(event, offset, head); | ||
1612 | 1604 | ||
1613 | case PERF_RECORD_EXIT ... PERF_RECORD_READ: | 1605 | return 0; |
1614 | return 0; | 1606 | } |
1615 | 1607 | ||
1616 | case PERF_RECORD_SAMPLE: | 1608 | static int sample_type_check(u64 type) |
1617 | return process_sample_event(event, offset, head); | 1609 | { |
1610 | sample_type = type; | ||
1618 | 1611 | ||
1619 | case PERF_RECORD_MAX: | 1612 | if (!(sample_type & PERF_SAMPLE_RAW)) { |
1620 | default: | 1613 | fprintf(stderr, |
1614 | "No trace sample to read. Did you call perf record " | ||
1615 | "without -R?"); | ||
1621 | return -1; | 1616 | return -1; |
1622 | } | 1617 | } |
1623 | 1618 | ||
1624 | return 0; | 1619 | return 0; |
1625 | } | 1620 | } |
1626 | 1621 | ||
1622 | static struct perf_file_handler file_handler = { | ||
1623 | .process_sample_event = process_sample_event, | ||
1624 | .process_comm_event = process_comm_event, | ||
1625 | .process_lost_event = process_lost_event, | ||
1626 | .sample_type_check = sample_type_check, | ||
1627 | }; | ||
1628 | |||
1627 | static int read_events(void) | 1629 | static int read_events(void) |
1628 | { | 1630 | { |
1629 | int ret, rc = EXIT_FAILURE; | ||
1630 | unsigned long offset = 0; | ||
1631 | unsigned long head = 0; | ||
1632 | struct stat perf_stat; | ||
1633 | event_t *event; | ||
1634 | uint32_t size; | ||
1635 | char *buf; | ||
1636 | |||
1637 | register_idle_thread(&threads, &last_match); | 1631 | register_idle_thread(&threads, &last_match); |
1632 | register_perf_file_handler(&file_handler); | ||
1638 | 1633 | ||
1639 | input = open(input_name, O_RDONLY); | 1634 | return mmap_dispatch_perf_file(&header, input_name, 0, 0, &cwdlen, &cwd); |
1640 | if (input < 0) { | ||
1641 | perror("failed to open file"); | ||
1642 | exit(-1); | ||
1643 | } | ||
1644 | |||
1645 | ret = fstat(input, &perf_stat); | ||
1646 | if (ret < 0) { | ||
1647 | perror("failed to stat file"); | ||
1648 | exit(-1); | ||
1649 | } | ||
1650 | |||
1651 | if (!perf_stat.st_size) { | ||
1652 | fprintf(stderr, "zero-sized file, nothing to do!\n"); | ||
1653 | exit(0); | ||
1654 | } | ||
1655 | header = perf_header__read(input); | ||
1656 | head = header->data_offset; | ||
1657 | sample_type = perf_header__sample_type(header); | ||
1658 | |||
1659 | if (!(sample_type & PERF_SAMPLE_RAW)) | ||
1660 | die("No trace sample to read. Did you call perf record " | ||
1661 | "without -R?"); | ||
1662 | |||
1663 | if (load_kernel() < 0) { | ||
1664 | perror("failed to load kernel symbols"); | ||
1665 | return EXIT_FAILURE; | ||
1666 | } | ||
1667 | |||
1668 | remap: | ||
1669 | buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ, | ||
1670 | MAP_SHARED, input, offset); | ||
1671 | if (buf == MAP_FAILED) { | ||
1672 | perror("failed to mmap file"); | ||
1673 | exit(-1); | ||
1674 | } | ||
1675 | |||
1676 | more: | ||
1677 | event = (event_t *)(buf + head); | ||
1678 | |||
1679 | size = event->header.size; | ||
1680 | if (!size) | ||
1681 | size = 8; | ||
1682 | |||
1683 | if (head + event->header.size >= page_size * mmap_window) { | ||
1684 | unsigned long shift = page_size * (head / page_size); | ||
1685 | int res; | ||
1686 | |||
1687 | res = munmap(buf, page_size * mmap_window); | ||
1688 | assert(res == 0); | ||
1689 | |||
1690 | offset += shift; | ||
1691 | head -= shift; | ||
1692 | goto remap; | ||
1693 | } | ||
1694 | |||
1695 | size = event->header.size; | ||
1696 | |||
1697 | |||
1698 | if (!size || process_event(event, offset, head) < 0) { | ||
1699 | |||
1700 | /* | ||
1701 | * assume we lost track of the stream, check alignment, and | ||
1702 | * increment a single u64 in the hope to catch on again 'soon'. | ||
1703 | */ | ||
1704 | |||
1705 | if (unlikely(head & 7)) | ||
1706 | head &= ~7ULL; | ||
1707 | |||
1708 | size = 8; | ||
1709 | } | ||
1710 | |||
1711 | head += size; | ||
1712 | |||
1713 | if (offset + head < (unsigned long)perf_stat.st_size) | ||
1714 | goto more; | ||
1715 | |||
1716 | rc = EXIT_SUCCESS; | ||
1717 | close(input); | ||
1718 | |||
1719 | return rc; | ||
1720 | } | 1635 | } |
1721 | 1636 | ||
1722 | static void print_bad_events(void) | 1637 | static void print_bad_events(void) |
@@ -1934,7 +1849,6 @@ static int __cmd_record(int argc, const char **argv) | |||
1934 | int cmd_sched(int argc, const char **argv, const char *prefix __used) | 1849 | int cmd_sched(int argc, const char **argv, const char *prefix __used) |
1935 | { | 1850 | { |
1936 | symbol__init(); | 1851 | symbol__init(); |
1937 | page_size = getpagesize(); | ||
1938 | 1852 | ||
1939 | argc = parse_options(argc, argv, sched_options, sched_usage, | 1853 | argc = parse_options(argc, argv, sched_options, sched_usage, |
1940 | PARSE_OPT_STOP_AT_NON_OPTION); | 1854 | PARSE_OPT_STOP_AT_NON_OPTION); |