perf trace: Only auto set call-graph to "dwarf" when syscalls are being traced
[deliverable/linux.git] / tools / perf / builtin-trace.c
index a4b133fac82bae09a9ce1eee2bf8112ea0294f6f..487c10401d46be23b22c1522b974a4155ce4bceb 100644 (file)
 #include "util/bpf-loader.h"
 #include "callchain.h"
 #include "syscalltbl.h"
+#include "rb_resort.h"
 
 #include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
 #include <stdlib.h>
-#include <linux/futex.h>
 #include <linux/err.h>
-#include <linux/seccomp.h>
 #include <linux/filter.h>
 #include <linux/audit.h>
 #include <sys/ptrace.h>
 # define O_CLOEXEC             02000000
 #endif
 
-#ifndef MSG_CMSG_CLOEXEC
-# define MSG_CMSG_CLOEXEC      0x40000000
-#endif
-
-#ifndef PERF_FLAG_FD_NO_GROUP
-# define PERF_FLAG_FD_NO_GROUP         (1UL << 0)
-#endif
-
-#ifndef PERF_FLAG_FD_OUTPUT
-# define PERF_FLAG_FD_OUTPUT           (1UL << 1)
-#endif
-
-#ifndef PERF_FLAG_PID_CGROUP
-# define PERF_FLAG_PID_CGROUP          (1UL << 2) /* pid=cgroup id, per-cpu mode only */
-#endif
-
-#ifndef PERF_FLAG_FD_CLOEXEC
-# define PERF_FLAG_FD_CLOEXEC          (1UL << 3) /* O_CLOEXEC */
-#endif
-
 struct trace {
        struct perf_tool        tool;
        struct syscalltbl       *sctbl;
@@ -389,80 +368,6 @@ static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
 
 #define SCA_INT syscall_arg__scnprintf_int
 
-static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
-                                          struct syscall_arg *arg)
-{
-       int printed = 0, op = arg->val;
-
-       if (op == 0)
-               return scnprintf(bf, size, "NONE");
-#define        P_CMD(cmd) \
-       if ((op & LOCK_##cmd) == LOCK_##cmd) { \
-               printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
-               op &= ~LOCK_##cmd; \
-       }
-
-       P_CMD(SH);
-       P_CMD(EX);
-       P_CMD(NB);
-       P_CMD(UN);
-       P_CMD(MAND);
-       P_CMD(RW);
-       P_CMD(READ);
-       P_CMD(WRITE);
-#undef P_OP
-
-       if (op)
-               printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
-
-       return printed;
-}
-
-#define SCA_FLOCK syscall_arg__scnprintf_flock
-
-static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
-{
-       enum syscall_futex_args {
-               SCF_UADDR   = (1 << 0),
-               SCF_OP      = (1 << 1),
-               SCF_VAL     = (1 << 2),
-               SCF_TIMEOUT = (1 << 3),
-               SCF_UADDR2  = (1 << 4),
-               SCF_VAL3    = (1 << 5),
-       };
-       int op = arg->val;
-       int cmd = op & FUTEX_CMD_MASK;
-       size_t printed = 0;
-
-       switch (cmd) {
-#define        P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
-       P_FUTEX_OP(WAIT);           arg->mask |= SCF_VAL3|SCF_UADDR2;             break;
-       P_FUTEX_OP(WAKE);           arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
-       P_FUTEX_OP(FD);             arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
-       P_FUTEX_OP(REQUEUE);        arg->mask |= SCF_VAL3|SCF_TIMEOUT;            break;
-       P_FUTEX_OP(CMP_REQUEUE);    arg->mask |= SCF_TIMEOUT;                     break;
-       P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT;                     break;
-       P_FUTEX_OP(WAKE_OP);                                                      break;
-       P_FUTEX_OP(LOCK_PI);        arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
-       P_FUTEX_OP(UNLOCK_PI);      arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
-       P_FUTEX_OP(TRYLOCK_PI);     arg->mask |= SCF_VAL3|SCF_UADDR2;             break;
-       P_FUTEX_OP(WAIT_BITSET);    arg->mask |= SCF_UADDR2;                      break;
-       P_FUTEX_OP(WAKE_BITSET);    arg->mask |= SCF_UADDR2;                      break;
-       P_FUTEX_OP(WAIT_REQUEUE_PI);                                              break;
-       default: printed = scnprintf(bf, size, "%#x", cmd);                       break;
-       }
-
-       if (op & FUTEX_PRIVATE_FLAG)
-               printed += scnprintf(bf + printed, size - printed, "|PRIV");
-
-       if (op & FUTEX_CLOCK_REALTIME)
-               printed += scnprintf(bf + printed, size - printed, "|CLKRT");
-
-       return printed;
-}
-
-#define SCA_FUTEX_OP  syscall_arg__scnprintf_futex_op
-
 static const char *bpf_cmd[] = {
        "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
        "MAP_GET_NEXT_KEY", "PROG_LOAD",
@@ -529,63 +434,6 @@ static const char *socket_families[] = {
 };
 static DEFINE_STRARRAY(socket_families);
 
-#ifndef MSG_PROBE
-#define MSG_PROBE           0x10
-#endif
-#ifndef MSG_WAITFORONE
-#define MSG_WAITFORONE 0x10000
-#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)
 {
@@ -618,90 +466,6 @@ static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
 
 #define SCA_FILENAME syscall_arg__scnprintf_filename
 
-static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
-                                              struct syscall_arg *arg)
-{
-       int printed = 0, flags = arg->val;
-
-       if (!(flags & O_CREAT))
-               arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
-
-       if (flags == 0)
-               return scnprintf(bf, size, "RDONLY");
-#define        P_FLAG(n) \
-       if (flags & O_##n) { \
-               printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
-               flags &= ~O_##n; \
-       }
-
-       P_FLAG(APPEND);
-       P_FLAG(ASYNC);
-       P_FLAG(CLOEXEC);
-       P_FLAG(CREAT);
-       P_FLAG(DIRECT);
-       P_FLAG(DIRECTORY);
-       P_FLAG(EXCL);
-       P_FLAG(LARGEFILE);
-       P_FLAG(NOATIME);
-       P_FLAG(NOCTTY);
-#ifdef O_NONBLOCK
-       P_FLAG(NONBLOCK);
-#elif O_NDELAY
-       P_FLAG(NDELAY);
-#endif
-#ifdef O_PATH
-       P_FLAG(PATH);
-#endif
-       P_FLAG(RDWR);
-#ifdef O_DSYNC
-       if ((flags & O_SYNC) == O_SYNC)
-               printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
-       else {
-               P_FLAG(DSYNC);
-       }
-#else
-       P_FLAG(SYNC);
-#endif
-       P_FLAG(TRUNC);
-       P_FLAG(WRONLY);
-#undef P_FLAG
-
-       if (flags)
-               printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
-
-       return printed;
-}
-
-#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
-
-static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
-                                               struct syscall_arg *arg)
-{
-       int printed = 0, flags = arg->val;
-
-       if (flags == 0)
-               return 0;
-
-#define        P_FLAG(n) \
-       if (flags & PERF_FLAG_##n) { \
-               printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
-               flags &= ~PERF_FLAG_##n; \
-       }
-
-       P_FLAG(FD_NO_GROUP);
-       P_FLAG(FD_OUTPUT);
-       P_FLAG(PID_CGROUP);
-       P_FLAG(FD_CLOEXEC);
-#undef P_FLAG
-
-       if (flags)
-               printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
-
-       return printed;
-}
-
-#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
-
 static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
                                                struct syscall_arg *arg)
 {
@@ -725,59 +489,6 @@ static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
 
 #define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
 
-static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
-{
-       int sig = arg->val;
-
-       switch (sig) {
-#define        P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
-       P_SIGNUM(HUP);
-       P_SIGNUM(INT);
-       P_SIGNUM(QUIT);
-       P_SIGNUM(ILL);
-       P_SIGNUM(TRAP);
-       P_SIGNUM(ABRT);
-       P_SIGNUM(BUS);
-       P_SIGNUM(FPE);
-       P_SIGNUM(KILL);
-       P_SIGNUM(USR1);
-       P_SIGNUM(SEGV);
-       P_SIGNUM(USR2);
-       P_SIGNUM(PIPE);
-       P_SIGNUM(ALRM);
-       P_SIGNUM(TERM);
-       P_SIGNUM(CHLD);
-       P_SIGNUM(CONT);
-       P_SIGNUM(STOP);
-       P_SIGNUM(TSTP);
-       P_SIGNUM(TTIN);
-       P_SIGNUM(TTOU);
-       P_SIGNUM(URG);
-       P_SIGNUM(XCPU);
-       P_SIGNUM(XFSZ);
-       P_SIGNUM(VTALRM);
-       P_SIGNUM(PROF);
-       P_SIGNUM(WINCH);
-       P_SIGNUM(IO);
-       P_SIGNUM(PWR);
-       P_SIGNUM(SYS);
-#ifdef SIGEMT
-       P_SIGNUM(EMT);
-#endif
-#ifdef SIGSTKFLT
-       P_SIGNUM(STKFLT);
-#endif
-#ifdef SIGSWI
-       P_SIGNUM(SWI);
-#endif
-       default: break;
-       }
-
-       return scnprintf(bf, size, "%#x", sig);
-}
-
-#define SCA_SIGNUM syscall_arg__scnprintf_signum
-
 #if defined(__i386__) || defined(__x86_64__)
 /*
  * FIXME: Make this available to all arches.
@@ -805,57 +516,6 @@ static const char *tioctls[] = {
 static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
 #endif /* defined(__i386__) || defined(__x86_64__) */
 
-#ifndef SECCOMP_SET_MODE_STRICT
-#define SECCOMP_SET_MODE_STRICT 0
-#endif
-#ifndef SECCOMP_SET_MODE_FILTER
-#define SECCOMP_SET_MODE_FILTER 1
-#endif
-
-static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg)
-{
-       int op = arg->val;
-       size_t printed = 0;
-
-       switch (op) {
-#define        P_SECCOMP_SET_MODE_OP(n) case SECCOMP_SET_MODE_##n: printed = scnprintf(bf, size, #n); break
-       P_SECCOMP_SET_MODE_OP(STRICT);
-       P_SECCOMP_SET_MODE_OP(FILTER);
-#undef P_SECCOMP_SET_MODE_OP
-       default: printed = scnprintf(bf, size, "%#x", op);                        break;
-       }
-
-       return printed;
-}
-
-#define SCA_SECCOMP_OP  syscall_arg__scnprintf_seccomp_op
-
-#ifndef SECCOMP_FILTER_FLAG_TSYNC
-#define SECCOMP_FILTER_FLAG_TSYNC 1
-#endif
-
-static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size,
-                                                  struct syscall_arg *arg)
-{
-       int printed = 0, flags = arg->val;
-
-#define        P_FLAG(n) \
-       if (flags & SECCOMP_FILTER_FLAG_##n) { \
-               printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
-               flags &= ~SECCOMP_FILTER_FLAG_##n; \
-       }
-
-       P_FLAG(TSYNC);
-#undef P_FLAG
-
-       if (flags)
-               printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
-
-       return printed;
-}
-
-#define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags
-
 #ifndef GRND_NONBLOCK
 #define GRND_NONBLOCK  0x0001
 #endif
