perf trace: Add option to show process COMM
[platform/adaptation/renesas_rcar/renesas_kernel.git] / tools / perf / builtin-trace.c
index 2b19aef..be65843 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <libaudit.h>
 #include <stdlib.h>
+#include <sys/eventfd.h>
 #include <sys/mman.h>
 #include <linux/futex.h>
 
@@ -252,6 +253,13 @@ static const char *fcntl_cmds[] = {
 };
 static DEFINE_STRARRAY(fcntl_cmds);
 
+static const char *rlimit_resources[] = {
+       "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
+       "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
+       "RTTIME",
+};
+static DEFINE_STRARRAY(rlimit_resources);
+
 static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
 static DEFINE_STRARRAY(sighow);
 
@@ -312,6 +320,87 @@ static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
 
 #define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
 
+#ifndef MSG_PROBE
+#define MSG_PROBE           0x10
+#endif
+#ifndef MSG_SENDPAGE_NOTLAST
+#define MSG_SENDPAGE_NOTLAST 0x20000
+#endif
+#ifndef MSG_FASTOPEN
+#define MSG_FASTOPEN        0x20000000
+#endif
+
+static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
+                                              struct syscall_arg *arg)
+{
+       int printed = 0, flags = arg->val;
+
+       if (flags == 0)
+               return scnprintf(bf, size, "NONE");
+#define        P_MSG_FLAG(n) \
+       if (flags & MSG_##n) { \
+               printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
+               flags &= ~MSG_##n; \
+       }
+
+       P_MSG_FLAG(OOB);
+       P_MSG_FLAG(PEEK);
+       P_MSG_FLAG(DONTROUTE);
+       P_MSG_FLAG(TRYHARD);
+       P_MSG_FLAG(CTRUNC);
+       P_MSG_FLAG(PROBE);
+       P_MSG_FLAG(TRUNC);
+       P_MSG_FLAG(DONTWAIT);
+       P_MSG_FLAG(EOR);
+       P_MSG_FLAG(WAITALL);
+       P_MSG_FLAG(FIN);
+       P_MSG_FLAG(SYN);
+       P_MSG_FLAG(CONFIRM);
+       P_MSG_FLAG(RST);
+       P_MSG_FLAG(ERRQUEUE);
+       P_MSG_FLAG(NOSIGNAL);
+       P_MSG_FLAG(MORE);
+       P_MSG_FLAG(WAITFORONE);
+       P_MSG_FLAG(SENDPAGE_NOTLAST);
+       P_MSG_FLAG(FASTOPEN);
+       P_MSG_FLAG(CMSG_CLOEXEC);
+#undef P_MSG_FLAG
+
+       if (flags)
+               printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
+
+       return printed;
+}
+
+#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
+
+static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
+                                                struct syscall_arg *arg)
+{
+       size_t printed = 0;
+       int mode = arg->val;
+
+       if (mode == F_OK) /* 0 */
+               return scnprintf(bf, size, "F");
+#define        P_MODE(n) \
+       if (mode & n##_OK) { \
+               printed += scnprintf(bf + printed, size - printed, "%s", #n); \
+               mode &= ~n##_OK; \
+       }
+
+       P_MODE(R);
+       P_MODE(W);
+       P_MODE(X);
+#undef P_MODE
+
+       if (mode)
+               printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
+
+       return printed;
+}
+
+#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
+
 static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
                                               struct syscall_arg *arg)
 {
@@ -368,6 +457,32 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
 
 #define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
 
+static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
+                                                  struct syscall_arg *arg)
+{
+       int printed = 0, flags = arg->val;
+
+       if (flags == 0)
+               return scnprintf(bf, size, "NONE");
+#define        P_FLAG(n) \
+       if (flags & EFD_##n) { \
+               printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
+               flags &= ~EFD_##n; \
+       }
+
+       P_FLAG(SEMAPHORE);
+       P_FLAG(CLOEXEC);
+       P_FLAG(NONBLOCK);
+#undef P_FLAG
+
+       if (flags)
+               printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
+
+       return printed;
+}
+
+#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
+
 static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
 {
        int sig = arg->val;
@@ -422,12 +537,14 @@ static struct syscall_fmt {
        bool       timeout;
        bool       hexret;
 } syscall_fmts[] = {
-       { .name     = "access",     .errmsg = true, },
+       { .name     = "access",     .errmsg = true,
+         .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
        { .name     = "arch_prctl", .errmsg = true, .alias = "prctl", },
        { .name     = "brk",        .hexret = true,
          .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
-       { .name     = "mmap",       .hexret = true, },
        { .name     = "connect",    .errmsg = true, },
+       { .name     = "eventfd2",   .errmsg = true,
+         .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
        { .name     = "fcntl",      .errmsg = true,
          .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ },
          .arg_parm      = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
@@ -438,6 +555,9 @@ static struct syscall_fmt {
        { .name     = "getitimer",  .errmsg = true,
          .arg_scnprintf = { [0] = SCA_STRARRAY, /* which */ },
          .arg_parm      = { [0] = &strarray__itimers, /* which */ }, },
+       { .name     = "getrlimit",  .errmsg = true,
+         .arg_scnprintf = { [0] = SCA_STRARRAY, /* resource */ },
+         .arg_parm      = { [0] = &strarray__rlimit_resources, /* resource */ }, },
        { .name     = "ioctl",      .errmsg = true,
          .arg_scnprintf = { [2] = SCA_HEX, /* arg */ }, },
        { .name     = "kill",       .errmsg = true,
@@ -470,9 +590,17 @@ static struct syscall_fmt {
        { .name     = "poll",       .errmsg = true, .timeout = true, },
        { .name     = "ppoll",      .errmsg = true, .timeout = true, },
        { .name     = "pread",      .errmsg = true, .alias = "pread64", },
+       { .name     = "prlimit64",  .errmsg = true,
+         .arg_scnprintf = { [1] = SCA_STRARRAY, /* resource */ },
+         .arg_parm      = { [1] = &strarray__rlimit_resources, /* resource */ }, },
        { .name     = "pwrite",     .errmsg = true, .alias = "pwrite64", },
        { .name     = "read",       .errmsg = true, },
-       { .name     = "recvfrom",   .errmsg = true, },
+       { .name     = "recvfrom",   .errmsg = true,
+         .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
+       { .name     = "recvmmsg",   .errmsg = true,
+         .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
+       { .name     = "recvmsg",    .errmsg = true,
+         .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
        { .name     = "rt_sigaction", .errmsg = true,
          .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
        { .name     = "rt_sigprocmask", .errmsg = true,
@@ -483,9 +611,18 @@ static struct syscall_fmt {
        { .name     = "rt_tgsigqueueinfo", .errmsg = true,
          .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
        { .name     = "select",     .errmsg = true, .timeout = true, },
+       { .name     = "sendmmsg",    .errmsg = true,
+         .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
+       { .name     = "sendmsg",    .errmsg = true,
+         .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
+       { .name     = "sendto",     .errmsg = true,
+         .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
        { .name     = "setitimer",  .errmsg = true,
          .arg_scnprintf = { [0] = SCA_STRARRAY, /* which */ },
          .arg_parm      = { [0] = &strarray__itimers, /* which */ }, },
+       { .name     = "setrlimit",  .errmsg = true,
+         .arg_scnprintf = { [0] = SCA_STRARRAY, /* resource */ },
+         .arg_parm      = { [0] = &strarray__rlimit_resources, /* resource */ }, },
        { .name     = "socket",     .errmsg = true,
          .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
                             [1] = SCA_SK_TYPE, /* type */ },
@@ -580,6 +717,7 @@ struct trace {
        struct perf_record_opts opts;
        struct machine          host;
        u64                     base_time;
+       bool                    full_time;
        FILE                    *output;
        unsigned long           nr_events;
        struct strlist          *ev_qualifier;
@@ -588,6 +726,7 @@ struct trace {
        struct intlist          *pid_list;
        bool                    sched;
        bool                    multiple_threads;
+       bool                    show_comm;
        double                  duration_filter;
        double                  runtime_ms;
 };
@@ -617,8 +756,11 @@ static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thre
        size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
        printed += fprintf_duration(duration, fp);
 
-       if (trace->multiple_threads)
+       if (trace->multiple_threads) {
+               if (trace->show_comm)
+                       printed += fprintf(fp, "%.14s/", thread->comm);
                printed += fprintf(fp, "%d ", thread->tid);
+       }
 
        return printed;
 }
@@ -774,6 +916,9 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
                        if (arg.mask & bit)
                                continue;
 
+                       if (args[arg.idx] == 0)
+                               continue;
+
                        printed += scnprintf(bf + printed, size - printed,
                                             "%s%s: ", printed ? ", " : "", field->name);
                        if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
@@ -1022,7 +1167,7 @@ static int trace__process_sample(struct perf_tool *tool,
        if (skip_sample(trace, sample))
                return 0;
 
-       if (trace->base_time == 0)
+       if (!trace->full_time && trace->base_time == 0)
                trace->base_time = sample->time;
 
        if (handler)
@@ -1151,7 +1296,7 @@ again:
                                continue;
                        }
 
-                       if (trace->base_time == 0)
+                       if (!trace->full_time && trace->base_time == 0)
                                trace->base_time = sample.time;
 
                        if (type != PERF_RECORD_SAMPLE) {
@@ -1362,10 +1507,13 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
                        .mmap_pages    = 1024,
                },
                .output = stdout,
+               .show_comm = true,
        };
        const char *output_name = NULL;
        const char *ev_qualifier_str = NULL;
        const struct option trace_options[] = {
+       OPT_BOOLEAN(0, "comm", &trace.show_comm,
+                   "show the thread COMM next to its id"),
        OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
                    "list of events to trace"),
        OPT_STRING('o', "output", &output_name, "file", "output file name"),
@@ -1389,6 +1537,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
                     trace__set_duration),
        OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
        OPT_INCR('v', "verbose", &verbose, "be more verbose"),
+       OPT_BOOLEAN('T', "time", &trace.full_time,
+                   "Show full timestamp, not time relative to first start"),
        OPT_END()
        };
        int err;