1 #include <traceevent/event-parse.h>
3 #include "util/color.h"
4 #include "util/debug.h"
5 #include "util/evlist.h"
6 #include "util/machine.h"
7 #include "util/session.h"
8 #include "util/thread.h"
9 #include "util/parse-options.h"
10 #include "util/strlist.h"
11 #include "util/intlist.h"
12 #include "util/thread_map.h"
16 #include <sys/eventfd.h>
18 #include <linux/futex.h>
20 /* For older distros: */
22 # define MAP_STACK 0x20000
26 # define MADV_HWPOISON 100
29 #ifndef MADV_MERGEABLE
30 # define MADV_MERGEABLE 12
33 #ifndef MADV_UNMERGEABLE
34 # define MADV_UNMERGEABLE 13
49 #define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
50 .nr_entries = ARRAY_SIZE(array), \
54 static size_t syscall_arg__scnprintf_strarray(char *bf
, size_t size
,
55 struct syscall_arg
*arg
)
58 struct strarray
*sa
= arg
->parm
;
60 if (idx
< 0 || idx
>= sa
->nr_entries
)
61 return scnprintf(bf
, size
, "%d", idx
);
63 return scnprintf(bf
, size
, "%s", sa
->entries
[idx
]);
66 #define SCA_STRARRAY syscall_arg__scnprintf_strarray
68 static size_t syscall_arg__scnprintf_hex(char *bf
, size_t size
,
69 struct syscall_arg
*arg
)
71 return scnprintf(bf
, size
, "%#lx", arg
->val
);
74 #define SCA_HEX syscall_arg__scnprintf_hex
76 static size_t syscall_arg__scnprintf_mmap_prot(char *bf
, size_t size
,
77 struct syscall_arg
*arg
)
79 int printed
= 0, prot
= arg
->val
;
81 if (prot
== PROT_NONE
)
82 return scnprintf(bf
, size
, "NONE");
83 #define P_MMAP_PROT(n) \
84 if (prot & PROT_##n) { \
85 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
95 P_MMAP_PROT(GROWSDOWN
);
100 printed
+= scnprintf(bf
+ printed
, size
- printed
, "%s%#x", printed
? "|" : "", prot
);
105 #define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
107 static size_t syscall_arg__scnprintf_mmap_flags(char *bf
, size_t size
,
108 struct syscall_arg
*arg
)
110 int printed
= 0, flags
= arg
->val
;
112 #define P_MMAP_FLAG(n) \
113 if (flags & MAP_##n) { \
114 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
119 P_MMAP_FLAG(PRIVATE
);
123 P_MMAP_FLAG(ANONYMOUS
);
124 P_MMAP_FLAG(DENYWRITE
);
125 P_MMAP_FLAG(EXECUTABLE
);
128 P_MMAP_FLAG(GROWSDOWN
);
130 P_MMAP_FLAG(HUGETLB
);
133 P_MMAP_FLAG(NONBLOCK
);
134 P_MMAP_FLAG(NORESERVE
);
135 P_MMAP_FLAG(POPULATE
);
137 #ifdef MAP_UNINITIALIZED
138 P_MMAP_FLAG(UNINITIALIZED
);
143 printed
+= scnprintf(bf
+ printed
, size
- printed
, "%s%#x", printed
? "|" : "", flags
);
148 #define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
150 static size_t syscall_arg__scnprintf_madvise_behavior(char *bf
, size_t size
,
151 struct syscall_arg
*arg
)
153 int behavior
= arg
->val
;
156 #define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
159 P_MADV_BHV(SEQUENTIAL
);
160 P_MADV_BHV(WILLNEED
);
161 P_MADV_BHV(DONTNEED
);
163 P_MADV_BHV(DONTFORK
);
165 P_MADV_BHV(HWPOISON
);
166 #ifdef MADV_SOFT_OFFLINE
167 P_MADV_BHV(SOFT_OFFLINE
);
169 P_MADV_BHV(MERGEABLE
);
170 P_MADV_BHV(UNMERGEABLE
);
172 P_MADV_BHV(HUGEPAGE
);
174 #ifdef MADV_NOHUGEPAGE
175 P_MADV_BHV(NOHUGEPAGE
);
178 P_MADV_BHV(DONTDUMP
);
187 return scnprintf(bf
, size
, "%#x", behavior
);
190 #define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
192 static size_t syscall_arg__scnprintf_flock(char *bf
, size_t size
,
193 struct syscall_arg
*arg
)
195 int printed
= 0, op
= arg
->val
;
198 return scnprintf(bf
, size
, "NONE");
200 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
201 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
216 printed
+= scnprintf(bf
+ printed
, size
- printed
, "%s%#x", printed
? "|" : "", op
);
221 #define SCA_FLOCK syscall_arg__scnprintf_flock
223 static size_t syscall_arg__scnprintf_futex_op(char *bf
, size_t size
, struct syscall_arg
*arg
)
225 enum syscall_futex_args
{
226 SCF_UADDR
= (1 << 0),
229 SCF_TIMEOUT
= (1 << 3),
230 SCF_UADDR2
= (1 << 4),
234 int cmd
= op
& FUTEX_CMD_MASK
;
238 #define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
239 P_FUTEX_OP(WAIT
); arg
->mask
|= SCF_VAL3
|SCF_UADDR2
; break;
240 P_FUTEX_OP(WAKE
); arg
->mask
|= SCF_VAL3
|SCF_UADDR2
|SCF_TIMEOUT
; break;
241 P_FUTEX_OP(FD
); arg
->mask
|= SCF_VAL3
|SCF_UADDR2
|SCF_TIMEOUT
; break;
242 P_FUTEX_OP(REQUEUE
); arg
->mask
|= SCF_VAL3
|SCF_TIMEOUT
; break;
243 P_FUTEX_OP(CMP_REQUEUE
); arg
->mask
|= SCF_TIMEOUT
; break;
244 P_FUTEX_OP(CMP_REQUEUE_PI
); arg
->mask
|= SCF_TIMEOUT
; break;
245 P_FUTEX_OP(WAKE_OP
); break;
246 P_FUTEX_OP(LOCK_PI
); arg
->mask
|= SCF_VAL3
|SCF_UADDR2
|SCF_TIMEOUT
; break;
247 P_FUTEX_OP(UNLOCK_PI
); arg
->mask
|= SCF_VAL3
|SCF_UADDR2
|SCF_TIMEOUT
; break;
248 P_FUTEX_OP(TRYLOCK_PI
); arg
->mask
|= SCF_VAL3
|SCF_UADDR2
; break;
249 P_FUTEX_OP(WAIT_BITSET
); arg
->mask
|= SCF_UADDR2
; break;
250 P_FUTEX_OP(WAKE_BITSET
); arg
->mask
|= SCF_UADDR2
; break;
251 P_FUTEX_OP(WAIT_REQUEUE_PI
); break;
252 default: printed
= scnprintf(bf
, size
, "%#x", cmd
); break;
255 if (op
& FUTEX_PRIVATE_FLAG
)
256 printed
+= scnprintf(bf
+ printed
, size
- printed
, "|PRIV");
258 if (op
& FUTEX_CLOCK_REALTIME
)
259 printed
+= scnprintf(bf
+ printed
, size
- printed
, "|CLKRT");
264 #define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
266 static const char *epoll_ctl_ops
[] = { [1] = "ADD", "DEL", "MOD", };
267 static DEFINE_STRARRAY(epoll_ctl_ops
);
269 static const char *itimers
[] = { "REAL", "VIRTUAL", "PROF", };
270 static DEFINE_STRARRAY(itimers
);
272 static const char *whences
[] = { "SET", "CUR", "END",
280 static DEFINE_STRARRAY(whences
);
282 static const char *fcntl_cmds
[] = {
283 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
284 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
285 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
288 static DEFINE_STRARRAY(fcntl_cmds
);
290 static const char *rlimit_resources
[] = {
291 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
292 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
295 static DEFINE_STRARRAY(rlimit_resources
);
297 static const char *sighow
[] = { "BLOCK", "UNBLOCK", "SETMASK", };
298 static DEFINE_STRARRAY(sighow
);
300 static const char *socket_families
[] = {
301 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
302 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
303 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
304 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
305 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
306 "ALG", "NFC", "VSOCK",
308 static DEFINE_STRARRAY(socket_families
);
310 #ifndef SOCK_TYPE_MASK
311 #define SOCK_TYPE_MASK 0xf
314 static size_t syscall_arg__scnprintf_socket_type(char *bf
, size_t size
,
315 struct syscall_arg
*arg
)
319 flags
= type
& ~SOCK_TYPE_MASK
;
321 type
&= SOCK_TYPE_MASK
;
323 * Can't use a strarray, MIPS may override for ABI reasons.
326 #define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
331 P_SK_TYPE(SEQPACKET
);
336 printed
= scnprintf(bf
, size
, "%#x", type
);
339 #define P_SK_FLAG(n) \
340 if (flags & SOCK_##n) { \
341 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
342 flags &= ~SOCK_##n; \
350 printed
+= scnprintf(bf
+ printed
, size
- printed
, "|%#x", flags
);
355 #define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
358 #define MSG_PROBE 0x10
360 #ifndef MSG_SENDPAGE_NOTLAST
361 #define MSG_SENDPAGE_NOTLAST 0x20000
364 #define MSG_FASTOPEN 0x20000000
367 static size_t syscall_arg__scnprintf_msg_flags(char *bf
, size_t size
,
368 struct syscall_arg
*arg
)
370 int printed
= 0, flags
= arg
->val
;
373 return scnprintf(bf
, size
, "NONE");
374 #define P_MSG_FLAG(n) \
375 if (flags & MSG_##n) { \
376 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
382 P_MSG_FLAG(DONTROUTE
);
387 P_MSG_FLAG(DONTWAIT
);
394 P_MSG_FLAG(ERRQUEUE
);
395 P_MSG_FLAG(NOSIGNAL
);
397 P_MSG_FLAG(WAITFORONE
);
398 P_MSG_FLAG(SENDPAGE_NOTLAST
);
399 P_MSG_FLAG(FASTOPEN
);
400 P_MSG_FLAG(CMSG_CLOEXEC
);
404 printed
+= scnprintf(bf
+ printed
, size
- printed
, "%s%#x", printed
? "|" : "", flags
);
409 #define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
411 static size_t syscall_arg__scnprintf_access_mode(char *bf
, size_t size
,
412 struct syscall_arg
*arg
)
417 if (mode
== F_OK
) /* 0 */
418 return scnprintf(bf
, size
, "F");
420 if (mode & n##_OK) { \
421 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
431 printed
+= scnprintf(bf
+ printed
, size
- printed
, "|%#x", mode
);
436 #define SCA_ACCMODE syscall_arg__scnprintf_access_mode
438 static size_t syscall_arg__scnprintf_open_flags(char *bf
, size_t size
,
439 struct syscall_arg
*arg
)
441 int printed
= 0, flags
= arg
->val
;
443 if (!(flags
& O_CREAT
))
444 arg
->mask
|= 1 << (arg
->idx
+ 1); /* Mask the mode parm */
447 return scnprintf(bf
, size
, "RDONLY");
449 if (flags & O_##n) { \
450 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
474 if ((flags
& O_SYNC
) == O_SYNC
)
475 printed
+= scnprintf(bf
+ printed
, size
- printed
, "%s%s", printed
? "|" : "", "SYNC");
487 printed
+= scnprintf(bf
+ printed
, size
- printed
, "%s%#x", printed
? "|" : "", flags
);
492 #define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
494 static size_t syscall_arg__scnprintf_eventfd_flags(char *bf
, size_t size
,
495 struct syscall_arg
*arg
)
497 int printed
= 0, flags
= arg
->val
;
500 return scnprintf(bf
, size
, "NONE");
502 if (flags & EFD_##n) { \
503 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
513 printed
+= scnprintf(bf
+ printed
, size
- printed
, "%s%#x", printed
? "|" : "", flags
);
518 #define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
520 static size_t syscall_arg__scnprintf_signum(char *bf
, size_t size
, struct syscall_arg
*arg
)
525 #define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
560 return scnprintf(bf
, size
, "%#x", sig
);
563 #define SCA_SIGNUM syscall_arg__scnprintf_signum
565 static struct syscall_fmt
{
568 size_t (*arg_scnprintf
[6])(char *bf
, size_t size
, struct syscall_arg
*arg
);
574 { .name
= "access", .errmsg
= true,
575 .arg_scnprintf
= { [1] = SCA_ACCMODE
, /* mode */ }, },
576 { .name
= "arch_prctl", .errmsg
= true, .alias
= "prctl", },
577 { .name
= "brk", .hexret
= true,
578 .arg_scnprintf
= { [0] = SCA_HEX
, /* brk */ }, },
579 { .name
= "connect", .errmsg
= true, },
580 { .name
= "epoll_ctl", .errmsg
= true,
581 .arg_scnprintf
= { [1] = SCA_STRARRAY
, /* op */ },
582 .arg_parm
= { [1] = &strarray__epoll_ctl_ops
, /* op */ }, },
583 { .name
= "eventfd2", .errmsg
= true,
584 .arg_scnprintf
= { [1] = SCA_EFD_FLAGS
, /* flags */ }, },
585 { .name
= "fcntl", .errmsg
= true,
586 .arg_scnprintf
= { [1] = SCA_STRARRAY
, /* cmd */ },
587 .arg_parm
= { [1] = &strarray__fcntl_cmds
, /* cmd */ }, },
588 { .name
= "flock", .errmsg
= true,
589 .arg_scnprintf
= { [1] = SCA_FLOCK
, /* cmd */ }, },
590 { .name
= "fstat", .errmsg
= true, .alias
= "newfstat", },
591 { .name
= "fstatat", .errmsg
= true, .alias
= "newfstatat", },
592 { .name
= "futex", .errmsg
= true,
593 .arg_scnprintf
= { [1] = SCA_FUTEX_OP
, /* op */ }, },
594 { .name
= "getitimer", .errmsg
= true,
595 .arg_scnprintf
= { [0] = SCA_STRARRAY
, /* which */ },
596 .arg_parm
= { [0] = &strarray__itimers
, /* which */ }, },
597 { .name
= "getrlimit", .errmsg
= true,
598 .arg_scnprintf
= { [0] = SCA_STRARRAY
, /* resource */ },
599 .arg_parm
= { [0] = &strarray__rlimit_resources
, /* resource */ }, },
600 { .name
= "ioctl", .errmsg
= true,
601 .arg_scnprintf
= { [2] = SCA_HEX
, /* arg */ }, },
602 { .name
= "kill", .errmsg
= true,
603 .arg_scnprintf
= { [1] = SCA_SIGNUM
, /* sig */ }, },
604 { .name
= "lseek", .errmsg
= true,
605 .arg_scnprintf
= { [2] = SCA_STRARRAY
, /* whence */ },
606 .arg_parm
= { [2] = &strarray__whences
, /* whence */ }, },
607 { .name
= "lstat", .errmsg
= true, .alias
= "newlstat", },
608 { .name
= "madvise", .errmsg
= true,
609 .arg_scnprintf
= { [0] = SCA_HEX
, /* start */
610 [2] = SCA_MADV_BHV
, /* behavior */ }, },
611 { .name
= "mmap", .hexret
= true,
612 .arg_scnprintf
= { [0] = SCA_HEX
, /* addr */
613 [2] = SCA_MMAP_PROT
, /* prot */
614 [3] = SCA_MMAP_FLAGS
, /* flags */ }, },
615 { .name
= "mprotect", .errmsg
= true,
616 .arg_scnprintf
= { [0] = SCA_HEX
, /* start */
617 [2] = SCA_MMAP_PROT
, /* prot */ }, },
618 { .name
= "mremap", .hexret
= true,
619 .arg_scnprintf
= { [0] = SCA_HEX
, /* addr */
620 [4] = SCA_HEX
, /* new_addr */ }, },
621 { .name
= "munmap", .errmsg
= true,
622 .arg_scnprintf
= { [0] = SCA_HEX
, /* addr */ }, },
623 { .name
= "open", .errmsg
= true,
624 .arg_scnprintf
= { [1] = SCA_OPEN_FLAGS
, /* flags */ }, },
625 { .name
= "open_by_handle_at", .errmsg
= true,
626 .arg_scnprintf
= { [2] = SCA_OPEN_FLAGS
, /* flags */ }, },
627 { .name
= "openat", .errmsg
= true,
628 .arg_scnprintf
= { [2] = SCA_OPEN_FLAGS
, /* flags */ }, },
629 { .name
= "poll", .errmsg
= true, .timeout
= true, },
630 { .name
= "ppoll", .errmsg
= true, .timeout
= true, },
631 { .name
= "pread", .errmsg
= true, .alias
= "pread64", },
632 { .name
= "prlimit64", .errmsg
= true,
633 .arg_scnprintf
= { [1] = SCA_STRARRAY
, /* resource */ },
634 .arg_parm
= { [1] = &strarray__rlimit_resources
, /* resource */ }, },
635 { .name
= "pwrite", .errmsg
= true, .alias
= "pwrite64", },
636 { .name
= "read", .errmsg
= true, },
637 { .name
= "recvfrom", .errmsg
= true,
638 .arg_scnprintf
= { [3] = SCA_MSG_FLAGS
, /* flags */ }, },
639 { .name
= "recvmmsg", .errmsg
= true,
640 .arg_scnprintf
= { [3] = SCA_MSG_FLAGS
, /* flags */ }, },
641 { .name
= "recvmsg", .errmsg
= true,
642 .arg_scnprintf
= { [2] = SCA_MSG_FLAGS
, /* flags */ }, },
643 { .name
= "rt_sigaction", .errmsg
= true,
644 .arg_scnprintf
= { [0] = SCA_SIGNUM
, /* sig */ }, },
645 { .name
= "rt_sigprocmask", .errmsg
= true,
646 .arg_scnprintf
= { [0] = SCA_STRARRAY
, /* how */ },
647 .arg_parm
= { [0] = &strarray__sighow
, /* how */ }, },
648 { .name
= "rt_sigqueueinfo", .errmsg
= true,
649 .arg_scnprintf
= { [1] = SCA_SIGNUM
, /* sig */ }, },
650 { .name
= "rt_tgsigqueueinfo", .errmsg
= true,
651 .arg_scnprintf
= { [2] = SCA_SIGNUM
, /* sig */ }, },
652 { .name
= "select", .errmsg
= true, .timeout
= true, },
653 { .name
= "sendmmsg", .errmsg
= true,
654 .arg_scnprintf
= { [3] = SCA_MSG_FLAGS
, /* flags */ }, },
655 { .name
= "sendmsg", .errmsg
= true,
656 .arg_scnprintf
= { [2] = SCA_MSG_FLAGS
, /* flags */ }, },
657 { .name
= "sendto", .errmsg
= true,
658 .arg_scnprintf
= { [3] = SCA_MSG_FLAGS
, /* flags */ }, },
659 { .name
= "setitimer", .errmsg
= true,
660 .arg_scnprintf
= { [0] = SCA_STRARRAY
, /* which */ },
661 .arg_parm
= { [0] = &strarray__itimers
, /* which */ }, },
662 { .name
= "setrlimit", .errmsg
= true,
663 .arg_scnprintf
= { [0] = SCA_STRARRAY
, /* resource */ },
664 .arg_parm
= { [0] = &strarray__rlimit_resources
, /* resource */ }, },
665 { .name
= "socket", .errmsg
= true,
666 .arg_scnprintf
= { [0] = SCA_STRARRAY
, /* family */
667 [1] = SCA_SK_TYPE
, /* type */ },
668 .arg_parm
= { [0] = &strarray__socket_families
, /* family */ }, },
669 { .name
= "stat", .errmsg
= true, .alias
= "newstat", },
670 { .name
= "tgkill", .errmsg
= true,
671 .arg_scnprintf
= { [2] = SCA_SIGNUM
, /* sig */ }, },
672 { .name
= "tkill", .errmsg
= true,
673 .arg_scnprintf
= { [1] = SCA_SIGNUM
, /* sig */ }, },
674 { .name
= "uname", .errmsg
= true, .alias
= "newuname", },
677 static int syscall_fmt__cmp(const void *name
, const void *fmtp
)
679 const struct syscall_fmt
*fmt
= fmtp
;
680 return strcmp(name
, fmt
->name
);
683 static struct syscall_fmt
*syscall_fmt__find(const char *name
)
685 const int nmemb
= ARRAY_SIZE(syscall_fmts
);
686 return bsearch(name
, syscall_fmts
, nmemb
, sizeof(struct syscall_fmt
), syscall_fmt__cmp
);
690 struct event_format
*tp_format
;
693 struct syscall_fmt
*fmt
;
694 size_t (**arg_scnprintf
)(char *bf
, size_t size
, struct syscall_arg
*arg
);
698 static size_t fprintf_duration(unsigned long t
, FILE *fp
)
700 double duration
= (double)t
/ NSEC_PER_MSEC
;
701 size_t printed
= fprintf(fp
, "(");
704 printed
+= color_fprintf(fp
, PERF_COLOR_RED
, "%6.3f ms", duration
);
705 else if (duration
>= 0.01)
706 printed
+= color_fprintf(fp
, PERF_COLOR_YELLOW
, "%6.3f ms", duration
);
708 printed
+= color_fprintf(fp
, PERF_COLOR_NORMAL
, "%6.3f ms", duration
);
709 return printed
+ fprintf(fp
, "): ");
712 struct thread_trace
{
716 unsigned long nr_events
;
721 static struct thread_trace
*thread_trace__new(void)
723 return zalloc(sizeof(struct thread_trace
));
726 static struct thread_trace
*thread__trace(struct thread
*thread
, FILE *fp
)
728 struct thread_trace
*ttrace
;
733 if (thread
->priv
== NULL
)
734 thread
->priv
= thread_trace__new();
736 if (thread
->priv
== NULL
)
739 ttrace
= thread
->priv
;
744 color_fprintf(fp
, PERF_COLOR_RED
,
745 "WARNING: not enough memory, dropping samples!\n");
750 struct perf_tool tool
;
754 struct syscall
*table
;
756 struct perf_record_opts opts
;
761 unsigned long nr_events
;
762 struct strlist
*ev_qualifier
;
763 bool not_ev_qualifier
;
764 struct intlist
*tid_list
;
765 struct intlist
*pid_list
;
767 bool multiple_threads
;
769 double duration_filter
;
773 static bool trace__filter_duration(struct trace
*trace
, double t
)
775 return t
< (trace
->duration_filter
* NSEC_PER_MSEC
);
778 static size_t trace__fprintf_tstamp(struct trace
*trace
, u64 tstamp
, FILE *fp
)
780 double ts
= (double)(tstamp
- trace
->base_time
) / NSEC_PER_MSEC
;
782 return fprintf(fp
, "%10.3f ", ts
);
785 static bool done
= false;
787 static void sig_handler(int sig __maybe_unused
)
792 static size_t trace__fprintf_entry_head(struct trace
*trace
, struct thread
*thread
,
793 u64 duration
, u64 tstamp
, FILE *fp
)
795 size_t printed
= trace__fprintf_tstamp(trace
, tstamp
, fp
);
796 printed
+= fprintf_duration(duration
, fp
);
798 if (trace
->multiple_threads
) {
799 if (trace
->show_comm
)
800 printed
+= fprintf(fp
, "%.14s/", thread
->comm
);
801 printed
+= fprintf(fp
, "%d ", thread
->tid
);
807 static int trace__process_event(struct trace
*trace
, struct machine
*machine
,
808 union perf_event
*event
)
812 switch (event
->header
.type
) {
813 case PERF_RECORD_LOST
:
814 color_fprintf(trace
->output
, PERF_COLOR_RED
,
815 "LOST %" PRIu64
" events!\n", event
->lost
.lost
);
816 ret
= machine__process_lost_event(machine
, event
);
818 ret
= machine__process_event(machine
, event
);
825 static int trace__tool_process(struct perf_tool
*tool
,
826 union perf_event
*event
,
827 struct perf_sample
*sample __maybe_unused
,
828 struct machine
*machine
)
830 struct trace
*trace
= container_of(tool
, struct trace
, tool
);
831 return trace__process_event(trace
, machine
, event
);
834 static int trace__symbols_init(struct trace
*trace
, struct perf_evlist
*evlist
)
836 int err
= symbol__init();
841 machine__init(&trace
->host
, "", HOST_KERNEL_ID
);
842 machine__create_kernel_maps(&trace
->host
);
844 if (perf_target__has_task(&trace
->opts
.target
)) {
845 err
= perf_event__synthesize_thread_map(&trace
->tool
, evlist
->threads
,
849 err
= perf_event__synthesize_threads(&trace
->tool
, trace__tool_process
,
859 static int syscall__set_arg_fmts(struct syscall
*sc
)
861 struct format_field
*field
;
864 sc
->arg_scnprintf
= calloc(sc
->tp_format
->format
.nr_fields
- 1, sizeof(void *));
865 if (sc
->arg_scnprintf
== NULL
)
869 sc
->arg_parm
= sc
->fmt
->arg_parm
;
871 for (field
= sc
->tp_format
->format
.fields
->next
; field
; field
= field
->next
) {
872 if (sc
->fmt
&& sc
->fmt
->arg_scnprintf
[idx
])
873 sc
->arg_scnprintf
[idx
] = sc
->fmt
->arg_scnprintf
[idx
];
874 else if (field
->flags
& FIELD_IS_POINTER
)
875 sc
->arg_scnprintf
[idx
] = syscall_arg__scnprintf_hex
;
882 static int trace__read_syscall_info(struct trace
*trace
, int id
)
886 const char *name
= audit_syscall_to_name(id
, trace
->audit_machine
);
891 if (id
> trace
->syscalls
.max
) {
892 struct syscall
*nsyscalls
= realloc(trace
->syscalls
.table
, (id
+ 1) * sizeof(*sc
));
894 if (nsyscalls
== NULL
)
897 if (trace
->syscalls
.max
!= -1) {
898 memset(nsyscalls
+ trace
->syscalls
.max
+ 1, 0,
899 (id
- trace
->syscalls
.max
) * sizeof(*sc
));
901 memset(nsyscalls
, 0, (id
+ 1) * sizeof(*sc
));
904 trace
->syscalls
.table
= nsyscalls
;
905 trace
->syscalls
.max
= id
;
908 sc
= trace
->syscalls
.table
+ id
;
911 if (trace
->ev_qualifier
) {
912 bool in
= strlist__find(trace
->ev_qualifier
, name
) != NULL
;
914 if (!(in
^ trace
->not_ev_qualifier
)) {
917 * No need to do read tracepoint information since this will be
924 sc
->fmt
= syscall_fmt__find(sc
->name
);
926 snprintf(tp_name
, sizeof(tp_name
), "sys_enter_%s", sc
->name
);
927 sc
->tp_format
= event_format__new("syscalls", tp_name
);
929 if (sc
->tp_format
== NULL
&& sc
->fmt
&& sc
->fmt
->alias
) {
930 snprintf(tp_name
, sizeof(tp_name
), "sys_enter_%s", sc
->fmt
->alias
);
931 sc
->tp_format
= event_format__new("syscalls", tp_name
);
934 if (sc
->tp_format
== NULL
)
937 return syscall__set_arg_fmts(sc
);
940 static size_t syscall__scnprintf_args(struct syscall
*sc
, char *bf
, size_t size
,
945 if (sc
->tp_format
!= NULL
) {
946 struct format_field
*field
;
948 struct syscall_arg arg
= {
953 for (field
= sc
->tp_format
->format
.fields
->next
; field
;
954 field
= field
->next
, ++arg
.idx
, bit
<<= 1) {
958 if (args
[arg
.idx
] == 0)
961 printed
+= scnprintf(bf
+ printed
, size
- printed
,
962 "%s%s: ", printed
? ", " : "", field
->name
);
963 if (sc
->arg_scnprintf
&& sc
->arg_scnprintf
[arg
.idx
]) {
964 arg
.val
= args
[arg
.idx
];
966 arg
.parm
= sc
->arg_parm
[arg
.idx
];
967 printed
+= sc
->arg_scnprintf
[arg
.idx
](bf
+ printed
,
968 size
- printed
, &arg
);
970 printed
+= scnprintf(bf
+ printed
, size
- printed
,
971 "%ld", args
[arg
.idx
]);
978 printed
+= scnprintf(bf
+ printed
, size
- printed
,
980 printed
? ", " : "", i
, args
[i
]);
988 typedef int (*tracepoint_handler
)(struct trace
*trace
, struct perf_evsel
*evsel
,
989 struct perf_sample
*sample
);
991 static struct syscall
*trace__syscall_info(struct trace
*trace
,
992 struct perf_evsel
*evsel
,
993 struct perf_sample
*sample
)
995 int id
= perf_evsel__intval(evsel
, sample
, "id");
1000 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
1001 * before that, leaving at a higher verbosity level till that is
1002 * explained. Reproduced with plain ftrace with:
1004 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
1005 * grep "NR -1 " /t/trace_pipe
1007 * After generating some load on the machine.
1011 fprintf(trace
->output
, "Invalid syscall %d id, skipping (%s, %" PRIu64
") ...\n",
1012 id
, perf_evsel__name(evsel
), ++n
);
1017 if ((id
> trace
->syscalls
.max
|| trace
->syscalls
.table
[id
].name
== NULL
) &&
1018 trace__read_syscall_info(trace
, id
))
1021 if ((id
> trace
->syscalls
.max
|| trace
->syscalls
.table
[id
].name
== NULL
))
1024 return &trace
->syscalls
.table
[id
];
1028 fprintf(trace
->output
, "Problems reading syscall %d", id
);
1029 if (id
<= trace
->syscalls
.max
&& trace
->syscalls
.table
[id
].name
!= NULL
)
1030 fprintf(trace
->output
, "(%s)", trace
->syscalls
.table
[id
].name
);
1031 fputs(" information\n", trace
->output
);
1036 static int trace__sys_enter(struct trace
*trace
, struct perf_evsel
*evsel
,
1037 struct perf_sample
*sample
)
1042 struct thread
*thread
;
1043 struct syscall
*sc
= trace__syscall_info(trace
, evsel
, sample
);
1044 struct thread_trace
*ttrace
;
1052 thread
= machine__findnew_thread(&trace
->host
, sample
->pid
,
1054 ttrace
= thread__trace(thread
, trace
->output
);
1058 args
= perf_evsel__rawptr(evsel
, sample
, "args");
1060 fprintf(trace
->output
, "Problems reading syscall arguments\n");
1064 ttrace
= thread
->priv
;
1066 if (ttrace
->entry_str
== NULL
) {
1067 ttrace
->entry_str
= malloc(1024);
1068 if (!ttrace
->entry_str
)
1072 ttrace
->entry_time
= sample
->time
;
1073 msg
= ttrace
->entry_str
;
1074 printed
+= scnprintf(msg
+ printed
, 1024 - printed
, "%s(", sc
->name
);
1076 printed
+= syscall__scnprintf_args(sc
, msg
+ printed
, 1024 - printed
, args
);
1078 if (!strcmp(sc
->name
, "exit_group") || !strcmp(sc
->name
, "exit")) {
1079 if (!trace
->duration_filter
) {
1080 trace__fprintf_entry_head(trace
, thread
, 1, sample
->time
, trace
->output
);
1081 fprintf(trace
->output
, "%-70s\n", ttrace
->entry_str
);
1084 ttrace
->entry_pending
= true;
1089 static int trace__sys_exit(struct trace
*trace
, struct perf_evsel
*evsel
,
1090 struct perf_sample
*sample
)
1094 struct thread
*thread
;
1095 struct syscall
*sc
= trace__syscall_info(trace
, evsel
, sample
);
1096 struct thread_trace
*ttrace
;
1104 thread
= machine__findnew_thread(&trace
->host
, sample
->pid
,
1106 ttrace
= thread__trace(thread
, trace
->output
);
1110 ret
= perf_evsel__intval(evsel
, sample
, "ret");
1112 ttrace
= thread
->priv
;
1114 ttrace
->exit_time
= sample
->time
;
1116 if (ttrace
->entry_time
) {
1117 duration
= sample
->time
- ttrace
->entry_time
;
1118 if (trace__filter_duration(trace
, duration
))
1120 } else if (trace
->duration_filter
)
1123 trace__fprintf_entry_head(trace
, thread
, duration
, sample
->time
, trace
->output
);
1125 if (ttrace
->entry_pending
) {
1126 fprintf(trace
->output
, "%-70s", ttrace
->entry_str
);
1128 fprintf(trace
->output
, " ... [");
1129 color_fprintf(trace
->output
, PERF_COLOR_YELLOW
, "continued");
1130 fprintf(trace
->output
, "]: %s()", sc
->name
);
1133 if (sc
->fmt
== NULL
) {
1135 fprintf(trace
->output
, ") = %d", ret
);
1136 } else if (ret
< 0 && sc
->fmt
->errmsg
) {
1138 const char *emsg
= strerror_r(-ret
, bf
, sizeof(bf
)),
1139 *e
= audit_errno_to_name(-ret
);
1141 fprintf(trace
->output
, ") = -1 %s %s", e
, emsg
);
1142 } else if (ret
== 0 && sc
->fmt
->timeout
)
1143 fprintf(trace
->output
, ") = 0 Timeout");
1144 else if (sc
->fmt
->hexret
)
1145 fprintf(trace
->output
, ") = %#x", ret
);
1149 fputc('\n', trace
->output
);
1151 ttrace
->entry_pending
= false;
1156 static int trace__sched_stat_runtime(struct trace
*trace
, struct perf_evsel
*evsel
,
1157 struct perf_sample
*sample
)
1159 u64 runtime
= perf_evsel__intval(evsel
, sample
, "runtime");
1160 double runtime_ms
= (double)runtime
/ NSEC_PER_MSEC
;
1161 struct thread
*thread
= machine__findnew_thread(&trace
->host
,
1164 struct thread_trace
*ttrace
= thread__trace(thread
, trace
->output
);
1169 ttrace
->runtime_ms
+= runtime_ms
;
1170 trace
->runtime_ms
+= runtime_ms
;
1174 fprintf(trace
->output
, "%s: comm=%s,pid=%u,runtime=%" PRIu64
",vruntime=%" PRIu64
")\n",
1176 perf_evsel__strval(evsel
, sample
, "comm"),
1177 (pid_t
)perf_evsel__intval(evsel
, sample
, "pid"),
1179 perf_evsel__intval(evsel
, sample
, "vruntime"));
1183 static bool skip_sample(struct trace
*trace
, struct perf_sample
*sample
)
1185 if ((trace
->pid_list
&& intlist__find(trace
->pid_list
, sample
->pid
)) ||
1186 (trace
->tid_list
&& intlist__find(trace
->tid_list
, sample
->tid
)))
1189 if (trace
->pid_list
|| trace
->tid_list
)
1195 static int trace__process_sample(struct perf_tool
*tool
,
1196 union perf_event
*event __maybe_unused
,
1197 struct perf_sample
*sample
,
1198 struct perf_evsel
*evsel
,
1199 struct machine
*machine __maybe_unused
)
1201 struct trace
*trace
= container_of(tool
, struct trace
, tool
);
1204 tracepoint_handler handler
= evsel
->handler
.func
;
1206 if (skip_sample(trace
, sample
))
1209 if (!trace
->full_time
&& trace
->base_time
== 0)
1210 trace
->base_time
= sample
->time
;
1213 handler(trace
, evsel
, sample
);
1219 perf_session__has_tp(struct perf_session
*session
, const char *name
)
1221 struct perf_evsel
*evsel
;
1223 evsel
= perf_evlist__find_tracepoint_by_name(session
->evlist
, name
);
1225 return evsel
!= NULL
;
1228 static int parse_target_str(struct trace
*trace
)
1230 if (trace
->opts
.target
.pid
) {
1231 trace
->pid_list
= intlist__new(trace
->opts
.target
.pid
);
1232 if (trace
->pid_list
== NULL
) {
1233 pr_err("Error parsing process id string\n");
1238 if (trace
->opts
.target
.tid
) {
1239 trace
->tid_list
= intlist__new(trace
->opts
.target
.tid
);
1240 if (trace
->tid_list
== NULL
) {
1241 pr_err("Error parsing thread id string\n");
1249 static int trace__run(struct trace
*trace
, int argc
, const char **argv
)
1251 struct perf_evlist
*evlist
= perf_evlist__new();
1252 struct perf_evsel
*evsel
;
1254 unsigned long before
;
1255 const bool forks
= argc
> 0;
1257 if (evlist
== NULL
) {
1258 fprintf(trace
->output
, "Not enough memory to run!\n");
1262 if (perf_evlist__add_newtp(evlist
, "raw_syscalls", "sys_enter", trace__sys_enter
) ||
1263 perf_evlist__add_newtp(evlist
, "raw_syscalls", "sys_exit", trace__sys_exit
)) {
1264 fprintf(trace
->output
, "Couldn't read the raw_syscalls tracepoints information!\n");
1265 goto out_delete_evlist
;
1269 perf_evlist__add_newtp(evlist
, "sched", "sched_stat_runtime",
1270 trace__sched_stat_runtime
)) {
1271 fprintf(trace
->output
, "Couldn't read the sched_stat_runtime tracepoint information!\n");
1272 goto out_delete_evlist
;
1275 err
= perf_evlist__create_maps(evlist
, &trace
->opts
.target
);
1277 fprintf(trace
->output
, "Problems parsing the target to trace, check your options!\n");
1278 goto out_delete_evlist
;
1281 err
= trace__symbols_init(trace
, evlist
);
1283 fprintf(trace
->output
, "Problems initializing symbol libraries!\n");
1284 goto out_delete_maps
;
1287 perf_evlist__config(evlist
, &trace
->opts
);
1289 signal(SIGCHLD
, sig_handler
);
1290 signal(SIGINT
, sig_handler
);
1293 err
= perf_evlist__prepare_workload(evlist
, &trace
->opts
.target
,
1294 argv
, false, false);
1296 fprintf(trace
->output
, "Couldn't run the workload!\n");
1297 goto out_delete_maps
;
1301 err
= perf_evlist__open(evlist
);
1303 fprintf(trace
->output
, "Couldn't create the events: %s\n", strerror(errno
));
1304 goto out_delete_maps
;
1307 err
= perf_evlist__mmap(evlist
, UINT_MAX
, false);
1309 fprintf(trace
->output
, "Couldn't mmap the events: %s\n", strerror(errno
));
1310 goto out_close_evlist
;
1313 perf_evlist__enable(evlist
);
1316 perf_evlist__start_workload(evlist
);
1318 trace
->multiple_threads
= evlist
->threads
->map
[0] == -1 || evlist
->threads
->nr
> 1;
1320 before
= trace
->nr_events
;
1322 for (i
= 0; i
< evlist
->nr_mmaps
; i
++) {
1323 union perf_event
*event
;
1325 while ((event
= perf_evlist__mmap_read(evlist
, i
)) != NULL
) {
1326 const u32 type
= event
->header
.type
;
1327 tracepoint_handler handler
;
1328 struct perf_sample sample
;
1332 err
= perf_evlist__parse_sample(evlist
, event
, &sample
);
1334 fprintf(trace
->output
, "Can't parse sample, err = %d, skipping...\n", err
);
1338 if (!trace
->full_time
&& trace
->base_time
== 0)
1339 trace
->base_time
= sample
.time
;
1341 if (type
!= PERF_RECORD_SAMPLE
) {
1342 trace__process_event(trace
, &trace
->host
, event
);
1346 evsel
= perf_evlist__id2evsel(evlist
, sample
.id
);
1347 if (evsel
== NULL
) {
1348 fprintf(trace
->output
, "Unknown tp ID %" PRIu64
", skipping...\n", sample
.id
);
1352 if (sample
.raw_data
== NULL
) {
1353 fprintf(trace
->output
, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
1354 perf_evsel__name(evsel
), sample
.tid
,
1355 sample
.cpu
, sample
.raw_size
);
1359 handler
= evsel
->handler
.func
;
1360 handler(trace
, evsel
, &sample
);
1363 goto out_unmap_evlist
;
1367 if (trace
->nr_events
== before
) {
1369 goto out_unmap_evlist
;
1371 poll(evlist
->pollfd
, evlist
->nr_fds
, -1);
1375 perf_evlist__disable(evlist
);
1380 perf_evlist__munmap(evlist
);
1382 perf_evlist__close(evlist
);
1384 perf_evlist__delete_maps(evlist
);
1386 perf_evlist__delete(evlist
);
1391 static int trace__replay(struct trace
*trace
)
1393 const struct perf_evsel_str_handler handlers
[] = {
1394 { "raw_syscalls:sys_enter", trace__sys_enter
, },
1395 { "raw_syscalls:sys_exit", trace__sys_exit
, },
1398 struct perf_session
*session
;
1401 trace
->tool
.sample
= trace__process_sample
;
1402 trace
->tool
.mmap
= perf_event__process_mmap
;
1403 trace
->tool
.mmap2
= perf_event__process_mmap2
;
1404 trace
->tool
.comm
= perf_event__process_comm
;
1405 trace
->tool
.exit
= perf_event__process_exit
;
1406 trace
->tool
.fork
= perf_event__process_fork
;
1407 trace
->tool
.attr
= perf_event__process_attr
;
1408 trace
->tool
.tracing_data
= perf_event__process_tracing_data
;
1409 trace
->tool
.build_id
= perf_event__process_build_id
;
1411 trace
->tool
.ordered_samples
= true;
1412 trace
->tool
.ordering_requires_timestamps
= true;
1414 /* add tid to output */
1415 trace
->multiple_threads
= true;
1417 if (symbol__init() < 0)
1420 session
= perf_session__new(input_name
, O_RDONLY
, 0, false,
1422 if (session
== NULL
)
1425 err
= perf_session__set_tracepoints_handlers(session
, handlers
);
1429 if (!perf_session__has_tp(session
, "raw_syscalls:sys_enter")) {
1430 pr_err("Data file does not have raw_syscalls:sys_enter events\n");
1434 if (!perf_session__has_tp(session
, "raw_syscalls:sys_exit")) {
1435 pr_err("Data file does not have raw_syscalls:sys_exit events\n");
1439 err
= parse_target_str(trace
);
1445 err
= perf_session__process_events(session
, &trace
->tool
);
1447 pr_err("Failed to process events, error %d", err
);
1450 perf_session__delete(session
);
1455 static size_t trace__fprintf_threads_header(FILE *fp
)
1459 printed
= fprintf(fp
, "\n _____________________________________________________________________\n");
1460 printed
+= fprintf(fp
," __) Summary of events (__\n\n");
1461 printed
+= fprintf(fp
," [ task - pid ] [ events ] [ ratio ] [ runtime ]\n");
1462 printed
+= fprintf(fp
," _____________________________________________________________________\n\n");
1467 static size_t trace__fprintf_thread_summary(struct trace
*trace
, FILE *fp
)
1469 size_t printed
= trace__fprintf_threads_header(fp
);
1472 for (nd
= rb_first(&trace
->host
.threads
); nd
; nd
= rb_next(nd
)) {
1473 struct thread
*thread
= rb_entry(nd
, struct thread
, rb_node
);
1474 struct thread_trace
*ttrace
= thread
->priv
;
1481 ratio
= (double)ttrace
->nr_events
/ trace
->nr_events
* 100.0;
1483 color
= PERF_COLOR_NORMAL
;
1485 color
= PERF_COLOR_RED
;
1486 else if (ratio
> 25.0)
1487 color
= PERF_COLOR_GREEN
;
1488 else if (ratio
> 5.0)
1489 color
= PERF_COLOR_YELLOW
;
1491 printed
+= color_fprintf(fp
, color
, "%20s", thread
->comm
);
1492 printed
+= fprintf(fp
, " - %-5d :%11lu [", thread
->tid
, ttrace
->nr_events
);
1493 printed
+= color_fprintf(fp
, color
, "%5.1f%%", ratio
);
1494 printed
+= fprintf(fp
, " ] %10.3f ms\n", ttrace
->runtime_ms
);
1500 static int trace__set_duration(const struct option
*opt
, const char *str
,
1501 int unset __maybe_unused
)
1503 struct trace
*trace
= opt
->value
;
1505 trace
->duration_filter
= atof(str
);
1509 static int trace__open_output(struct trace
*trace
, const char *filename
)
1513 if (!stat(filename
, &st
) && st
.st_size
) {
1514 char oldname
[PATH_MAX
];
1516 scnprintf(oldname
, sizeof(oldname
), "%s.old", filename
);
1518 rename(filename
, oldname
);
1521 trace
->output
= fopen(filename
, "w");
1523 return trace
->output
== NULL
? -errno
: 0;
1526 int cmd_trace(int argc
, const char **argv
, const char *prefix __maybe_unused
)
1528 const char * const trace_usage
[] = {
1529 "perf trace [<options>] [<command>]",
1530 "perf trace [<options>] -- <command> [<options>]",
1533 struct trace trace
= {
1534 .audit_machine
= audit_detect_machine(),
1543 .user_freq
= UINT_MAX
,
1544 .user_interval
= ULLONG_MAX
,
1551 const char *output_name
= NULL
;
1552 const char *ev_qualifier_str
= NULL
;
1553 const struct option trace_options
[] = {
1554 OPT_BOOLEAN(0, "comm", &trace
.show_comm
,
1555 "show the thread COMM next to its id"),
1556 OPT_STRING('e', "expr", &ev_qualifier_str
, "expr",
1557 "list of events to trace"),
1558 OPT_STRING('o', "output", &output_name
, "file", "output file name"),
1559 OPT_STRING('i', "input", &input_name
, "file", "Analyze events in file"),
1560 OPT_STRING('p', "pid", &trace
.opts
.target
.pid
, "pid",
1561 "trace events on existing process id"),
1562 OPT_STRING('t', "tid", &trace
.opts
.target
.tid
, "tid",
1563 "trace events on existing thread id"),
1564 OPT_BOOLEAN('a', "all-cpus", &trace
.opts
.target
.system_wide
,
1565 "system-wide collection from all CPUs"),
1566 OPT_STRING('C', "cpu", &trace
.opts
.target
.cpu_list
, "cpu",
1567 "list of cpus to monitor"),
1568 OPT_BOOLEAN(0, "no-inherit", &trace
.opts
.no_inherit
,
1569 "child tasks do not inherit counters"),
1570 OPT_CALLBACK('m', "mmap-pages", &trace
.opts
.mmap_pages
, "pages",
1571 "number of mmap data pages",
1572 perf_evlist__parse_mmap_pages
),
1573 OPT_STRING('u', "uid", &trace
.opts
.target
.uid_str
, "user",
1575 OPT_CALLBACK(0, "duration", &trace
, "float",
1576 "show only events with duration > N.M ms",
1577 trace__set_duration
),
1578 OPT_BOOLEAN(0, "sched", &trace
.sched
, "show blocking scheduler events"),
1579 OPT_INCR('v', "verbose", &verbose
, "be more verbose"),
1580 OPT_BOOLEAN('T', "time", &trace
.full_time
,
1581 "Show full timestamp, not time relative to first start"),
1587 argc
= parse_options(argc
, argv
, trace_options
, trace_usage
, 0);
1589 if (output_name
!= NULL
) {
1590 err
= trace__open_output(&trace
, output_name
);
1592 perror("failed to create output file");
1597 if (ev_qualifier_str
!= NULL
) {
1598 const char *s
= ev_qualifier_str
;
1600 trace
.not_ev_qualifier
= *s
== '!';
1601 if (trace
.not_ev_qualifier
)
1603 trace
.ev_qualifier
= strlist__new(true, s
);
1604 if (trace
.ev_qualifier
== NULL
) {
1605 fputs("Not enough memory to parse event qualifier",
1612 err
= perf_target__validate(&trace
.opts
.target
);
1614 perf_target__strerror(&trace
.opts
.target
, err
, bf
, sizeof(bf
));
1615 fprintf(trace
.output
, "%s", bf
);
1619 err
= perf_target__parse_uid(&trace
.opts
.target
);
1621 perf_target__strerror(&trace
.opts
.target
, err
, bf
, sizeof(bf
));
1622 fprintf(trace
.output
, "%s", bf
);
1626 if (!argc
&& perf_target__none(&trace
.opts
.target
))
1627 trace
.opts
.target
.system_wide
= true;
1630 err
= trace__replay(&trace
);
1632 err
= trace__run(&trace
, argc
, argv
);
1634 if (trace
.sched
&& !err
)
1635 trace__fprintf_thread_summary(&trace
, trace
.output
);
1638 if (output_name
!= NULL
)
1639 fclose(trace
.output
);