@@ -891,10 +551,17 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
          .arg_parm      = { [arg] = &strarray__##array, }
 
 #include "trace/beauty/eventfd.c"
-#include "trace/beauty/pid.c"
+#include "trace/beauty/flock.c"
+#include "trace/beauty/futex_op.c"
 #include "trace/beauty/mmap.c"
 #include "trace/beauty/mode_t.c"
+#include "trace/beauty/msg_flags.c"
+#include "trace/beauty/open_flags.c"
+#include "trace/beauty/perf_event_open.c"
+#include "trace/beauty/pid.c"
 #include "trace/beauty/sched_policy.c"
+#include "trace/beauty/seccomp.c"
+#include "trace/beauty/signum.c"
 #include "trace/beauty/socket_type.c"
 #include "trace/beauty/waitid_options.c"
 
@@ -1086,8 +753,7 @@ static struct syscall_fmt {
                             [1] = SCA_FILENAME, /* filename */
                             [2] = SCA_OPEN_FLAGS, /* flags */ }, },
        { .name     = "perf_event_open", .errmsg = true,
-         .arg_scnprintf = { [1] = SCA_INT, /* pid */
-                            [2] = SCA_INT, /* cpu */
+         .arg_scnprintf = { [2] = SCA_INT, /* cpu */
                             [3] = SCA_FD,  /* group_fd */
                             [4] = SCA_PERF_FLAGS,  /* flags */ }, },
        { .name     = "pipe2",      .errmsg = true,
@@ -1494,6 +1160,24 @@ static int trace__tool_process(struct perf_tool *tool,
        return trace__process_event(trace, machine, event, sample);
 }
 
+static char *trace__machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp)
+{
+       struct machine *machine = vmachine;
+
+       if (machine->kptr_restrict_warned)
+               return NULL;
+
+       if (symbol_conf.kptr_restrict) {
+               pr_warning("Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
+                          "Check /proc/sys/kernel/kptr_restrict.\n\n"
+                          "Kernel samples will not be resolved.\n");
+               machine->kptr_restrict_warned = true;
+               return NULL;
+       }
+
+       return machine__resolve_kernel_addr(vmachine, addrp, modp);
+}
+
 static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
 {
        int err = symbol__init(NULL);
@@ -1505,7 +1189,7 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
        if (trace->host == NULL)
                return -ENOMEM;
 
-       if (trace_event__register_resolver(trace->host, machine__resolve_kernel_addr) < 0)
+       if (trace_event__register_resolver(trace->host, trace__machine__resolve_kernel_addr) < 0)
                return -errno;
 
        err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
@@ -1709,7 +1393,12 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
                                                     "%ld", val);
                        }
                }
