diff options
Diffstat (limited to 'tools/perf/util/session.c')
-rw-r--r-- | tools/perf/util/session.c | 278 |
1 files changed, 132 insertions, 146 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 568b750c01f6..f36d24a02445 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -16,73 +16,34 @@ | |||
16 | #include "perf_regs.h" | 16 | #include "perf_regs.h" |
17 | #include "vdso.h" | 17 | #include "vdso.h" |
18 | 18 | ||
19 | static int perf_session__open(struct perf_session *self, bool force) | 19 | static int perf_session__open(struct perf_session *session) |
20 | { | 20 | { |
21 | struct stat input_stat; | 21 | struct perf_data_file *file = session->file; |
22 | 22 | ||
23 | if (!strcmp(self->filename, "-")) { | 23 | if (perf_session__read_header(session) < 0) { |
24 | self->fd_pipe = true; | ||
25 | self->fd = STDIN_FILENO; | ||
26 | |||
27 | if (perf_session__read_header(self) < 0) | ||
28 | pr_err("incompatible file format (rerun with -v to learn more)"); | ||
29 | |||
30 | return 0; | ||
31 | } | ||
32 | |||
33 | self->fd = open(self->filename, O_RDONLY); | ||
34 | if (self->fd < 0) { | ||
35 | int err = errno; | ||
36 | |||
37 | pr_err("failed to open %s: %s", self->filename, strerror(err)); | ||
38 | if (err == ENOENT && !strcmp(self->filename, "perf.data")) | ||
39 | pr_err(" (try 'perf record' first)"); | ||
40 | pr_err("\n"); | ||
41 | return -errno; | ||
42 | } | ||
43 | |||
44 | if (fstat(self->fd, &input_stat) < 0) | ||
45 | goto out_close; | ||
46 | |||
47 | if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) { | ||
48 | pr_err("file %s not owned by current user or root\n", | ||
49 | self->filename); | ||
50 | goto out_close; | ||
51 | } | ||
52 | |||
53 | if (!input_stat.st_size) { | ||
54 | pr_info("zero-sized file (%s), nothing to do!\n", | ||
55 | self->filename); | ||
56 | goto out_close; | ||
57 | } | ||
58 | |||
59 | if (perf_session__read_header(self) < 0) { | ||
60 | pr_err("incompatible file format (rerun with -v to learn more)"); | 24 | pr_err("incompatible file format (rerun with -v to learn more)"); |
61 | goto out_close; | 25 | return -1; |
62 | } | 26 | } |
63 | 27 | ||
64 | if (!perf_evlist__valid_sample_type(self->evlist)) { | 28 | if (perf_data_file__is_pipe(file)) |
29 | return 0; | ||
30 | |||
31 | if (!perf_evlist__valid_sample_type(session->evlist)) { | ||
65 | pr_err("non matching sample_type"); | 32 | pr_err("non matching sample_type"); |
66 | goto out_close; | 33 | return -1; |
67 | } | 34 | } |
68 | 35 | ||
69 | if (!perf_evlist__valid_sample_id_all(self->evlist)) { | 36 | if (!perf_evlist__valid_sample_id_all(session->evlist)) { |
70 | pr_err("non matching sample_id_all"); | 37 | pr_err("non matching sample_id_all"); |
71 | goto out_close; | 38 | return -1; |
72 | } | 39 | } |
73 | 40 | ||
74 | if (!perf_evlist__valid_read_format(self->evlist)) { | 41 | if (!perf_evlist__valid_read_format(session->evlist)) { |
75 | pr_err("non matching read_format"); | 42 | pr_err("non matching read_format"); |
76 | goto out_close; | 43 | return -1; |
77 | } | 44 | } |
78 | 45 | ||
79 | self->size = input_stat.st_size; | ||
80 | return 0; | 46 | return 0; |
81 | |||
82 | out_close: | ||
83 | close(self->fd); | ||
84 | self->fd = -1; | ||
85 | return -1; | ||
86 | } | 47 | } |
87 | 48 | ||
88 | void perf_session__set_id_hdr_size(struct perf_session *session) | 49 | void perf_session__set_id_hdr_size(struct perf_session *session) |
@@ -92,71 +53,70 @@ void perf_session__set_id_hdr_size(struct perf_session *session) | |||
92 | machines__set_id_hdr_size(&session->machines, id_hdr_size); | 53 | machines__set_id_hdr_size(&session->machines, id_hdr_size); |
93 | } | 54 | } |
94 | 55 | ||
95 | int perf_session__create_kernel_maps(struct perf_session *self) | 56 | int perf_session__create_kernel_maps(struct perf_session *session) |
96 | { | 57 | { |
97 | int ret = machine__create_kernel_maps(&self->machines.host); | 58 | int ret = machine__create_kernel_maps(&session->machines.host); |
98 | 59 | ||
99 | if (ret >= 0) | 60 | if (ret >= 0) |
100 | ret = machines__create_guest_kernel_maps(&self->machines); | 61 | ret = machines__create_guest_kernel_maps(&session->machines); |
101 | return ret; | 62 | return ret; |
102 | } | 63 | } |
103 | 64 | ||
104 | static void perf_session__destroy_kernel_maps(struct perf_session *self) | 65 | static void perf_session__destroy_kernel_maps(struct perf_session *session) |
105 | { | 66 | { |
106 | machines__destroy_kernel_maps(&self->machines); | 67 | machines__destroy_kernel_maps(&session->machines); |
107 | } | 68 | } |
108 | 69 | ||
109 | struct perf_session *perf_session__new(const char *filename, int mode, | 70 | struct perf_session *perf_session__new(struct perf_data_file *file, |
110 | bool force, bool repipe, | 71 | bool repipe, struct perf_tool *tool) |
111 | struct perf_tool *tool) | ||
112 | { | 72 | { |
113 | struct perf_session *self; | 73 | struct perf_session *session = zalloc(sizeof(*session)); |
114 | struct stat st; | ||
115 | size_t len; | ||
116 | |||
117 | if (!filename || !strlen(filename)) { | ||
118 | if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) | ||
119 | filename = "-"; | ||
120 | else | ||
121 | filename = "perf.data"; | ||
122 | } | ||
123 | 74 | ||
124 | len = strlen(filename); | 75 | if (!session) |
125 | self = zalloc(sizeof(*self) + len); | ||
126 | |||
127 | if (self == NULL) | ||
128 | goto out; | 76 | goto out; |
129 | 77 | ||
130 | memcpy(self->filename, filename, len); | 78 | session->repipe = repipe; |
131 | self->repipe = repipe; | 79 | INIT_LIST_HEAD(&session->ordered_samples.samples); |
132 | INIT_LIST_HEAD(&self->ordered_samples.samples); | 80 | INIT_LIST_HEAD(&session->ordered_samples.sample_cache); |
133 | INIT_LIST_HEAD(&self->ordered_samples.sample_cache); | 81 | INIT_LIST_HEAD(&session->ordered_samples.to_free); |
134 | INIT_LIST_HEAD(&self->ordered_samples.to_free); | 82 | machines__init(&session->machines); |
135 | machines__init(&self->machines); | ||
136 | 83 | ||
137 | if (mode == O_RDONLY) { | 84 | if (file) { |
138 | if (perf_session__open(self, force) < 0) | 85 | if (perf_data_file__open(file)) |
139 | goto out_delete; | 86 | goto out_delete; |
140 | perf_session__set_id_hdr_size(self); | 87 | |
141 | } else if (mode == O_WRONLY) { | 88 | session->file = file; |
89 | |||
90 | if (perf_data_file__is_read(file)) { | ||
91 | if (perf_session__open(session) < 0) | ||
92 | goto out_close; | ||
93 | |||
94 | perf_session__set_id_hdr_size(session); | ||
95 | } | ||
96 | } | ||
97 | |||
98 | if (!file || perf_data_file__is_write(file)) { | ||
142 | /* | 99 | /* |
143 | * In O_RDONLY mode this will be performed when reading the | 100 | * In O_RDONLY mode this will be performed when reading the |
144 | * kernel MMAP event, in perf_event__process_mmap(). | 101 | * kernel MMAP event, in perf_event__process_mmap(). |
145 | */ | 102 | */ |
146 | if (perf_session__create_kernel_maps(self) < 0) | 103 | if (perf_session__create_kernel_maps(session) < 0) |
147 | goto out_delete; | 104 | goto out_delete; |
148 | } | 105 | } |
149 | 106 | ||
150 | if (tool && tool->ordering_requires_timestamps && | 107 | if (tool && tool->ordering_requires_timestamps && |
151 | tool->ordered_samples && !perf_evlist__sample_id_all(self->evlist)) { | 108 | tool->ordered_samples && !perf_evlist__sample_id_all(session->evlist)) { |
152 | dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); | 109 | dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); |
153 | tool->ordered_samples = false; | 110 | tool->ordered_samples = false; |
154 | } | 111 | } |
155 | 112 | ||
156 | out: | 113 | return session; |
157 | return self; | 114 | |
158 | out_delete: | 115 | out_close: |
159 | perf_session__delete(self); | 116 | perf_data_file__close(file); |
117 | out_delete: | ||
118 | perf_session__delete(session); | ||
119 | out: | ||
160 | return NULL; | 120 | return NULL; |
161 | } | 121 | } |
162 | 122 | ||
@@ -186,15 +146,16 @@ static void perf_session_env__delete(struct perf_session_env *env) | |||
186 | free(env->pmu_mappings); | 146 | free(env->pmu_mappings); |
187 | } | 147 | } |
188 | 148 | ||
189 | void perf_session__delete(struct perf_session *self) | 149 | void perf_session__delete(struct perf_session *session) |
190 | { | 150 | { |
191 | perf_session__destroy_kernel_maps(self); | 151 | perf_session__destroy_kernel_maps(session); |
192 | perf_session__delete_dead_threads(self); | 152 | perf_session__delete_dead_threads(session); |
193 | perf_session__delete_threads(self); | 153 | perf_session__delete_threads(session); |
194 | perf_session_env__delete(&self->header.env); | 154 | perf_session_env__delete(&session->header.env); |
195 | machines__exit(&self->machines); | 155 | machines__exit(&session->machines); |
196 | close(self->fd); | 156 | if (session->file) |
197 | free(self); | 157 | perf_data_file__close(session->file); |
158 | free(session); | ||
198 | vdso__exit(); | 159 | vdso__exit(); |
199 | } | 160 | } |
200 | 161 | ||
@@ -397,6 +358,17 @@ static void perf_event__read_swap(union perf_event *event, bool sample_id_all) | |||
397 | swap_sample_id_all(event, &event->read + 1); | 358 | swap_sample_id_all(event, &event->read + 1); |
398 | } | 359 | } |
399 | 360 | ||
361 | static void perf_event__throttle_swap(union perf_event *event, | ||
362 | bool sample_id_all) | ||
363 | { | ||
364 | event->throttle.time = bswap_64(event->throttle.time); | ||
365 | event->throttle.id = bswap_64(event->throttle.id); | ||
366 | event->throttle.stream_id = bswap_64(event->throttle.stream_id); | ||
367 | |||
368 | if (sample_id_all) | ||
369 | swap_sample_id_all(event, &event->throttle + 1); | ||
370 | } | ||
371 | |||
400 | static u8 revbyte(u8 b) | 372 | static u8 revbyte(u8 b) |
401 | { | 373 | { |
402 | int rev = (b >> 4) | ((b & 0xf) << 4); | 374 | int rev = (b >> 4) | ((b & 0xf) << 4); |
@@ -442,6 +414,9 @@ void perf_event__attr_swap(struct perf_event_attr *attr) | |||
442 | attr->bp_type = bswap_32(attr->bp_type); | 414 | attr->bp_type = bswap_32(attr->bp_type); |
443 | attr->bp_addr = bswap_64(attr->bp_addr); | 415 | attr->bp_addr = bswap_64(attr->bp_addr); |
444 | attr->bp_len = bswap_64(attr->bp_len); | 416 | attr->bp_len = bswap_64(attr->bp_len); |
417 | attr->branch_sample_type = bswap_64(attr->branch_sample_type); | ||
418 | attr->sample_regs_user = bswap_64(attr->sample_regs_user); | ||
419 | attr->sample_stack_user = bswap_32(attr->sample_stack_user); | ||
445 | 420 | ||
446 | swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64)); | 421 | swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64)); |
447 | } | 422 | } |
@@ -482,6 +457,8 @@ static perf_event__swap_op perf_event__swap_ops[] = { | |||
482 | [PERF_RECORD_EXIT] = perf_event__task_swap, | 457 | [PERF_RECORD_EXIT] = perf_event__task_swap, |
483 | [PERF_RECORD_LOST] = perf_event__all64_swap, | 458 | [PERF_RECORD_LOST] = perf_event__all64_swap, |
484 | [PERF_RECORD_READ] = perf_event__read_swap, | 459 | [PERF_RECORD_READ] = perf_event__read_swap, |
460 | [PERF_RECORD_THROTTLE] = perf_event__throttle_swap, | ||
461 | [PERF_RECORD_UNTHROTTLE] = perf_event__throttle_swap, | ||
485 | [PERF_RECORD_SAMPLE] = perf_event__all64_swap, | 462 | [PERF_RECORD_SAMPLE] = perf_event__all64_swap, |
486 | [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap, | 463 | [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap, |
487 | [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, | 464 | [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, |
@@ -525,13 +502,16 @@ static int flush_sample_queue(struct perf_session *s, | |||
525 | struct perf_sample sample; | 502 | struct perf_sample sample; |
526 | u64 limit = os->next_flush; | 503 | u64 limit = os->next_flush; |
527 | u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; | 504 | u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; |
528 | unsigned idx = 0, progress_next = os->nr_samples / 16; | ||
529 | bool show_progress = limit == ULLONG_MAX; | 505 | bool show_progress = limit == ULLONG_MAX; |
506 | struct ui_progress prog; | ||
530 | int ret; | 507 | int ret; |
531 | 508 | ||
532 | if (!tool->ordered_samples || !limit) | 509 | if (!tool->ordered_samples || !limit) |
533 | return 0; | 510 | return 0; |
534 | 511 | ||
512 | if (show_progress) | ||
513 | ui_progress__init(&prog, os->nr_samples, "Processing time ordered events..."); | ||
514 | |||
535 | list_for_each_entry_safe(iter, tmp, head, list) { | 515 | list_for_each_entry_safe(iter, tmp, head, list) { |
536 | if (session_done()) | 516 | if (session_done()) |
537 | return 0; | 517 | return 0; |
@@ -552,11 +532,9 @@ static int flush_sample_queue(struct perf_session *s, | |||
552 | os->last_flush = iter->timestamp; | 532 | os->last_flush = iter->timestamp; |
553 | list_del(&iter->list); | 533 | list_del(&iter->list); |
554 | list_add(&iter->list, &os->sample_cache); | 534 | list_add(&iter->list, &os->sample_cache); |
555 | if (show_progress && (++idx >= progress_next)) { | 535 | |
556 | progress_next += os->nr_samples / 16; | 536 | if (show_progress) |
557 | ui_progress__update(idx, os->nr_samples, | 537 | ui_progress__update(&prog, 1); |
558 | "Processing time ordered events..."); | ||
559 | } | ||
560 | } | 538 | } |
561 | 539 | ||
562 | if (list_empty(head)) { | 540 | if (list_empty(head)) { |
@@ -860,6 +838,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event, | |||
860 | if (sample_type & PERF_SAMPLE_DATA_SRC) | 838 | if (sample_type & PERF_SAMPLE_DATA_SRC) |
861 | printf(" . data_src: 0x%"PRIx64"\n", sample->data_src); | 839 | printf(" . data_src: 0x%"PRIx64"\n", sample->data_src); |
862 | 840 | ||
841 | if (sample_type & PERF_SAMPLE_TRANSACTION) | ||
842 | printf("... transaction: %" PRIx64 "\n", sample->transaction); | ||
843 | |||
863 | if (sample_type & PERF_SAMPLE_READ) | 844 | if (sample_type & PERF_SAMPLE_READ) |
864 | sample_read__printf(sample, evsel->attr.read_format); | 845 | sample_read__printf(sample, evsel->attr.read_format); |
865 | } | 846 | } |
@@ -1031,6 +1012,7 @@ static int perf_session_deliver_event(struct perf_session *session, | |||
1031 | static int perf_session__process_user_event(struct perf_session *session, union perf_event *event, | 1012 | static int perf_session__process_user_event(struct perf_session *session, union perf_event *event, |
1032 | struct perf_tool *tool, u64 file_offset) | 1013 | struct perf_tool *tool, u64 file_offset) |
1033 | { | 1014 | { |
1015 | int fd = perf_data_file__fd(session->file); | ||
1034 | int err; | 1016 | int err; |
1035 | 1017 | ||
1036 | dump_event(session, event, file_offset, NULL); | 1018 | dump_event(session, event, file_offset, NULL); |
@@ -1044,7 +1026,7 @@ static int perf_session__process_user_event(struct perf_session *session, union | |||
1044 | return err; | 1026 | return err; |
1045 | case PERF_RECORD_HEADER_TRACING_DATA: | 1027 | case PERF_RECORD_HEADER_TRACING_DATA: |
1046 | /* setup for reading amidst mmap */ | 1028 | /* setup for reading amidst mmap */ |
1047 | lseek(session->fd, file_offset, SEEK_SET); | 1029 | lseek(fd, file_offset, SEEK_SET); |
1048 | return tool->tracing_data(tool, event, session); | 1030 | return tool->tracing_data(tool, event, session); |
1049 | case PERF_RECORD_HEADER_BUILD_ID: | 1031 | case PERF_RECORD_HEADER_BUILD_ID: |
1050 | return tool->build_id(tool, event, session); | 1032 | return tool->build_id(tool, event, session); |
@@ -1101,11 +1083,11 @@ static int perf_session__process_event(struct perf_session *session, | |||
1101 | file_offset); | 1083 | file_offset); |
1102 | } | 1084 | } |
1103 | 1085 | ||
1104 | void perf_event_header__bswap(struct perf_event_header *self) | 1086 | void perf_event_header__bswap(struct perf_event_header *hdr) |
1105 | { | 1087 | { |
1106 | self->type = bswap_32(self->type); | 1088 | hdr->type = bswap_32(hdr->type); |
1107 | self->misc = bswap_16(self->misc); | 1089 | hdr->misc = bswap_16(hdr->misc); |
1108 | self->size = bswap_16(self->size); | 1090 | hdr->size = bswap_16(hdr->size); |
1109 | } | 1091 | } |
1110 | 1092 | ||
1111 | struct thread *perf_session__findnew(struct perf_session *session, pid_t pid) | 1093 | struct thread *perf_session__findnew(struct perf_session *session, pid_t pid) |
@@ -1113,11 +1095,11 @@ struct thread *perf_session__findnew(struct perf_session *session, pid_t pid) | |||
1113 | return machine__findnew_thread(&session->machines.host, 0, pid); | 1095 | return machine__findnew_thread(&session->machines.host, 0, pid); |
1114 | } | 1096 | } |
1115 | 1097 | ||
1116 | static struct thread *perf_session__register_idle_thread(struct perf_session *self) | 1098 | static struct thread *perf_session__register_idle_thread(struct perf_session *session) |
1117 | { | 1099 | { |
1118 | struct thread *thread = perf_session__findnew(self, 0); | 1100 | struct thread *thread = perf_session__findnew(session, 0); |
1119 | 1101 | ||
1120 | if (thread == NULL || thread__set_comm(thread, "swapper")) { | 1102 | if (thread == NULL || thread__set_comm(thread, "swapper", 0)) { |
1121 | pr_err("problem inserting idle task.\n"); | 1103 | pr_err("problem inserting idle task.\n"); |
1122 | thread = NULL; | 1104 | thread = NULL; |
1123 | } | 1105 | } |
@@ -1167,9 +1149,10 @@ static void perf_session__warn_about_errors(const struct perf_session *session, | |||
1167 | 1149 | ||
1168 | volatile int session_done; | 1150 | volatile int session_done; |
1169 | 1151 | ||
1170 | static int __perf_session__process_pipe_events(struct perf_session *self, | 1152 | static int __perf_session__process_pipe_events(struct perf_session *session, |
1171 | struct perf_tool *tool) | 1153 | struct perf_tool *tool) |
1172 | { | 1154 | { |
1155 | int fd = perf_data_file__fd(session->file); | ||
1173 | union perf_event *event; | 1156 | union perf_event *event; |
1174 | uint32_t size, cur_size = 0; | 1157 | uint32_t size, cur_size = 0; |
1175 | void *buf = NULL; | 1158 | void *buf = NULL; |
@@ -1188,7 +1171,7 @@ static int __perf_session__process_pipe_events(struct perf_session *self, | |||
1188 | return -errno; | 1171 | return -errno; |
1189 | more: | 1172 | more: |
1190 | event = buf; | 1173 | event = buf; |
1191 | err = readn(self->fd, event, sizeof(struct perf_event_header)); | 1174 | err = readn(fd, event, sizeof(struct perf_event_header)); |
1192 | if (err <= 0) { | 1175 | if (err <= 0) { |
1193 | if (err == 0) | 1176 | if (err == 0) |
1194 | goto done; | 1177 | goto done; |
@@ -1197,7 +1180,7 @@ more: | |||
1197 | goto out_err; | 1180 | goto out_err; |
1198 | } | 1181 | } |
1199 | 1182 | ||
1200 | if (self->header.needs_swap) | 1183 | if (session->header.needs_swap) |
1201 | perf_event_header__bswap(&event->header); | 1184 | perf_event_header__bswap(&event->header); |
1202 | 1185 | ||
1203 | size = event->header.size; | 1186 | size = event->header.size; |
@@ -1220,7 +1203,7 @@ more: | |||
1220 | p += sizeof(struct perf_event_header); | 1203 | p += sizeof(struct perf_event_header); |
1221 | 1204 | ||
1222 | if (size - sizeof(struct perf_event_header)) { | 1205 | if (size - sizeof(struct perf_event_header)) { |
1223 | err = readn(self->fd, p, size - sizeof(struct perf_event_header)); | 1206 | err = readn(fd, p, size - sizeof(struct perf_event_header)); |
1224 | if (err <= 0) { | 1207 | if (err <= 0) { |
1225 | if (err == 0) { | 1208 | if (err == 0) { |
1226 | pr_err("unexpected end of event stream\n"); | 1209 | pr_err("unexpected end of event stream\n"); |
@@ -1232,7 +1215,7 @@ more: | |||
1232 | } | 1215 | } |
1233 | } | 1216 | } |
1234 | 1217 | ||
1235 | if ((skip = perf_session__process_event(self, event, tool, head)) < 0) { | 1218 | if ((skip = perf_session__process_event(session, event, tool, head)) < 0) { |
1236 | pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", | 1219 | pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", |
1237 | head, event->header.size, event->header.type); | 1220 | head, event->header.size, event->header.type); |
1238 | err = -EINVAL; | 1221 | err = -EINVAL; |
@@ -1247,11 +1230,13 @@ more: | |||
1247 | if (!session_done()) | 1230 | if (!session_done()) |
1248 | goto more; | 1231 | goto more; |
1249 | done: | 1232 | done: |
1250 | err = 0; | 1233 | /* do the final flush for ordered samples */ |
1234 | session->ordered_samples.next_flush = ULLONG_MAX; | ||
1235 | err = flush_sample_queue(session, tool); | ||
1251 | out_err: | 1236 | out_err: |
1252 | free(buf); | 1237 | free(buf); |
1253 | perf_session__warn_about_errors(self, tool); | 1238 | perf_session__warn_about_errors(session, tool); |
1254 | perf_session_free_sample_buffers(self); | 1239 | perf_session_free_sample_buffers(session); |
1255 | return err; | 1240 | return err; |
1256 | } | 1241 | } |
1257 | 1242 | ||
@@ -1299,12 +1284,14 @@ int __perf_session__process_events(struct perf_session *session, | |||
1299 | u64 data_offset, u64 data_size, | 1284 | u64 data_offset, u64 data_size, |
1300 | u64 file_size, struct perf_tool *tool) | 1285 | u64 file_size, struct perf_tool *tool) |
1301 | { | 1286 | { |
1302 | u64 head, page_offset, file_offset, file_pos, progress_next; | 1287 | int fd = perf_data_file__fd(session->file); |
1288 | u64 head, page_offset, file_offset, file_pos; | ||
1303 | int err, mmap_prot, mmap_flags, map_idx = 0; | 1289 | int err, mmap_prot, mmap_flags, map_idx = 0; |
1304 | size_t mmap_size; | 1290 | size_t mmap_size; |
1305 | char *buf, *mmaps[NUM_MMAPS]; | 1291 | char *buf, *mmaps[NUM_MMAPS]; |
1306 | union perf_event *event; | 1292 | union perf_event *event; |
1307 | uint32_t size; | 1293 | uint32_t size; |
1294 | struct ui_progress prog; | ||
1308 | 1295 | ||
1309 | perf_tool__fill_defaults(tool); | 1296 | perf_tool__fill_defaults(tool); |
1310 | 1297 | ||
@@ -1315,7 +1302,7 @@ int __perf_session__process_events(struct perf_session *session, | |||
1315 | if (data_size && (data_offset + data_size < file_size)) | 1302 | if (data_size && (data_offset + data_size < file_size)) |
1316 | file_size = data_offset + data_size; | 1303 | file_size = data_offset + data_size; |
1317 | 1304 | ||
1318 | progress_next = file_size / 16; | 1305 | ui_progress__init(&prog, file_size, "Processing events..."); |
1319 | 1306 | ||
1320 | mmap_size = MMAP_SIZE; | 1307 | mmap_size = MMAP_SIZE; |
1321 | if (mmap_size > file_size) | 1308 | if (mmap_size > file_size) |
@@ -1331,7 +1318,7 @@ int __perf_session__process_events(struct perf_session *session, | |||
1331 | mmap_flags = MAP_PRIVATE; | 1318 | mmap_flags = MAP_PRIVATE; |
1332 | } | 1319 | } |
1333 | remap: | 1320 | remap: |
1334 | buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, session->fd, | 1321 | buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, fd, |
1335 | file_offset); | 1322 | file_offset); |
1336 | if (buf == MAP_FAILED) { | 1323 | if (buf == MAP_FAILED) { |
1337 | pr_err("failed to mmap file\n"); | 1324 | pr_err("failed to mmap file\n"); |
@@ -1370,19 +1357,15 @@ more: | |||
1370 | head += size; | 1357 | head += size; |
1371 | file_pos += size; | 1358 | file_pos += size; |
1372 | 1359 | ||
1373 | if (file_pos >= progress_next) { | 1360 | ui_progress__update(&prog, size); |
1374 | progress_next += file_size / 16; | ||
1375 | ui_progress__update(file_pos, file_size, | ||
1376 | "Processing events..."); | ||
1377 | } | ||
1378 | 1361 | ||
1379 | err = 0; | ||
1380 | if (session_done()) | 1362 | if (session_done()) |
1381 | goto out_err; | 1363 | goto out; |
1382 | 1364 | ||
1383 | if (file_pos < file_size) | 1365 | if (file_pos < file_size) |
1384 | goto more; | 1366 | goto more; |
1385 | 1367 | ||
1368 | out: | ||
1386 | /* do the final flush for ordered samples */ | 1369 | /* do the final flush for ordered samples */ |
1387 | session->ordered_samples.next_flush = ULLONG_MAX; | 1370 | session->ordered_samples.next_flush = ULLONG_MAX; |
1388 | err = flush_sample_queue(session, tool); | 1371 | err = flush_sample_queue(session, tool); |
@@ -1393,21 +1376,22 @@ out_err: | |||
1393 | return err; | 1376 | return err; |
1394 | } | 1377 | } |
1395 | 1378 | ||
1396 | int perf_session__process_events(struct perf_session *self, | 1379 | int perf_session__process_events(struct perf_session *session, |
1397 | struct perf_tool *tool) | 1380 | struct perf_tool *tool) |
1398 | { | 1381 | { |
1382 | u64 size = perf_data_file__size(session->file); | ||
1399 | int err; | 1383 | int err; |
1400 | 1384 | ||
1401 | if (perf_session__register_idle_thread(self) == NULL) | 1385 | if (perf_session__register_idle_thread(session) == NULL) |
1402 | return -ENOMEM; | 1386 | return -ENOMEM; |
1403 | 1387 | ||
1404 | if (!self->fd_pipe) | 1388 | if (!perf_data_file__is_pipe(session->file)) |
1405 | err = __perf_session__process_events(self, | 1389 | err = __perf_session__process_events(session, |
1406 | self->header.data_offset, | 1390 | session->header.data_offset, |
1407 | self->header.data_size, | 1391 | session->header.data_size, |
1408 | self->size, tool); | 1392 | size, tool); |
1409 | else | 1393 | else |
1410 | err = __perf_session__process_pipe_events(self, tool); | 1394 | err = __perf_session__process_pipe_events(session, tool); |
1411 | 1395 | ||
1412 | return err; | 1396 | return err; |
1413 | } | 1397 | } |
@@ -1456,15 +1440,15 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps, | |||
1456 | return 0; | 1440 | return 0; |
1457 | } | 1441 | } |
1458 | 1442 | ||
1459 | size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) | 1443 | size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp) |
1460 | { | 1444 | { |
1461 | return machines__fprintf_dsos(&self->machines, fp); | 1445 | return machines__fprintf_dsos(&session->machines, fp); |
1462 | } | 1446 | } |
1463 | 1447 | ||
1464 | size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, | 1448 | size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp, |
1465 | bool (skip)(struct dso *dso, int parm), int parm) | 1449 | bool (skip)(struct dso *dso, int parm), int parm) |
1466 | { | 1450 | { |
1467 | return machines__fprintf_dsos_buildid(&self->machines, fp, skip, parm); | 1451 | return machines__fprintf_dsos_buildid(&session->machines, fp, skip, parm); |
1468 | } | 1452 | } |
1469 | 1453 | ||
1470 | size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) | 1454 | size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) |
@@ -1525,7 +1509,8 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, | |||
1525 | if (symbol_conf.use_callchain && sample->callchain) { | 1509 | if (symbol_conf.use_callchain && sample->callchain) { |
1526 | 1510 | ||
1527 | if (machine__resolve_callchain(machine, evsel, al.thread, | 1511 | if (machine__resolve_callchain(machine, evsel, al.thread, |
1528 | sample, NULL, NULL) != 0) { | 1512 | sample, NULL, NULL, |
1513 | PERF_MAX_STACK_DEPTH) != 0) { | ||
1529 | if (verbose) | 1514 | if (verbose) |
1530 | error("Failed to resolve callchain. Skipping\n"); | 1515 | error("Failed to resolve callchain. Skipping\n"); |
1531 | return; | 1516 | return; |
@@ -1629,13 +1614,14 @@ int perf_session__cpu_bitmap(struct perf_session *session, | |||
1629 | void perf_session__fprintf_info(struct perf_session *session, FILE *fp, | 1614 | void perf_session__fprintf_info(struct perf_session *session, FILE *fp, |
1630 | bool full) | 1615 | bool full) |
1631 | { | 1616 | { |
1617 | int fd = perf_data_file__fd(session->file); | ||
1632 | struct stat st; | 1618 | struct stat st; |
1633 | int ret; | 1619 | int ret; |
1634 | 1620 | ||
1635 | if (session == NULL || fp == NULL) | 1621 | if (session == NULL || fp == NULL) |
1636 | return; | 1622 | return; |
1637 | 1623 | ||
1638 | ret = fstat(session->fd, &st); | 1624 | ret = fstat(fd, &st); |
1639 | if (ret == -1) | 1625 | if (ret == -1) |
1640 | return; | 1626 | return; |
1641 | 1627 | ||
@@ -1664,9 +1650,9 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session, | |||
1664 | continue; | 1650 | continue; |
1665 | 1651 | ||
1666 | err = -EEXIST; | 1652 | err = -EEXIST; |
1667 | if (evsel->handler.func != NULL) | 1653 | if (evsel->handler != NULL) |
1668 | goto out; | 1654 | goto out; |
1669 | evsel->handler.func = assocs[i].handler; | 1655 | evsel->handler = assocs[i].handler; |
1670 | } | 1656 | } |
1671 | 1657 | ||
1672 | err = 0; | 1658 | err = 0; |