aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-12-11 18:24:02 -0500
committerIngo Molnar <mingo@elte.hu>2009-12-12 01:42:12 -0500
commit94c744b6c0c6c5802a85ebfebbec429ac5851f2b (patch)
treee34dcaca54f1d7752ab1e7974bb73f94ff3cf94c /tools/perf/util
parentea08d8cbd162fe3756e3e2298efbe0b8b12f92d1 (diff)
perf tools: Introduce perf_session class
That does all the initialization boilerplate, opening the file, reading the header, checking if it is valid, etc. And that will as well have the threads list, kmap (now) global variable, etc, so that we can handle two (or more) perf.data files describing sessions to compare. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1260573842-19720-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/data_map.c71
-rw-r--r--tools/perf/util/data_map.h9
-rw-r--r--tools/perf/util/header.c28
-rw-r--r--tools/perf/util/header.h4
-rw-r--r--tools/perf/util/session.c80
-rw-r--r--tools/perf/util/session.h16
6 files changed, 118 insertions, 90 deletions
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c
index 59b65d0bd7c1..6d46dda53a29 100644
--- a/tools/perf/util/data_map.c
+++ b/tools/perf/util/data_map.c
@@ -129,23 +129,16 @@ out:
129 return err; 129 return err;
130} 130}
131 131
132int mmap_dispatch_perf_file(struct perf_header **pheader, 132int perf_session__process_events(struct perf_session *self,
133 const char *input_name, 133 int full_paths, int *cwdlen, char **cwd)
134 int force,
135 int full_paths,
136 int *cwdlen,
137 char **cwd)
138{ 134{
139 int err; 135 int err;
140 struct perf_header *header;
141 unsigned long head, shift; 136 unsigned long head, shift;
142 unsigned long offset = 0; 137 unsigned long offset = 0;
143 struct stat input_stat;
144 size_t page_size; 138 size_t page_size;
145 u64 sample_type; 139 u64 sample_type;
146 event_t *event; 140 event_t *event;
147 uint32_t size; 141 uint32_t size;
148 int input;
149 char *buf; 142 char *buf;
150 143
151 if (curr_handler == NULL) { 144 if (curr_handler == NULL) {
@@ -155,56 +148,19 @@ int mmap_dispatch_perf_file(struct perf_header **pheader,
155 148
156 page_size = getpagesize(); 149 page_size = getpagesize();
157 150
158 input = open(input_name, O_RDONLY); 151 head = self->header.data_offset;
159 if (input < 0) { 152 sample_type = perf_header__sample_type(&self->header);
160 pr_err("Failed to open file: %s", input_name);
161 if (!strcmp(input_name, "perf.data"))
162 pr_err(" (try 'perf record' first)");
163 pr_err("\n");
164 return -errno;
165 }
166
167 if (fstat(input, &input_stat) < 0) {
168 pr_err("failed to stat file");
169 err = -errno;
170 goto out_close;
171 }
172
173 err = -EACCES;
174 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
175 pr_err("file: %s not owned by current user or root\n",
176 input_name);
177 goto out_close;
178 }
179
180 if (input_stat.st_size == 0) {
181 pr_info("zero-sized file, nothing to do!\n");
182 goto done;
183 }
184
185 err = -ENOMEM;
186 header = perf_header__new();
187 if (header == NULL)
188 goto out_close;
189
190 err = perf_header__read(header, input);
191 if (err < 0)
192 goto out_delete;
193 *pheader = header;
194 head = header->data_offset;
195
196 sample_type = perf_header__sample_type(header);
197 153
198 err = -EINVAL; 154 err = -EINVAL;
199 if (curr_handler->sample_type_check && 155 if (curr_handler->sample_type_check &&
200 curr_handler->sample_type_check(sample_type) < 0) 156 curr_handler->sample_type_check(sample_type) < 0)
201 goto out_delete; 157 goto out_err;
202 158
203 if (!full_paths) { 159 if (!full_paths) {
204 if (getcwd(__cwd, sizeof(__cwd)) == NULL) { 160 if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
205 pr_err("failed to get the current directory\n"); 161 pr_err("failed to get the current directory\n");
206 err = -errno; 162 err = -errno;
207 goto out_delete; 163 goto out_err;
208 } 164 }
209 *cwd = __cwd; 165 *cwd = __cwd;
210 *cwdlen = strlen(*cwd); 166 *cwdlen = strlen(*cwd);
@@ -219,11 +175,11 @@ int mmap_dispatch_perf_file(struct perf_header **pheader,
219 175
220remap: 176remap:
221 buf = mmap(NULL, page_size * mmap_window, PROT_READ, 177 buf = mmap(NULL, page_size * mmap_window, PROT_READ,
222 MAP_SHARED, input, offset); 178 MAP_SHARED, self->fd, offset);
223 if (buf == MAP_FAILED) { 179 if (buf == MAP_FAILED) {
224 pr_err("failed to mmap file\n"); 180 pr_err("failed to mmap file\n");
225 err = -errno; 181 err = -errno;
226 goto out_delete; 182 goto out_err;
227 } 183 }
228 184
229more: 185more:
@@ -273,19 +229,14 @@ more:
273 229
274 head += size; 230 head += size;
275 231
276 if (offset + head >= header->data_offset + header->data_size) 232 if (offset + head >= self->header.data_offset + self->header.data_size)
277 goto done; 233 goto done;
278 234
279 if (offset + head < (unsigned long)input_stat.st_size) 235 if (offset + head < self->size)
280 goto more; 236 goto more;
281 237
282done: 238done:
283 err = 0; 239 err = 0;
284out_close: 240out_err:
285 close(input);
286
287 return err; 241 return err;
288out_delete:
289 perf_header__delete(header);
290 goto out_close;
291} 242}
diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h
index 258a87bcc4fb..98c5b823388c 100644
--- a/tools/perf/util/data_map.h
+++ b/tools/perf/util/data_map.h
@@ -3,6 +3,7 @@
3 3
4#include "event.h" 4#include "event.h"
5#include "header.h" 5#include "header.h"
6#include "session.h"
6 7
7typedef int (*event_type_handler_t)(event_t *); 8typedef int (*event_type_handler_t)(event_t *);
8 9
@@ -21,12 +22,8 @@ struct perf_file_handler {
21}; 22};
22 23
23void register_perf_file_handler(struct perf_file_handler *handler); 24void register_perf_file_handler(struct perf_file_handler *handler);
24int mmap_dispatch_perf_file(struct perf_header **pheader, 25int perf_session__process_events(struct perf_session *self,
25 const char *input_name, 26 int full_paths, int *cwdlen, char **cwd);
26 int force,
27 int full_paths,
28 int *cwdlen,
29 char **cwd);
30int perf_header__read_build_ids(int input, u64 offset, u64 file_size); 27int perf_header__read_build_ids(int input, u64 offset, u64 file_size);
31 28
32#endif 29#endif
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 59a9c0b3033e..f2e8d8715111 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -58,35 +58,19 @@ int perf_header_attr__add_id(struct perf_header_attr *self, u64 id)
58 return 0; 58 return 0;
59} 59}
60 60
61/* 61int perf_header__init(struct perf_header *self)
62 * Create new perf.data header:
63 */
64struct perf_header *perf_header__new(void)
65{ 62{
66 struct perf_header *self = zalloc(sizeof(*self)); 63 self->size = 1;
67 64 self->attr = malloc(sizeof(void *));
68 if (self != NULL) { 65 return self->attr == NULL ? -ENOMEM : 0;
69 self->size = 1;
70 self->attr = malloc(sizeof(void *));
71
72 if (self->attr == NULL) {
73 free(self);
74 self = NULL;
75 }
76 }
77
78 return self;
79} 66}
80 67
81void perf_header__delete(struct perf_header *self) 68void perf_header__exit(struct perf_header *self)
82{ 69{
83 int i; 70 int i;
84
85 for (i = 0; i < self->attrs; ++i) 71 for (i = 0; i < self->attrs; ++i)
86 perf_header_attr__delete(self->attr[i]); 72 perf_header_attr__delete(self->attr[i]);
87
88 free(self->attr); 73 free(self->attr);
89 free(self);
90} 74}
91 75
92int perf_header__add_attr(struct perf_header *self, 76int perf_header__add_attr(struct perf_header *self,
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index d1dbe2b79c42..d118d05d3abe 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -55,8 +55,8 @@ struct perf_header {
55 DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); 55 DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
56}; 56};
57 57
58struct perf_header *perf_header__new(void); 58int perf_header__init(struct perf_header *self);
59void perf_header__delete(struct perf_header *self); 59void perf_header__exit(struct perf_header *self);
60 60
61int perf_header__read(struct perf_header *self, int fd); 61int perf_header__read(struct perf_header *self, int fd);
62int perf_header__write(struct perf_header *self, int fd, bool at_exit); 62int perf_header__write(struct perf_header *self, int fd, bool at_exit);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
new file mode 100644
index 000000000000..707ce1cb1621
--- /dev/null
+++ b/tools/perf/util/session.c
@@ -0,0 +1,80 @@
1#include <linux/kernel.h>
2
3#include <unistd.h>
4#include <sys/types.h>
5
6#include "session.h"
7#include "util.h"
8
9static int perf_session__open(struct perf_session *self, bool force)
10{
11 struct stat input_stat;
12
13 self->fd = open(self->filename, O_RDONLY);
14 if (self->fd < 0) {
15 pr_err("failed to open file: %s", self->filename);
16 if (!strcmp(self->filename, "perf.data"))
17 pr_err(" (try 'perf record' first)");
18 pr_err("\n");
19 return -errno;
20 }
21
22 if (fstat(self->fd, &input_stat) < 0)
23 goto out_close;
24
25 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
26 pr_err("file %s not owned by current user or root\n",
27 self->filename);
28 goto out_close;
29 }
30
31 if (!input_stat.st_size) {
32 pr_info("zero-sized file (%s), nothing to do!\n",
33 self->filename);
34 goto out_close;
35 }
36
37 if (perf_header__read(&self->header, self->fd) < 0) {
38 pr_err("incompatible file format");
39 goto out_close;
40 }
41
42 self->size = input_stat.st_size;
43 return 0;
44
45out_close:
46 close(self->fd);
47 self->fd = -1;
48 return -1;
49}
50
51struct perf_session *perf_session__new(const char *filename, int mode, bool force)
52{
53 size_t len = strlen(filename) + 1;
54 struct perf_session *self = zalloc(sizeof(*self) + len);
55
56 if (self == NULL)
57 goto out;
58
59 if (perf_header__init(&self->header) < 0)
60 goto out_delete;
61
62 memcpy(self->filename, filename, len);
63
64 if (mode == O_RDONLY && perf_session__open(self, force) < 0) {
65 perf_session__delete(self);
66 self = NULL;
67 }
68out:
69 return self;
70out_delete:
71 free(self);
72 return NULL;
73}
74
75void perf_session__delete(struct perf_session *self)
76{
77 perf_header__exit(&self->header);
78 close(self->fd);
79 free(self);
80}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
new file mode 100644
index 000000000000..f3699c8c8ed4
--- /dev/null
+++ b/tools/perf/util/session.h
@@ -0,0 +1,16 @@
1#ifndef __PERF_SESSION_H
2#define __PERF_SESSION_H
3
4#include "header.h"
5
6struct perf_session {
7 struct perf_header header;
8 unsigned long size;
9 int fd;
10 char filename[0];
11};
12
13struct perf_session *perf_session__new(const char *filename, int mode, bool force);
14void perf_session__delete(struct perf_session *self);
15
16#endif /* __PERF_SESSION_H */