-       } else {
+       } else if (IS_ERR(sc->tp_format)) {
+               /*
+                * If we managed to read the tracepoint /format file, then we
+                * may end up not having any args, like with gettid(), so only
+                * print the raw args when we didn't manage to read it.
+                */
                int i = 0;
 
                while (i < 6) {
@@ -1863,7 +1552,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
        if (sc->is_exit) {
                if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
                        trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
-                       fprintf(trace->output, "%-70s\n", ttrace->entry_str);
+                       fprintf(trace->output, "%-70s)\n", ttrace->entry_str);
                }
        } else {
                ttrace->entry_pending = true;
@@ -2888,15 +2577,29 @@ static size_t trace__fprintf_threads_header(FILE *fp)
        return printed;
 }
 
+DEFINE_RESORT_RB(syscall_stats, a->msecs > b->msecs,
+       struct stats    *stats;
+       double          msecs;
+       int             syscall;
+)
+{
+       struct int_node *source = rb_entry(nd, struct int_node, rb_node);
+       struct stats *stats = source->priv;
+
+       entry->syscall = source->i;
+       entry->stats   = stats;
+       entry->msecs   = stats ? (u64)stats->n * (avg_stats(stats) / NSEC_PER_MSEC) : 0;
+}
+
 static size_t thread__dump_stats(struct thread_trace *ttrace,
                                 struct trace *trace, FILE *fp)
 {
-       struct stats *stats;
        size_t printed = 0;
        struct syscall *sc;
-       struct int_node *inode = intlist__first(ttrace->syscall_stats);
+       struct rb_node *nd;
+       DECLARE_RESORT_RB_INTLIST(syscall_stats, ttrace->syscall_stats);
 
-       if (inode == NULL)
+       if (syscall_stats == NULL)
                return 0;
 
        printed += fprintf(fp, "\n");
@@ -2905,9 +2608,8 @@ static size_t thread__dump_stats(struct thread_trace *ttrace,
        printed += fprintf(fp, "                               (msec)    (msec)    (msec)    (msec)        (%%)\n");
        printed += fprintf(fp, "   --------------- -------- --------- --------- --------- ---------     ------\n");
 
-       /* each int_node is a syscall */
-       while (inode) {
-               stats = inode->priv;
+       resort_rb__for_each(nd, syscall_stats) {
+               struct stats *stats = syscall_stats_entry->stats;
                if (stats) {
                        double min = (double)(stats->min) / NSEC_PER_MSEC;
                        double max = (double)(stats->max) / NSEC_PER_MSEC;
@@ -2918,34 +2620,23 @@ static size_t thread__dump_stats(struct thread_trace *ttrace,
                        pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
                        avg /= NSEC_PER_MSEC;
 
-                       sc = &trace->syscalls.table[inode->i];
+                       sc = &trace->syscalls.table[syscall_stats_entry->syscall];
                        printed += fprintf(fp, "   %-15s", sc->name);
                        printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
-                                          n, avg * n, min, avg);
+                                          n, syscall_stats_entry->msecs, min, avg);
                        printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
                }
-
-               inode = intlist__next(inode);
        }
 
+       resort_rb__delete(syscall_stats);
        printed += fprintf(fp, "\n\n");
 
        return printed;
 }
 
-/* struct used to pass data to per-thread function */
-struct summary_data {
-       FILE *fp;
-       struct trace *trace;
-       size_t printed;
-};
-
-static int trace__fprintf_one_thread(struct thread *thread, void *priv)
+static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trace *trace)
 {
-       struct summary_data *data = priv;
-       FILE *fp = data->fp;
-       size_t printed = data->printed;
-       struct trace *trace = data->trace;
+       size_t printed = 0;
        struct thread_trace *ttrace = thread__priv(thread);
        double ratio;
 
@@ -2961,25 +2652,45 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
                printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
        if (ttrace->pfmin)
                printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
-       printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
+       if (trace->sched)
+               printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
+       else if (fputc('\n', fp) != EOF)
+               ++printed;
+
        printed += thread__dump_stats(ttrace, trace, fp);
 
-       data->printed += printed;
+       return printed;
+}
 
-       return 0;
+static unsigned long thread__nr_events(struct thread_trace *ttrace)
+{
+       return ttrace ? ttrace->nr_events : 0;
+}
+
+DEFINE_RESORT_RB(threads, (thread__nr_events(a->thread->priv) < thread__nr_events(b->thread->priv)),
+       struct thread *thread;
+)
+{
+       entry->thread = rb_entry(nd, struct thread, rb_node);
 }
 
 static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
 {
-       struct summary_data data = {
-               .fp = fp,
-               .trace = trace
-       };
-       data.printed = trace__fprintf_threads_header(fp);
+       DECLARE_RESORT_RB_MACHINE_THREADS(threads, trace->host);
+       size_t printed = trace__fprintf_threads_header(fp);
+       struct rb_node *nd;
 
-       machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
+       if (threads == NULL) {
+               fprintf(fp, "%s", "Error sorting output by nr_events!\n");
+               return 0;
+       }
+
+       resort_rb__for_each(nd, threads)
+               printed += trace__fprintf_thread(fp, threads_entry->thread, trace);
 
-       return data.printed;
+       resort_rb__delete(threads);
+
+       return printed;
 }
 
 static int trace__set_duration(const struct option *opt, const char *str,
@@ -3150,7 +2861,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_UINTEGER(0, "max-stack", &trace.max_stack,
                     "Set the maximum stack depth when parsing the callchain, "
                     "anything beyond the specified depth will be ignored. "
-                    "Default: " __stringify(PERF_MAX_STACK_DEPTH)),
+                    "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
        OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
                        "per thread proc mmap processing timeout in ms"),
        OPT_END()
@@ -3194,12 +2905,12 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
                mmap_pages_user_set = false;
 
        if (trace.max_stack == UINT_MAX) {
-               trace.max_stack = PERF_MAX_STACK_DEPTH;
+               trace.max_stack = input_name ? PERF_MAX_STACK_DEPTH : sysctl_perf_event_max_stack;
                max_stack_user_set = false;
        }
 
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
-       if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled)
+       if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled && trace.trace_syscalls)
                record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false);
 #endif
 
This page took 0.035092 seconds and 5 git commands to generate.