aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-record.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r--tools/perf/builtin-record.c588
1 files changed, 275 insertions, 313 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index ff77b805de71..8e2c85798185 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -18,41 +18,43 @@
18 18
19#include "util/header.h" 19#include "util/header.h"
20#include "util/event.h" 20#include "util/event.h"
21#include "util/evlist.h"
22#include "util/evsel.h"
21#include "util/debug.h" 23#include "util/debug.h"
22#include "util/session.h" 24#include "util/session.h"
23#include "util/symbol.h" 25#include "util/symbol.h"
24#include "util/cpumap.h" 26#include "util/cpumap.h"
27#include "util/thread_map.h"
25 28
26#include <unistd.h> 29#include <unistd.h>
27#include <sched.h> 30#include <sched.h>
28#include <sys/mman.h> 31#include <sys/mman.h>
29 32
33#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
34
30enum write_mode_t { 35enum write_mode_t {
31 WRITE_FORCE, 36 WRITE_FORCE,
32 WRITE_APPEND 37 WRITE_APPEND
33}; 38};
34 39
35static int *fd[MAX_NR_CPUS][MAX_COUNTERS];
36
37static u64 user_interval = ULLONG_MAX; 40static u64 user_interval = ULLONG_MAX;
38static u64 default_interval = 0; 41static u64 default_interval = 0;
39 42
40static int nr_cpus = 0;
41static unsigned int page_size; 43static unsigned int page_size;
42static unsigned int mmap_pages = 128; 44static unsigned int mmap_pages = UINT_MAX;
43static unsigned int user_freq = UINT_MAX; 45static unsigned int user_freq = UINT_MAX;
44static int freq = 1000; 46static int freq = 1000;
45static int output; 47static int output;
46static int pipe_output = 0; 48static int pipe_output = 0;
47static const char *output_name = "perf.data"; 49static const char *output_name = NULL;
48static int group = 0; 50static int group = 0;
49static int realtime_prio = 0; 51static int realtime_prio = 0;
52static bool nodelay = false;
50static bool raw_samples = false; 53static bool raw_samples = false;
54static bool sample_id_all_avail = true;
51static bool system_wide = false; 55static bool system_wide = false;
52static pid_t target_pid = -1; 56static pid_t target_pid = -1;
53static pid_t target_tid = -1; 57static pid_t target_tid = -1;
54static pid_t *all_tids = NULL;
55static int thread_num = 0;
56static pid_t child_pid = -1; 58static pid_t child_pid = -1;
57static bool no_inherit = false; 59static bool no_inherit = false;
58static enum write_mode_t write_mode = WRITE_FORCE; 60static enum write_mode_t write_mode = WRITE_FORCE;
@@ -60,53 +62,20 @@ static bool call_graph = false;
60static bool inherit_stat = false; 62static bool inherit_stat = false;
61static bool no_samples = false; 63static bool no_samples = false;
62static bool sample_address = false; 64static bool sample_address = false;
65static bool sample_time = false;
63static bool no_buildid = false; 66static bool no_buildid = false;
67static bool no_buildid_cache = false;
68static struct perf_evlist *evsel_list;
64 69
65static long samples = 0; 70static long samples = 0;
66static u64 bytes_written = 0; 71static u64 bytes_written = 0;
67 72
68static struct pollfd *event_array;
69
70static int nr_poll = 0;
71static int nr_cpu = 0;
72
73static int file_new = 1; 73static int file_new = 1;
74static off_t post_processing_offset; 74static off_t post_processing_offset;
75 75
76static struct perf_session *session; 76static struct perf_session *session;
77static const char *cpu_list; 77static const char *cpu_list;
78 78
79struct mmap_data {
80 int counter;
81 void *base;
82 unsigned int mask;
83 unsigned int prev;
84};
85
86static struct mmap_data mmap_array[MAX_NR_CPUS];
87
88static unsigned long mmap_read_head(struct mmap_data *md)
89{
90 struct perf_event_mmap_page *pc = md->base;
91 long head;
92
93 head = pc->data_head;
94 rmb();
95
96 return head;
97}
98
99static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
100{
101 struct perf_event_mmap_page *pc = md->base;
102
103 /*
104 * ensure all reads are done before we write the tail out.
105 */
106 /* mb(); */
107 pc->data_tail = tail;
108}
109
110static void advance_output(size_t size) 79static void advance_output(size_t size)
111{ 80{
112 bytes_written += size; 81 bytes_written += size;
@@ -127,41 +96,26 @@ static void write_output(void *buf, size_t size)
127 } 96 }
128} 97}
129 98
130static int process_synthesized_event(event_t *event, 99static int process_synthesized_event(union perf_event *event,
100 struct perf_sample *sample __used,
131 struct perf_session *self __used) 101 struct perf_session *self __used)
132{ 102{
133 write_output(event, event->header.size); 103 write_output(event, event->header.size);
134 return 0; 104 return 0;
135} 105}
136 106
137static void mmap_read(struct mmap_data *md) 107static void mmap_read(struct perf_mmap *md)
138{ 108{
139 unsigned int head = mmap_read_head(md); 109 unsigned int head = perf_mmap__read_head(md);
140 unsigned int old = md->prev; 110 unsigned int old = md->prev;
141 unsigned char *data = md->base + page_size; 111 unsigned char *data = md->base + page_size;
142 unsigned long size; 112 unsigned long size;
143 void *buf; 113 void *buf;
144 int diff;
145 114
146 /* 115 if (old == head)
147 * If we're further behind than half the buffer, there's a chance 116 return;
148 * the writer will bite our tail and mess up the samples under us.
149 *
150 * If we somehow ended up ahead of the head, we got messed up.
151 *
152 * In either case, truncate and restart at head.
153 */
154 diff = head - old;
155 if (diff < 0) {
156 fprintf(stderr, "WARNING: failed to keep up with mmap data\n");
157 /*
158 * head points to a known good entry, start there.
159 */
160 old = head;
161 }
162 117
163 if (old != head) 118 samples++;
164 samples++;
165 119
166 size = head - old; 120 size = head - old;
167 121
@@ -180,7 +134,7 @@ static void mmap_read(struct mmap_data *md)
180 write_output(buf, size); 134 write_output(buf, size);
181 135
182 md->prev = old; 136 md->prev = old;
183 mmap_write_tail(md, old); 137 perf_mmap__write_tail(md, old);
184} 138}
185 139
186static volatile int done = 0; 140static volatile int done = 0;
@@ -197,55 +151,26 @@ static void sig_atexit(void)
197 if (child_pid > 0) 151 if (child_pid > 0)
198 kill(child_pid, SIGTERM); 152 kill(child_pid, SIGTERM);
199 153
200 if (signr == -1) 154 if (signr == -1 || signr == SIGUSR1)
201 return; 155 return;
202 156
203 signal(signr, SIG_DFL); 157 signal(signr, SIG_DFL);
204 kill(getpid(), signr); 158 kill(getpid(), signr);
205} 159}
206 160
207static int group_fd; 161static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
208
209static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int nr)
210{
211 struct perf_header_attr *h_attr;
212
213 if (nr < session->header.attrs) {
214 h_attr = session->header.attr[nr];
215 } else {
216 h_attr = perf_header_attr__new(a);
217 if (h_attr != NULL)
218 if (perf_header__add_attr(&session->header, h_attr) < 0) {
219 perf_header_attr__delete(h_attr);
220 h_attr = NULL;
221 }
222 }
223
224 return h_attr;
225}
226
227static void create_counter(int counter, int cpu)
228{ 162{
229 char *filter = filters[counter]; 163 struct perf_event_attr *attr = &evsel->attr;
230 struct perf_event_attr *attr = attrs + counter; 164 int track = !evsel->idx; /* only the first counter needs these */
231 struct perf_header_attr *h_attr;
232 int track = !counter; /* only the first counter needs these */
233 int thread_index;
234 int ret;
235 struct {
236 u64 count;
237 u64 time_enabled;
238 u64 time_running;
239 u64 id;
240 } read_data;
241 165
166 attr->inherit = !no_inherit;
242 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 167 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
243 PERF_FORMAT_TOTAL_TIME_RUNNING | 168 PERF_FORMAT_TOTAL_TIME_RUNNING |
244 PERF_FORMAT_ID; 169 PERF_FORMAT_ID;
245 170
246 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; 171 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
247 172
248 if (nr_counters > 1) 173 if (evlist->nr_entries > 1)
249 attr->sample_type |= PERF_SAMPLE_ID; 174 attr->sample_type |= PERF_SAMPLE_ID;
250 175
251 /* 176 /*
@@ -280,35 +205,94 @@ static void create_counter(int counter, int cpu)
280 if (system_wide) 205 if (system_wide)
281 attr->sample_type |= PERF_SAMPLE_CPU; 206 attr->sample_type |= PERF_SAMPLE_CPU;
282 207
208 if (sample_id_all_avail &&
209 (sample_time || system_wide || !no_inherit || cpu_list))
210 attr->sample_type |= PERF_SAMPLE_TIME;
211
283 if (raw_samples) { 212 if (raw_samples) {
284 attr->sample_type |= PERF_SAMPLE_TIME; 213 attr->sample_type |= PERF_SAMPLE_TIME;
285 attr->sample_type |= PERF_SAMPLE_RAW; 214 attr->sample_type |= PERF_SAMPLE_RAW;
286 attr->sample_type |= PERF_SAMPLE_CPU; 215 attr->sample_type |= PERF_SAMPLE_CPU;
287 } 216 }
288 217
218 if (nodelay) {
219 attr->watermark = 0;
220 attr->wakeup_events = 1;
221 }
222
289 attr->mmap = track; 223 attr->mmap = track;
290 attr->comm = track; 224 attr->comm = track;
291 attr->inherit = !no_inherit; 225
292 if (target_pid == -1 && target_tid == -1 && !system_wide) { 226 if (target_pid == -1 && target_tid == -1 && !system_wide) {
293 attr->disabled = 1; 227 attr->disabled = 1;
294 attr->enable_on_exec = 1; 228 attr->enable_on_exec = 1;
295 } 229 }
230}
296 231
297 for (thread_index = 0; thread_index < thread_num; thread_index++) { 232static bool perf_evlist__equal(struct perf_evlist *evlist,
298try_again: 233 struct perf_evlist *other)
299 fd[nr_cpu][counter][thread_index] = sys_perf_event_open(attr, 234{
300 all_tids[thread_index], cpu, group_fd, 0); 235 struct perf_evsel *pos, *pair;
236
237 if (evlist->nr_entries != other->nr_entries)
238 return false;
239
240 pair = list_entry(other->entries.next, struct perf_evsel, node);
301 241
302 if (fd[nr_cpu][counter][thread_index] < 0) { 242 list_for_each_entry(pos, &evlist->entries, node) {
243 if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
244 return false;
245 pair = list_entry(pair->node.next, struct perf_evsel, node);
246 }
247
248 return true;
249}
250
251static void open_counters(struct perf_evlist *evlist)
252{
253 struct perf_evsel *pos;
254
255 if (evlist->cpus->map[0] < 0)
256 no_inherit = true;
257
258 list_for_each_entry(pos, &evlist->entries, node) {
259 struct perf_event_attr *attr = &pos->attr;
260 /*
261 * Check if parse_single_tracepoint_event has already asked for
262 * PERF_SAMPLE_TIME.
263 *
264 * XXX this is kludgy but short term fix for problems introduced by
265 * eac23d1c that broke 'perf script' by having different sample_types
266 * when using multiple tracepoint events when we use a perf binary
267 * that tries to use sample_id_all on an older kernel.
268 *
269 * We need to move counter creation to perf_session, support
270 * different sample_types, etc.
271 */
272 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
273
274 config_attr(pos, evlist);
275retry_sample_id:
276 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
277try_again:
278 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
303 int err = errno; 279 int err = errno;
304 280
305 if (err == EPERM || err == EACCES) 281 if (err == EPERM || err == EACCES) {
306 die("Permission error - are you root?\n" 282 ui__warning_paranoid();
307 "\t Consider tweaking" 283 exit(EXIT_FAILURE);
308 " /proc/sys/kernel/perf_event_paranoid.\n"); 284 } else if (err == ENODEV && cpu_list) {
309 else if (err == ENODEV && cpu_list) {
310 die("No such device - did you specify" 285 die("No such device - did you specify"
311 " an out-of-range profile CPU?\n"); 286 " an out-of-range profile CPU?\n");
287 } else if (err == EINVAL && sample_id_all_avail) {
288 /*
289 * Old kernel, no attr->sample_id_type_all field
290 */
291 sample_id_all_avail = false;
292 if (!sample_time && !raw_samples && !time_needed)
293 attr->sample_type &= ~PERF_SAMPLE_TIME;
294
295 goto retry_sample_id;
312 } 296 }
313 297
314 /* 298 /*
@@ -320,14 +304,22 @@ try_again:
320 && attr->config == PERF_COUNT_HW_CPU_CYCLES) { 304 && attr->config == PERF_COUNT_HW_CPU_CYCLES) {
321 305
322 if (verbose) 306 if (verbose)
323 warning(" ... trying to fall back to cpu-clock-ticks\n"); 307 ui__warning("The cycles event is not supported, "
308 "trying to fall back to cpu-clock-ticks\n");
324 attr->type = PERF_TYPE_SOFTWARE; 309 attr->type = PERF_TYPE_SOFTWARE;
325 attr->config = PERF_COUNT_SW_CPU_CLOCK; 310 attr->config = PERF_COUNT_SW_CPU_CLOCK;
326 goto try_again; 311 goto try_again;
327 } 312 }
313
314 if (err == ENOENT) {
315 ui__warning("The %s event is not supported.\n",
316 event_name(pos));
317 exit(EXIT_FAILURE);
318 }
319
328 printf("\n"); 320 printf("\n");
329 error("perfcounter syscall returned with %d (%s)\n", 321 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
330 fd[nr_cpu][counter][thread_index], strerror(err)); 322 err, strerror(err));
331 323
332#if defined(__i386__) || defined(__x86_64__) 324#if defined(__i386__) || defined(__x86_64__)
333 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) 325 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
@@ -338,85 +330,28 @@ try_again:
338#endif 330#endif
339 331
340 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 332 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
341 exit(-1);
342 } 333 }
334 }
343 335
344 h_attr = get_header_attr(attr, counter); 336 if (perf_evlist__set_filters(evlist)) {
345 if (h_attr == NULL) 337 error("failed to set filter with %d (%s)\n", errno,
346 die("nomem\n"); 338 strerror(errno));
347 339 exit(-1);
348 if (!file_new) { 340 }
349 if (memcmp(&h_attr->attr, attr, sizeof(*attr))) {
350 fprintf(stderr, "incompatible append\n");
351 exit(-1);
352 }
353 }
354 341
355 if (read(fd[nr_cpu][counter][thread_index], &read_data, sizeof(read_data)) == -1) { 342 if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
356 perror("Unable to read perf file descriptor\n"); 343 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
357 exit(-1);
358 }
359 344
360 if (perf_header_attr__add_id(h_attr, read_data.id) < 0) { 345 if (file_new)
361 pr_warning("Not enough memory to add id\n"); 346 session->evlist = evlist;
347 else {
348 if (!perf_evlist__equal(session->evlist, evlist)) {
349 fprintf(stderr, "incompatible append\n");
362 exit(-1); 350 exit(-1);
363 } 351 }
352 }
364 353
365 assert(fd[nr_cpu][counter][thread_index] >= 0); 354 perf_session__update_sample_type(session);
366 fcntl(fd[nr_cpu][counter][thread_index], F_SETFL, O_NONBLOCK);
367
368 /*
369 * First counter acts as the group leader:
370 */
371 if (group && group_fd == -1)
372 group_fd = fd[nr_cpu][counter][thread_index];
373
374 if (counter || thread_index) {
375 ret = ioctl(fd[nr_cpu][counter][thread_index],
376 PERF_EVENT_IOC_SET_OUTPUT,
377 fd[nr_cpu][0][0]);
378 if (ret) {
379 error("failed to set output: %d (%s)\n", errno,
380 strerror(errno));
381 exit(-1);
382 }
383 } else {
384 mmap_array[nr_cpu].counter = counter;
385 mmap_array[nr_cpu].prev = 0;
386 mmap_array[nr_cpu].mask = mmap_pages*page_size - 1;
387 mmap_array[nr_cpu].base = mmap(NULL, (mmap_pages+1)*page_size,
388 PROT_READ|PROT_WRITE, MAP_SHARED, fd[nr_cpu][counter][thread_index], 0);
389 if (mmap_array[nr_cpu].base == MAP_FAILED) {
390 error("failed to mmap with %d (%s)\n", errno, strerror(errno));
391 exit(-1);
392 }
393
394 event_array[nr_poll].fd = fd[nr_cpu][counter][thread_index];
395 event_array[nr_poll].events = POLLIN;
396 nr_poll++;
397 }
398
399 if (filter != NULL) {
400 ret = ioctl(fd[nr_cpu][counter][thread_index],
401 PERF_EVENT_IOC_SET_FILTER, filter);
402 if (ret) {
403 error("failed to set filter with %d (%s)\n", errno,
404 strerror(errno));
405 exit(-1);
406 }
407 }
408 }
409}
410
411static void open_counters(int cpu)
412{
413 int counter;
414
415 group_fd = -1;
416 for (counter = 0; counter < nr_counters; counter++)
417 create_counter(counter, cpu);
418
419 nr_cpu++;
420} 355}
421 356
422static int process_buildids(void) 357static int process_buildids(void)
@@ -437,14 +372,16 @@ static void atexit_header(void)
437 if (!pipe_output) { 372 if (!pipe_output) {
438 session->header.data_size += bytes_written; 373 session->header.data_size += bytes_written;
439 374
440 process_buildids(); 375 if (!no_buildid)
441 perf_header__write(&session->header, output, true); 376 process_buildids();
377 perf_session__write_header(session, evsel_list, output, true);
442 perf_session__delete(session); 378 perf_session__delete(session);
379 perf_evlist__delete(evsel_list);
443 symbol__exit(); 380 symbol__exit();
444 } 381 }
445} 382}
446 383
447static void event__synthesize_guest_os(struct machine *machine, void *data) 384static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
448{ 385{
449 int err; 386 int err;
450 struct perf_session *psession = data; 387 struct perf_session *psession = data;
@@ -460,8 +397,8 @@ static void event__synthesize_guest_os(struct machine *machine, void *data)
460 *method is used to avoid symbol missing when the first addr is 397 *method is used to avoid symbol missing when the first addr is
461 *in module instead of in guest kernel. 398 *in module instead of in guest kernel.
462 */ 399 */
463 err = event__synthesize_modules(process_synthesized_event, 400 err = perf_event__synthesize_modules(process_synthesized_event,
464 psession, machine); 401 psession, machine);
465 if (err < 0) 402 if (err < 0)
466 pr_err("Couldn't record guest kernel [%d]'s reference" 403 pr_err("Couldn't record guest kernel [%d]'s reference"
467 " relocation symbol.\n", machine->pid); 404 " relocation symbol.\n", machine->pid);
@@ -470,11 +407,12 @@ static void event__synthesize_guest_os(struct machine *machine, void *data)
470 * We use _stext for guest kernel because guest kernel's /proc/kallsyms 407 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
471 * have no _text sometimes. 408 * have no _text sometimes.
472 */ 409 */
473 err = event__synthesize_kernel_mmap(process_synthesized_event, 410 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
474 psession, machine, "_text"); 411 psession, machine, "_text");
475 if (err < 0) 412 if (err < 0)
476 err = event__synthesize_kernel_mmap(process_synthesized_event, 413 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
477 psession, machine, "_stext"); 414 psession, machine,
415 "_stext");
478 if (err < 0) 416 if (err < 0)
479 pr_err("Couldn't record guest kernel [%d]'s reference" 417 pr_err("Couldn't record guest kernel [%d]'s reference"
480 " relocation symbol.\n", machine->pid); 418 " relocation symbol.\n", machine->pid);
@@ -489,9 +427,9 @@ static void mmap_read_all(void)
489{ 427{
490 int i; 428 int i;
491 429
492 for (i = 0; i < nr_cpu; i++) { 430 for (i = 0; i < evsel_list->nr_mmaps; i++) {
493 if (mmap_array[i].base) 431 if (evsel_list->mmap[i].base)
494 mmap_read(&mmap_array[i]); 432 mmap_read(&evsel_list->mmap[i]);
495 } 433 }
496 434
497 if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO)) 435 if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
@@ -500,7 +438,7 @@ static void mmap_read_all(void)
500 438
501static int __cmd_record(int argc, const char **argv) 439static int __cmd_record(int argc, const char **argv)
502{ 440{
503 int i, counter; 441 int i;
504 struct stat st; 442 struct stat st;
505 int flags; 443 int flags;
506 int err; 444 int err;
@@ -515,24 +453,33 @@ static int __cmd_record(int argc, const char **argv)
515 atexit(sig_atexit); 453 atexit(sig_atexit);
516 signal(SIGCHLD, sig_handler); 454 signal(SIGCHLD, sig_handler);
517 signal(SIGINT, sig_handler); 455 signal(SIGINT, sig_handler);
456 signal(SIGUSR1, sig_handler);
518 457
519 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { 458 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
520 perror("failed to create pipes"); 459 perror("failed to create pipes");
521 exit(-1); 460 exit(-1);
522 } 461 }
523 462
524 if (!strcmp(output_name, "-")) 463 if (!output_name) {
525 pipe_output = 1; 464 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
526 else if (!stat(output_name, &st) && st.st_size) { 465 pipe_output = 1;
527 if (write_mode == WRITE_FORCE) { 466 else
528 char oldname[PATH_MAX]; 467 output_name = "perf.data";
529 snprintf(oldname, sizeof(oldname), "%s.old", 468 }
530 output_name); 469 if (output_name) {
531 unlink(oldname); 470 if (!strcmp(output_name, "-"))
532 rename(output_name, oldname); 471 pipe_output = 1;
472 else if (!stat(output_name, &st) && st.st_size) {
473 if (write_mode == WRITE_FORCE) {
474 char oldname[PATH_MAX];
475 snprintf(oldname, sizeof(oldname), "%s.old",
476 output_name);
477 unlink(oldname);
478 rename(output_name, oldname);
479 }
480 } else if (write_mode == WRITE_APPEND) {
481 write_mode = WRITE_FORCE;
533 } 482 }
534 } else if (write_mode == WRITE_APPEND) {
535 write_mode = WRITE_FORCE;
536 } 483 }
537 484
538 flags = O_CREAT|O_RDWR; 485 flags = O_CREAT|O_RDWR;
@@ -551,25 +498,27 @@ static int __cmd_record(int argc, const char **argv)
551 } 498 }
552 499
553 session = perf_session__new(output_name, O_WRONLY, 500 session = perf_session__new(output_name, O_WRONLY,
554 write_mode == WRITE_FORCE, false); 501 write_mode == WRITE_FORCE, false, NULL);
555 if (session == NULL) { 502 if (session == NULL) {
556 pr_err("Not enough memory for reading perf file header\n"); 503 pr_err("Not enough memory for reading perf file header\n");
557 return -1; 504 return -1;
558 } 505 }
559 506
507 if (!no_buildid)
508 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
509
560 if (!file_new) { 510 if (!file_new) {
561 err = perf_header__read(session, output); 511 err = perf_session__read_header(session, output);
562 if (err < 0) 512 if (err < 0)
563 goto out_delete_session; 513 goto out_delete_session;
564 } 514 }
565 515
566 if (have_tracepoints(attrs, nr_counters)) 516 if (have_tracepoints(&evsel_list->entries))
567 perf_header__set_feat(&session->header, HEADER_TRACE_INFO); 517 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
568 518
569 /* 519 /* 512 kiB: default amount of unprivileged mlocked memory */
570 * perf_session__delete(session) will be called at atexit_header() 520 if (mmap_pages == UINT_MAX)
571 */ 521 mmap_pages = (512 * 1024) / page_size;
572 atexit(atexit_header);
573 522
574 if (forks) { 523 if (forks) {
575 child_pid = fork(); 524 child_pid = fork();
@@ -606,11 +555,12 @@ static int __cmd_record(int argc, const char **argv)
606 execvp(argv[0], (char **)argv); 555 execvp(argv[0], (char **)argv);
607 556
608 perror(argv[0]); 557 perror(argv[0]);
558 kill(getppid(), SIGUSR1);
609 exit(-1); 559 exit(-1);
610 } 560 }
611 561
612 if (!system_wide && target_tid == -1 && target_pid == -1) 562 if (!system_wide && target_tid == -1 && target_pid == -1)
613 all_tids[0] = child_pid; 563 evsel_list->threads->map[0] = child_pid;
614 564
615 close(child_ready_pipe[1]); 565 close(child_ready_pipe[1]);
616 close(go_pipe[0]); 566 close(go_pipe[0]);
@@ -624,25 +574,20 @@ static int __cmd_record(int argc, const char **argv)
624 close(child_ready_pipe[0]); 574 close(child_ready_pipe[0]);
625 } 575 }
626 576
627 nr_cpus = read_cpu_map(cpu_list); 577 open_counters(evsel_list);
628 if (nr_cpus < 1) {
629 perror("failed to collect number of CPUs\n");
630 return -1;
631 }
632 578
633 if (!system_wide && no_inherit && !cpu_list) { 579 /*
634 open_counters(-1); 580 * perf_session__delete(session) will be called at atexit_header()
635 } else { 581 */
636 for (i = 0; i < nr_cpus; i++) 582 atexit(atexit_header);
637 open_counters(cpumap[i]);
638 }
639 583
640 if (pipe_output) { 584 if (pipe_output) {
641 err = perf_header__write_pipe(output); 585 err = perf_header__write_pipe(output);
642 if (err < 0) 586 if (err < 0)
643 return err; 587 return err;
644 } else if (file_new) { 588 } else if (file_new) {
645 err = perf_header__write(&session->header, output, false); 589 err = perf_session__write_header(session, evsel_list,
590 output, false);
646 if (err < 0) 591 if (err < 0)
647 return err; 592 return err;
648 } 593 }
@@ -650,22 +595,21 @@ static int __cmd_record(int argc, const char **argv)
650 post_processing_offset = lseek(output, 0, SEEK_CUR); 595 post_processing_offset = lseek(output, 0, SEEK_CUR);
651 596
652 if (pipe_output) { 597 if (pipe_output) {
653 err = event__synthesize_attrs(&session->header, 598 err = perf_session__synthesize_attrs(session,
654 process_synthesized_event, 599 process_synthesized_event);
655 session);
656 if (err < 0) { 600 if (err < 0) {
657 pr_err("Couldn't synthesize attrs.\n"); 601 pr_err("Couldn't synthesize attrs.\n");
658 return err; 602 return err;
659 } 603 }
660 604
661 err = event__synthesize_event_types(process_synthesized_event, 605 err = perf_event__synthesize_event_types(process_synthesized_event,
662 session); 606 session);
663 if (err < 0) { 607 if (err < 0) {
664 pr_err("Couldn't synthesize event_types.\n"); 608 pr_err("Couldn't synthesize event_types.\n");
665 return err; 609 return err;
666 } 610 }
667 611
668 if (have_tracepoints(attrs, nr_counters)) { 612 if (have_tracepoints(&evsel_list->entries)) {
669 /* 613 /*
670 * FIXME err <= 0 here actually means that 614 * FIXME err <= 0 here actually means that
671 * there were no tracepoints so its not really 615 * there were no tracepoints so its not really
@@ -674,10 +618,9 @@ static int __cmd_record(int argc, const char **argv)
674 * return this more properly and also 618 * return this more properly and also
675 * propagate errors that now are calling die() 619 * propagate errors that now are calling die()
676 */ 620 */
677 err = event__synthesize_tracing_data(output, attrs, 621 err = perf_event__synthesize_tracing_data(output, evsel_list,
678 nr_counters, 622 process_synthesized_event,
679 process_synthesized_event, 623 session);
680 session);
681 if (err <= 0) { 624 if (err <= 0) {
682 pr_err("Couldn't record tracing data.\n"); 625 pr_err("Couldn't record tracing data.\n");
683 return err; 626 return err;
@@ -692,30 +635,34 @@ static int __cmd_record(int argc, const char **argv)
692 return -1; 635 return -1;
693 } 636 }
694 637
695 err = event__synthesize_kernel_mmap(process_synthesized_event, 638 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
696 session, machine, "_text"); 639 session, machine, "_text");
697 if (err < 0) 640 if (err < 0)
698 err = event__synthesize_kernel_mmap(process_synthesized_event, 641 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
699 session, machine, "_stext"); 642 session, machine, "_stext");
700 if (err < 0) { 643 if (err < 0)
701 pr_err("Couldn't record kernel reference relocation symbol.\n"); 644 pr_err("Couldn't record kernel reference relocation symbol\n"
702 return err; 645 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
703 } 646 "Check /proc/kallsyms permission or run as root.\n");
647
648 err = perf_event__synthesize_modules(process_synthesized_event,
649 session, machine);
650 if (err < 0)
651 pr_err("Couldn't record kernel module information.\n"
652 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
653 "Check /proc/modules permission or run as root.\n");
704 654
705 err = event__synthesize_modules(process_synthesized_event,
706 session, machine);
707 if (err < 0) {
708 pr_err("Couldn't record kernel reference relocation symbol.\n");
709 return err;
710 }
711 if (perf_guest) 655 if (perf_guest)
712 perf_session__process_machines(session, event__synthesize_guest_os); 656 perf_session__process_machines(session,
657 perf_event__synthesize_guest_os);
713 658
714 if (!system_wide) 659 if (!system_wide)
715 event__synthesize_thread(target_tid, process_synthesized_event, 660 perf_event__synthesize_thread_map(evsel_list->threads,
716 session); 661 process_synthesized_event,
662 session);
717 else 663 else
718 event__synthesize_threads(process_synthesized_event, session); 664 perf_event__synthesize_threads(process_synthesized_event,
665 session);
719 666
720 if (realtime_prio) { 667 if (realtime_prio) {
721 struct sched_param param; 668 struct sched_param param;
@@ -742,32 +689,35 @@ static int __cmd_record(int argc, const char **argv)
742 if (hits == samples) { 689 if (hits == samples) {
743 if (done) 690 if (done)
744 break; 691 break;
745 err = poll(event_array, nr_poll, -1); 692 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
746 waking++; 693 waking++;
747 } 694 }
748 695
749 if (done) { 696 if (done) {
750 for (i = 0; i < nr_cpu; i++) { 697 for (i = 0; i < evsel_list->cpus->nr; i++) {
751 for (counter = 0; 698 struct perf_evsel *pos;
752 counter < nr_counters; 699
753 counter++) { 700 list_for_each_entry(pos, &evsel_list->entries, node) {
754 for (thread = 0; 701 for (thread = 0;
755 thread < thread_num; 702 thread < evsel_list->threads->nr;
756 thread++) 703 thread++)
757 ioctl(fd[i][counter][thread], 704 ioctl(FD(pos, i, thread),
758 PERF_EVENT_IOC_DISABLE); 705 PERF_EVENT_IOC_DISABLE);
759 } 706 }
760 } 707 }
761 } 708 }
762 } 709 }
763 710
711 if (quiet || signr == SIGUSR1)
712 return 0;
713
764 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 714 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
765 715
766 /* 716 /*
767 * Approximate RIP event size: 24 bytes. 717 * Approximate RIP event size: 24 bytes.
768 */ 718 */
769 fprintf(stderr, 719 fprintf(stderr,
770 "[ perf record: Captured and wrote %.3f MB %s (~%lld samples) ]\n", 720 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
771 (double)bytes_written / 1024.0 / 1024.0, 721 (double)bytes_written / 1024.0 / 1024.0,
772 output_name, 722 output_name,
773 bytes_written / 24); 723 bytes_written / 24);
@@ -787,11 +737,11 @@ static const char * const record_usage[] = {
787 737
788static bool force, append_file; 738static bool force, append_file;
789 739
790static const struct option options[] = { 740const struct option record_options[] = {
791 OPT_CALLBACK('e', "event", NULL, "event", 741 OPT_CALLBACK('e', "event", &evsel_list, "event",
792 "event selector. use 'perf list' to list available events", 742 "event selector. use 'perf list' to list available events",
793 parse_events), 743 parse_events),
794 OPT_CALLBACK(0, "filter", NULL, "filter", 744 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
795 "event filter", parse_filter), 745 "event filter", parse_filter),
796 OPT_INTEGER('p', "pid", &target_pid, 746 OPT_INTEGER('p', "pid", &target_pid,
797 "record events on existing process id"), 747 "record events on existing process id"),
@@ -799,6 +749,8 @@ static const struct option options[] = {
799 "record events on existing thread id"), 749 "record events on existing thread id"),
800 OPT_INTEGER('r', "realtime", &realtime_prio, 750 OPT_INTEGER('r', "realtime", &realtime_prio,
801 "collect data with this RT SCHED_FIFO priority"), 751 "collect data with this RT SCHED_FIFO priority"),
752 OPT_BOOLEAN('D', "no-delay", &nodelay,
753 "collect data without buffering"),
802 OPT_BOOLEAN('R', "raw-samples", &raw_samples, 754 OPT_BOOLEAN('R', "raw-samples", &raw_samples,
803 "collect raw sample records from all opened counters"), 755 "collect raw sample records from all opened counters"),
804 OPT_BOOLEAN('a', "all-cpus", &system_wide, 756 OPT_BOOLEAN('a', "all-cpus", &system_wide,
@@ -820,74 +772,92 @@ static const struct option options[] = {
820 "do call-graph (stack chain/backtrace) recording"), 772 "do call-graph (stack chain/backtrace) recording"),
821 OPT_INCR('v', "verbose", &verbose, 773 OPT_INCR('v', "verbose", &verbose,
822 "be more verbose (show counter open errors, etc)"), 774 "be more verbose (show counter open errors, etc)"),
775 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
823 OPT_BOOLEAN('s', "stat", &inherit_stat, 776 OPT_BOOLEAN('s', "stat", &inherit_stat,
824 "per thread counts"), 777 "per thread counts"),
825 OPT_BOOLEAN('d', "data", &sample_address, 778 OPT_BOOLEAN('d', "data", &sample_address,
826 "Sample addresses"), 779 "Sample addresses"),
780 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
827 OPT_BOOLEAN('n', "no-samples", &no_samples, 781 OPT_BOOLEAN('n', "no-samples", &no_samples,
828 "don't sample"), 782 "don't sample"),
829 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid, 783 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
830 "do not update the buildid cache"), 784 "do not update the buildid cache"),
785 OPT_BOOLEAN('B', "no-buildid", &no_buildid,
786 "do not collect buildids in perf.data"),
787 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
788 "monitor event in cgroup name only",
789 parse_cgroups),
831 OPT_END() 790 OPT_END()
832}; 791};
833 792
834int cmd_record(int argc, const char **argv, const char *prefix __used) 793int cmd_record(int argc, const char **argv, const char *prefix __used)
835{ 794{
836 int i, j, err = -ENOMEM; 795 int err = -ENOMEM;
796 struct perf_evsel *pos;
837 797
838 argc = parse_options(argc, argv, options, record_usage, 798 evsel_list = perf_evlist__new(NULL, NULL);
799 if (evsel_list == NULL)
800 return -ENOMEM;
801
802 argc = parse_options(argc, argv, record_options, record_usage,
839 PARSE_OPT_STOP_AT_NON_OPTION); 803 PARSE_OPT_STOP_AT_NON_OPTION);
840 if (!argc && target_pid == -1 && target_tid == -1 && 804 if (!argc && target_pid == -1 && target_tid == -1 &&
841 !system_wide && !cpu_list) 805 !system_wide && !cpu_list)
842 usage_with_options(record_usage, options); 806 usage_with_options(record_usage, record_options);
843 807
844 if (force && append_file) { 808 if (force && append_file) {
845 fprintf(stderr, "Can't overwrite and append at the same time." 809 fprintf(stderr, "Can't overwrite and append at the same time."
846 " You need to choose between -f and -A"); 810 " You need to choose between -f and -A");
847 usage_with_options(record_usage, options); 811 usage_with_options(record_usage, record_options);
848 } else if (append_file) { 812 } else if (append_file) {
849 write_mode = WRITE_APPEND; 813 write_mode = WRITE_APPEND;
850 } else { 814 } else {
851 write_mode = WRITE_FORCE; 815 write_mode = WRITE_FORCE;
852 } 816 }
853 817
818 if (nr_cgroups && !system_wide) {
819 fprintf(stderr, "cgroup monitoring only available in"
820 " system-wide mode\n");
821 usage_with_options(record_usage, record_options);
822 }
823
854 symbol__init(); 824 symbol__init();
855 if (no_buildid) 825
826 if (symbol_conf.kptr_restrict)
827 pr_warning(
828"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
829"check /proc/sys/kernel/kptr_restrict.\n\n"
830"Samples in kernel functions may not be resolved if a suitable vmlinux\n"
831"file is not found in the buildid cache or in the vmlinux path.\n\n"
832"Samples in kernel modules won't be resolved at all.\n\n"
833"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
834"even with a suitable vmlinux or kallsyms file.\n\n");
835
836 if (no_buildid_cache || no_buildid)
856 disable_buildid_cache(); 837 disable_buildid_cache();
857 838
858 if (!nr_counters) { 839 if (evsel_list->nr_entries == 0 &&
859 nr_counters = 1; 840 perf_evlist__add_default(evsel_list) < 0) {
860 attrs[0].type = PERF_TYPE_HARDWARE; 841 pr_err("Not enough memory for event selector list\n");
861 attrs[0].config = PERF_COUNT_HW_CPU_CYCLES; 842 goto out_symbol_exit;
862 } 843 }
863 844
864 if (target_pid != -1) { 845 if (target_pid != -1)
865 target_tid = target_pid; 846 target_tid = target_pid;
866 thread_num = find_all_tid(target_pid, &all_tids);
867 if (thread_num <= 0) {
868 fprintf(stderr, "Can't find all threads of pid %d\n",
869 target_pid);
870 usage_with_options(record_usage, options);
871 }
872 } else {
873 all_tids=malloc(sizeof(pid_t));
874 if (!all_tids)
875 goto out_symbol_exit;
876 847
877 all_tids[0] = target_tid; 848 if (perf_evlist__create_maps(evsel_list, target_pid,
878 thread_num = 1; 849 target_tid, cpu_list) < 0)
879 } 850 usage_with_options(record_usage, record_options);
880 851
881 for (i = 0; i < MAX_NR_CPUS; i++) { 852 list_for_each_entry(pos, &evsel_list->entries, node) {
882 for (j = 0; j < MAX_COUNTERS; j++) { 853 if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
883 fd[i][j] = malloc(sizeof(int)*thread_num); 854 evsel_list->threads->nr) < 0)
884 if (!fd[i][j]) 855 goto out_free_fd;
885 goto out_free_fd; 856 if (perf_header__push_event(pos->attr.config, event_name(pos)))
886 } 857 goto out_free_fd;
887 } 858 }
888 event_array = malloc( 859
889 sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num); 860 if (perf_evlist__alloc_pollfd(evsel_list) < 0)
890 if (!event_array)
891 goto out_free_fd; 861 goto out_free_fd;
892 862
893 if (user_interval != ULLONG_MAX) 863 if (user_interval != ULLONG_MAX)
@@ -905,20 +875,12 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
905 } else { 875 } else {
906 fprintf(stderr, "frequency and count are zero, aborting\n"); 876 fprintf(stderr, "frequency and count are zero, aborting\n");
907 err = -EINVAL; 877 err = -EINVAL;
908 goto out_free_event_array; 878 goto out_free_fd;
909 } 879 }
910 880
911 err = __cmd_record(argc, argv); 881 err = __cmd_record(argc, argv);
912
913out_free_event_array:
914 free(event_array);
915out_free_fd: 882out_free_fd:
916 for (i = 0; i < MAX_NR_CPUS; i++) { 883 perf_evlist__delete_maps(evsel_list);
917 for (j = 0; j < MAX_COUNTERS; j++)
918 free(fd[i][j]);
919 }
920 free(all_tids);
921 all_tids = NULL;
922out_symbol_exit: 884out_symbol_exit:
923 symbol__exit(); 885 symbol__exit();
924 return err; 886 return err;