diff options
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); |