]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge branch 'perf/urgent' into perf/core
authorIngo Molnar <mingo@kernel.org>
Wed, 24 Oct 2012 08:20:57 +0000 (10:20 +0200)
committerIngo Molnar <mingo@kernel.org>
Wed, 24 Oct 2012 08:20:57 +0000 (10:20 +0200)
Pick up v3.7-rc2 and fixes before applying more patches.

Signed-off-by: Ingo Molnar <mingo@kernel.org>
33 files changed:
tools/perf/Documentation/android.txt [new file with mode: 0644]
tools/perf/Documentation/perf-diff.txt
tools/perf/Makefile
tools/perf/builtin-annotate.c
tools/perf/builtin-diff.c
tools/perf/builtin-inject.c
tools/perf/builtin-kvm.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-sched.c
tools/perf/builtin-script.c
tools/perf/builtin-test.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/config/feature-tests.mak
tools/perf/perf.c
tools/perf/ui/hist.c
tools/perf/ui/stdio/hist.c
tools/perf/util/build-id.c
tools/perf/util/event.c
tools/perf/util/event.h
tools/perf/util/evlist.c
tools/perf/util/hist.h
tools/perf/util/machine.c [new file with mode: 0644]
tools/perf/util/machine.h [new file with mode: 0644]
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/session.c
tools/perf/util/sort.h
tools/perf/util/thread.c
tools/perf/util/thread.h
tools/perf/util/trace-event-read.c
tools/perf/util/util.c
tools/perf/util/util.h

diff --git a/tools/perf/Documentation/android.txt b/tools/perf/Documentation/android.txt
new file mode 100644 (file)
index 0000000..a39dbbb
--- /dev/null
@@ -0,0 +1,75 @@
+How to compile perf for Android
+=========================================
+
+I. Set the Android NDK environment
+------------------------------------------------
+
+(a). Use the Android NDK
+------------------------------------------------
+1. You need to download and install the Android Native Development Kit (NDK).
+Set the NDK variable to point to the path where you installed the NDK:
+  export NDK=/path/to/android-ndk
+
+2. Set cross-compiling environment variables for NDK toolchain and sysroot.
+For arm:
+  export NDK_TOOLCHAIN=${NDK}/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-
+  export NDK_SYSROOT=${NDK}/platforms/android-9/arch-arm
+For x86:
+  export NDK_TOOLCHAIN=${NDK}/toolchains/x86-4.6/prebuilt/linux-x86/bin/i686-linux-android-
+  export NDK_SYSROOT=${NDK}/platforms/android-9/arch-x86
+
+This method is not working for Android NDK versions up to Revision 8b.
+perf uses some bionic enhancements that are not included in these NDK versions.
+You can use method (b) described below instead.
+
+(b). Use the Android source tree
+-----------------------------------------------
+1. Download the master branch of the Android source tree.
+Set the environment for the target you want using:
+  source build/envsetup.sh
+  lunch
+
+2. Build your own NDK sysroot to contain latest bionic changes and set the
+NDK sysroot environment variable.
+  cd ${ANDROID_BUILD_TOP}/ndk
+For arm:
+  ./build/tools/build-ndk-sysroot.sh --abi=arm
+  export NDK_SYSROOT=${ANDROID_BUILD_TOP}/ndk/build/platforms/android-3/arch-arm
+For x86:
+  ./build/tools/build-ndk-sysroot.sh --abi=x86
+  export NDK_SYSROOT=${ANDROID_BUILD_TOP}/ndk/build/platforms/android-3/arch-x86
+
+3. Set the NDK toolchain environment variable.
+For arm:
+  export NDK_TOOLCHAIN=${ANDROID_TOOLCHAIN}/arm-linux-androideabi-
+For x86:
+  export NDK_TOOLCHAIN=${ANDROID_TOOLCHAIN}/i686-linux-android-
+
+II. Compile perf for Android
+------------------------------------------------
+You need to run make with the NDK toolchain and sysroot defined above:
+  make CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}"
+
+III. Install perf
+-----------------------------------------------
+You need to connect to your Android device/emulator using adb.
+Install perf using:
+  adb push perf /data/perf
+
+If you also want to use perf-archive you need busybox tools for Android.
+For installing perf-archive, you first need to replace #!/bin/bash with #!/system/bin/sh:
+  sed 's/#!\/bin\/bash/#!\/system\/bin\/sh/g' perf-archive >> /tmp/perf-archive
+  chmod +x /tmp/perf-archive
+  adb push /tmp/perf-archive /data/perf-archive
+
+IV. Environment settings for running perf
+------------------------------------------------
+Some perf features need environment variables to run properly.
+You need to set these before running perf on the target:
+  adb shell
+  # PERF_PAGER=cat
+
+IV. Run perf
+------------------------------------------------
+Run perf on your device/emulator to which you previously connected using adb:
+  # ./data/perf
index ab7f667de1b158d290443397696166a573bbb7f4..194f37d635dfa3e543f21a37807f6be61e9e91bc 100644 (file)
@@ -72,6 +72,66 @@ OPTIONS
 --symfs=<directory>::
         Look for files with symbols relative to this directory.
 
+-b::
+--baseline-only::
+        Show only items with match in baseline.
+
+-c::
+--compute::
+        Differential computation selection - delta,ratio,wdiff (default is delta).
+        If '+' is specified as a first character, the output is sorted based
+        on the computation results.
+        See COMPARISON METHODS section for more info.
+
+-p::
+--period::
+        Show period values for both compared hist entries.
+
+-F::
+--formula::
+        Show formula for given computation.
+
+COMPARISON METHODS
+------------------
+delta
+~~~~~
+If specified the 'Delta' column is displayed with value 'd' computed as:
+
+  d = A->period_percent - B->period_percent
+
+with:
+  - A/B being matching hist entry from first/second file specified
+    (or perf.data/perf.data.old) respectively.
+
+  - period_percent being the % of the hist entry period value within
+    single data file
+
+ratio
+~~~~~
+If specified the 'Ratio' column is displayed with value 'r' computed as:
+
+  r = A->period / B->period
+
+with:
+  - A/B being matching hist entry from first/second file specified
+    (or perf.data/perf.data.old) respectively.
+
+  - period being the hist entry period value
+
+wdiff
+~~~~~
+If specified the 'Weighted diff' column is displayed with value 'd' computed as:
+
+   d = B->period * WEIGHT-A - A->period * WEIGHT-B
+
+  - A/B being matching hist entry from first/second file specified
+    (or perf.data/perf.data.old) respectively.
+
+  - period being the hist entry period value
+
+  - WEIGHT-A/WEIGHT-B being user suplied weights in the the '-c' option
+    behind ':' separator like '-c wdiff:1,2'.
+
 SEE ALSO
 --------
 linkperf:perf-record[1]
index 00deed4d61598c5d40d8c607a0da1f42402cefd6..f530502630a411f81fa466228a1359abe9e9648f 100644 (file)
@@ -155,15 +155,15 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
 
 -include config/feature-tests.mak
 
-ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y)
+ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all),y)
        CFLAGS := $(CFLAGS) -fstack-protector-all
 endif
 
-ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wstack-protector),y)
+ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wstack-protector),y)
        CFLAGS := $(CFLAGS) -Wstack-protector
 endif
 
-ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wvolatile-register-var),y)
+ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wvolatile-register-var),y)
        CFLAGS := $(CFLAGS) -Wvolatile-register-var
 endif
 
@@ -172,6 +172,13 @@ endif
 BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 BASIC_LDFLAGS =
 
+ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS)),y)
+       BIONIC := 1
+       EXTLIBS := $(filter-out -lrt,$(EXTLIBS))
+       EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
+       BASIC_CFLAGS += -I.
+endif
+
 # Guard against environment variables
 BUILTIN_OBJS =
 LIB_H =
@@ -303,6 +310,7 @@ LIB_H += util/evlist.h
 LIB_H += util/exec_cmd.h
 LIB_H += util/types.h
 LIB_H += util/levenshtein.h
+LIB_H += util/machine.h
 LIB_H += util/map.h
 LIB_H += util/parse-options.h
 LIB_H += util/parse-events.h
@@ -386,6 +394,7 @@ LIB_OBJS += $(OUTPUT)util/header.o
 LIB_OBJS += $(OUTPUT)util/callchain.o
 LIB_OBJS += $(OUTPUT)util/values.o
 LIB_OBJS += $(OUTPUT)util/debug.o
+LIB_OBJS += $(OUTPUT)util/machine.o
 LIB_OBJS += $(OUTPUT)util/map.o
 LIB_OBJS += $(OUTPUT)util/pstack.o
 LIB_OBJS += $(OUTPUT)util/session.o
@@ -470,12 +479,18 @@ else
 FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
 ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y)
        FLAGS_GLIBC=$(ALL_CFLAGS) $(ALL_LDFLAGS)
-       ifneq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y)
-               msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
-       else
+       ifeq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y)
+               LIBC_SUPPORT := 1
+       endif
+       ifeq ($(BIONIC),1)
+               LIBC_SUPPORT := 1
+       endif
+       ifeq ($(LIBC_SUPPORT),1)
                NO_LIBELF := 1
                NO_DWARF := 1
                NO_DEMANGLE := 1
+       else
+               msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
        endif
 else
        FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
@@ -754,6 +769,12 @@ ifndef NO_STRLCPY
        endif
 endif
 
+ifndef NO_ON_EXIT
+       ifeq ($(call try-cc,$(SOURCE_ON_EXIT),),y)
+               BASIC_CFLAGS += -DHAVE_ON_EXIT
+       endif
+endif
+
 ifndef NO_BACKTRACE
        ifeq ($(call try-cc,$(SOURCE_BACKTRACE),),y)
                BASIC_CFLAGS += -DBACKTRACE_SUPPORT
index 9ea38540b873b5ca02567aeb9114313f96fa6764..690fa9a54657bdfc0f26fe7f6578a08b7f94459e 100644 (file)
@@ -246,7 +246,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
                        .sample = process_sample_event,
                        .mmap   = perf_event__process_mmap,
                        .comm   = perf_event__process_comm,
-                       .fork   = perf_event__process_task,
+                       .exit   = perf_event__process_exit,
+                       .fork   = perf_event__process_fork,
                        .ordered_samples = true,
                        .ordering_requires_timestamps = true,
                },
index a0b531c14b974f24cbbd2727a879c59c69415e06..380683de1df38c3f097b3184d6cc62024c3a7170 100644 (file)
@@ -24,6 +24,228 @@ static char const *input_old = "perf.data.old",
 static char      diff__default_sort_order[] = "dso,symbol";
 static bool  force;
 static bool show_displacement;
+static bool show_period;
+static bool show_formula;
+static bool show_baseline_only;
+static bool sort_compute;
+
+static s64 compute_wdiff_w1;
+static s64 compute_wdiff_w2;
+
+enum {
+       COMPUTE_DELTA,
+       COMPUTE_RATIO,
+       COMPUTE_WEIGHTED_DIFF,
+       COMPUTE_MAX,
+};
+
+const char *compute_names[COMPUTE_MAX] = {
+       [COMPUTE_DELTA] = "delta",
+       [COMPUTE_RATIO] = "ratio",
+       [COMPUTE_WEIGHTED_DIFF] = "wdiff",
+};
+
+static int compute;
+
+static int setup_compute_opt_wdiff(char *opt)
+{
+       char *w1_str = opt;
+       char *w2_str;
+
+       int ret = -EINVAL;
+
+       if (!opt)
+               goto out;
+
+       w2_str = strchr(opt, ',');
+       if (!w2_str)
+               goto out;
+
+       *w2_str++ = 0x0;
+       if (!*w2_str)
+               goto out;
+
+       compute_wdiff_w1 = strtol(w1_str, NULL, 10);
+       compute_wdiff_w2 = strtol(w2_str, NULL, 10);
+
+       if (!compute_wdiff_w1 || !compute_wdiff_w2)
+               goto out;
+
+       pr_debug("compute wdiff w1(%" PRId64 ") w2(%" PRId64 ")\n",
+                 compute_wdiff_w1, compute_wdiff_w2);
+
+       ret = 0;
+
+ out:
+       if (ret)
+               pr_err("Failed: wrong weight data, use 'wdiff:w1,w2'\n");
+
+       return ret;
+}
+
+static int setup_compute_opt(char *opt)
+{
+       if (compute == COMPUTE_WEIGHTED_DIFF)
+               return setup_compute_opt_wdiff(opt);
+
+       if (opt) {
+               pr_err("Failed: extra option specified '%s'", opt);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int setup_compute(const struct option *opt, const char *str,
+                        int unset __maybe_unused)
+{
+       int *cp = (int *) opt->value;
+       char *cstr = (char *) str;
+       char buf[50];
+       unsigned i;
+       char *option;
+
+       if (!str) {
+               *cp = COMPUTE_DELTA;
+               return 0;
+       }
+
+       if (*str == '+') {
+               sort_compute = true;
+               cstr = (char *) ++str;
+               if (!*str)
+                       return 0;
+       }
+
+       option = strchr(str, ':');
+       if (option) {
+               unsigned len = option++ - str;
+
+               /*
+                * The str data are not writeable, so we need
+                * to use another buffer.
+                */
+
+               /* No option value is longer. */
+               if (len >= sizeof(buf))
+                       return -EINVAL;
+
+               strncpy(buf, str, len);
+               buf[len] = 0x0;
+               cstr = buf;
+       }
+
+       for (i = 0; i < COMPUTE_MAX; i++)
+               if (!strcmp(cstr, compute_names[i])) {
+                       *cp = i;
+                       return setup_compute_opt(option);
+               }
+
+       pr_err("Failed: '%s' is not computation method "
+              "(use 'delta','ratio' or 'wdiff')\n", str);
+       return -EINVAL;
+}
+
+static double get_period_percent(struct hist_entry *he, u64 period)
+{
+       u64 total = he->hists->stats.total_period;
+       return (period * 100.0) / total;
+}
+
+double perf_diff__compute_delta(struct hist_entry *he)
+{
+       struct hist_entry *pair = he->pair;
+       double new_percent = get_period_percent(he, he->stat.period);
+       double old_percent = pair ? get_period_percent(pair, pair->stat.period) : 0.0;
+
+       he->diff.period_ratio_delta = new_percent - old_percent;
+       he->diff.computed = true;
+       return he->diff.period_ratio_delta;
+}
+
+double perf_diff__compute_ratio(struct hist_entry *he)
+{
+       struct hist_entry *pair = he->pair;
+       double new_period = he->stat.period;
+       double old_period = pair ? pair->stat.period : 0;
+
+       he->diff.computed = true;
+       he->diff.period_ratio = pair ? (new_period / old_period) : 0;
+       return he->diff.period_ratio;
+}
+
+s64 perf_diff__compute_wdiff(struct hist_entry *he)
+{
+       struct hist_entry *pair = he->pair;
+       u64 new_period = he->stat.period;
+       u64 old_period = pair ? pair->stat.period : 0;
+
+       he->diff.computed = true;
+
+       if (!pair)
+               he->diff.wdiff = 0;
+       else
+               he->diff.wdiff = new_period * compute_wdiff_w2 -
+                                old_period * compute_wdiff_w1;
+
+       return he->diff.wdiff;
+}
+
+static int formula_delta(struct hist_entry *he, char *buf, size_t size)
+{
+       struct hist_entry *pair = he->pair;
+
+       if (!pair)
+               return -1;
+
+       return scnprintf(buf, size,
+                        "(%" PRIu64 " * 100 / %" PRIu64 ") - "
+                        "(%" PRIu64 " * 100 / %" PRIu64 ")",
+                         he->stat.period, he->hists->stats.total_period,
+                         pair->stat.period, pair->hists->stats.total_period);
+}
+
+static int formula_ratio(struct hist_entry *he, char *buf, size_t size)
+{
+       struct hist_entry *pair = he->pair;
+       double new_period = he->stat.period;
+       double old_period = pair ? pair->stat.period : 0;
+
+       if (!pair)
+               return -1;
+
+       return scnprintf(buf, size, "%.0F / %.0F", new_period, old_period);
+}
+
+static int formula_wdiff(struct hist_entry *he, char *buf, size_t size)
+{
+       struct hist_entry *pair = he->pair;
+       u64 new_period = he->stat.period;
+       u64 old_period = pair ? pair->stat.period : 0;
+
+       if (!pair)
+               return -1;
+
+       return scnprintf(buf, size,
+                 "(%" PRIu64 " * " "%" PRId64 ") - (%" PRIu64 " * " "%" PRId64 ")",
+                 new_period, compute_wdiff_w2, old_period, compute_wdiff_w1);
+}
+
+int perf_diff__formula(char *buf, size_t size, struct hist_entry *he)
+{
+       switch (compute) {
+       case COMPUTE_DELTA:
+               return formula_delta(he, buf, size);
+       case COMPUTE_RATIO:
+               return formula_ratio(he, buf, size);
+       case COMPUTE_WEIGHTED_DIFF:
+               return formula_wdiff(he, buf, size);
+       default:
+               BUG_ON(1);
+       }
+
+       return -1;
+}
 
 static int hists__add_entry(struct hists *self,
                            struct addr_location *al, u64 period)
@@ -47,7 +269,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
                return -1;
        }
 
-       if (al.filtered || al.sym == NULL)
+       if (al.filtered)
                return 0;
 
        if (hists__add_entry(&evsel->hists, &al, sample->period)) {
@@ -63,8 +285,8 @@ static struct perf_tool tool = {
        .sample = diff__process_sample_event,
        .mmap   = perf_event__process_mmap,
        .comm   = perf_event__process_comm,
-       .exit   = perf_event__process_task,
-       .fork   = perf_event__process_task,
+       .exit   = perf_event__process_exit,
+       .fork   = perf_event__process_fork,
        .lost   = perf_event__process_lost,
        .ordered_samples = true,
        .ordering_requires_timestamps = true,
@@ -172,6 +394,142 @@ static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name)
        }
 }
 
+static void hists__baseline_only(struct hists *hists)
+{
+       struct rb_node *next = rb_first(&hists->entries);
+
+       while (next != NULL) {
+               struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
+
+               next = rb_next(&he->rb_node);
+               if (!he->pair) {
+                       rb_erase(&he->rb_node, &hists->entries);
+                       hist_entry__free(he);
+               }
+       }
+}
+
+static void hists__precompute(struct hists *hists)
+{
+       struct rb_node *next = rb_first(&hists->entries);
+
+       while (next != NULL) {
+               struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
+
+               next = rb_next(&he->rb_node);
+
+               switch (compute) {
+               case COMPUTE_DELTA:
+                       perf_diff__compute_delta(he);
+                       break;
+               case COMPUTE_RATIO:
+                       perf_diff__compute_ratio(he);
+                       break;
+               case COMPUTE_WEIGHTED_DIFF:
+                       perf_diff__compute_wdiff(he);
+                       break;
+               default:
+                       BUG_ON(1);
+               }
+       }
+}
+
+static int64_t cmp_doubles(double l, double r)
+{
+       if (l > r)
+               return -1;
+       else if (l < r)
+               return 1;
+       else
+               return 0;
+}
+
+static int64_t
+hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
+                       int c)
+{
+       switch (c) {
+       case COMPUTE_DELTA:
+       {
+               double l = left->diff.period_ratio_delta;
+               double r = right->diff.period_ratio_delta;
+
+               return cmp_doubles(l, r);
+       }
+       case COMPUTE_RATIO:
+       {
+               double l = left->diff.period_ratio;
+               double r = right->diff.period_ratio;
+
+               return cmp_doubles(l, r);
+       }
+       case COMPUTE_WEIGHTED_DIFF:
+       {
+               s64 l = left->diff.wdiff;
+               s64 r = right->diff.wdiff;
+
+               return r - l;
+       }
+       default:
+               BUG_ON(1);
+       }
+
+       return 0;
+}
+
+static void insert_hist_entry_by_compute(struct rb_root *root,
+                                        struct hist_entry *he,
+                                        int c)
+{
+       struct rb_node **p = &root->rb_node;
+       struct rb_node *parent = NULL;
+       struct hist_entry *iter;
+
+       while (*p != NULL) {
+               parent = *p;
+               iter = rb_entry(parent, struct hist_entry, rb_node);
+               if (hist_entry__cmp_compute(he, iter, c) < 0)
+                       p = &(*p)->rb_left;
+               else
+                       p = &(*p)->rb_right;
+       }
+
+       rb_link_node(&he->rb_node, parent, p);
+       rb_insert_color(&he->rb_node, root);
+}
+
+static void hists__compute_resort(struct hists *hists)
+{
+       struct rb_root tmp = RB_ROOT;
+       struct rb_node *next = rb_first(&hists->entries);
+
+       while (next != NULL) {
+               struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
+
+               next = rb_next(&he->rb_node);
+
+               rb_erase(&he->rb_node, &hists->entries);
+               insert_hist_entry_by_compute(&tmp, he, compute);
+       }
+
+       hists->entries = tmp;
+}
+
+static void hists__process(struct hists *old, struct hists *new)
+{
+       hists__match(old, new);
+
+       if (show_baseline_only)
+               hists__baseline_only(new);
+
+       if (sort_compute) {
+               hists__precompute(new);
+               hists__compute_resort(new);
+       }
+
+       hists__fprintf(new, true, 0, 0, stdout);
+}
+
 static int __cmd_diff(void)
 {
        int ret, i;
@@ -213,8 +571,7 @@ static int __cmd_diff(void)
 
                first = false;
 
-               hists__match(&evsel_old->hists, &evsel->hists);
-               hists__fprintf(&evsel->hists, true, 0, 0, stdout);
+               hists__process(&evsel_old->hists, &evsel->hists);
        }
 
 out_delete:
@@ -235,6 +592,16 @@ static const struct option options[] = {
                    "be more verbose (show symbol address, etc)"),
        OPT_BOOLEAN('M', "displacement", &show_displacement,
                    "Show position displacement relative to baseline"),
+       OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
+                   "Show only items with match in baseline"),
+       OPT_CALLBACK('c', "compute", &compute,
+                    "delta,ratio,wdiff:w1,w2 (default delta)",
+                    "Entries differential computation selection",
+                    setup_compute),
+       OPT_BOOLEAN('p', "period", &show_period,
+                   "Show period values."),
+       OPT_BOOLEAN('F', "formula", &show_formula,
+                   "Show formula."),
        OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
                    "dump raw trace in ASCII"),
        OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
@@ -263,12 +630,36 @@ static void ui_init(void)
        /* No overhead column. */
        perf_hpp__column_enable(PERF_HPP__OVERHEAD, false);
 
-       /* Display baseline/delta/displacement columns. */
+       /*
+        * Display baseline/delta/ratio/displacement/
+        * formula/periods columns.
+        */
        perf_hpp__column_enable(PERF_HPP__BASELINE, true);
-       perf_hpp__column_enable(PERF_HPP__DELTA, true);
+
+       switch (compute) {
+       case COMPUTE_DELTA:
+               perf_hpp__column_enable(PERF_HPP__DELTA, true);
+               break;
+       case COMPUTE_RATIO:
+               perf_hpp__column_enable(PERF_HPP__RATIO, true);
+               break;
+       case COMPUTE_WEIGHTED_DIFF:
+               perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF, true);
+               break;
+       default:
+               BUG_ON(1);
+       };
 
        if (show_displacement)
                perf_hpp__column_enable(PERF_HPP__DISPL, true);
+
+       if (show_formula)
+               perf_hpp__column_enable(PERF_HPP__FORMULA, true);
+
+       if (show_period) {
+               perf_hpp__column_enable(PERF_HPP__PERIOD, true);
+               perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE, true);
+       }
 }
 
 int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
index 4688bea95c12e4d3dedfb1d12180848aaa8fd725..386a5c0013ffcace497e44c745f23b663c6fed0d 100644 (file)
@@ -102,14 +102,14 @@ static int perf_event__repipe_mmap(struct perf_tool *tool,
        return err;
 }
 
-static int perf_event__repipe_task(struct perf_tool *tool,
+static int perf_event__repipe_fork(struct perf_tool *tool,
                                   union perf_event *event,
                                   struct perf_sample *sample,
                                   struct machine *machine)
 {
        int err;
 
-       err = perf_event__process_task(tool, event, sample, machine);
+       err = perf_event__process_fork(tool, event, sample, machine);
        perf_event__repipe(tool, event, sample, machine);
 
        return err;
@@ -227,7 +227,7 @@ static int __cmd_inject(struct perf_inject *inject)
        if (inject->build_ids) {
                inject->tool.sample       = perf_event__inject_buildid;
                inject->tool.mmap         = perf_event__repipe_mmap;
-               inject->tool.fork         = perf_event__repipe_task;
+               inject->tool.fork         = perf_event__repipe_fork;
                inject->tool.tracing_data = perf_event__repipe_tracing_data;
        }
 
index 260abc535b5b428e817ebaa5a4354fbe67a947e1..836c82f0137176fb05f80bacab5e47c2b726593e 100644 (file)
@@ -313,9 +313,9 @@ struct vcpu_event_record {
 
 static void init_kvm_event_record(struct perf_kvm *kvm)
 {
-       int i;
+       unsigned int i;
 
-       for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++)
+       for (i = 0; i < EVENTS_CACHE_SIZE; i++)
                INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
 }
 
@@ -369,9 +369,10 @@ static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm,
        BUG_ON(key->key == INVALID_KEY);
 
        head = &kvm->kvm_events_cache[kvm_events_hash_fn(key->key)];
-       list_for_each_entry(event, head, hash_entry)
+       list_for_each_entry(event, head, hash_entry) {
                if (event->key.key == key->key && event->key.info == key->info)
                        return event;
+       }
 
        event = kvm_alloc_init_event(key);
        if (!event)
@@ -416,7 +417,10 @@ static double kvm_event_rel_stddev(int vcpu_id, struct kvm_event *event)
 static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
                             u64 time_diff)
 {
-       kvm_update_event_stats(&event->total, time_diff);
+       if (vcpu_id == -1) {
+               kvm_update_event_stats(&event->total, time_diff);
+               return true;
+       }
 
        if (!kvm_event_expand(event, vcpu_id))
                return false;
@@ -432,6 +436,12 @@ static bool handle_end_event(struct perf_kvm *kvm,
 {
        struct kvm_event *event;
        u64 time_begin, time_diff;
+       int vcpu;
+
+       if (kvm->trace_vcpu == -1)
+               vcpu = -1;
+       else
+               vcpu = vcpu_record->vcpu_id;
 
        event = vcpu_record->last_event;
        time_begin = vcpu_record->start_time;
@@ -461,7 +471,7 @@ static bool handle_end_event(struct perf_kvm *kvm,
        BUG_ON(timestamp < time_begin);
 
        time_diff = timestamp - time_begin;
-       return update_kvm_event(event, vcpu_record->vcpu_id, time_diff);
+       return update_kvm_event(event, vcpu, time_diff);
 }
 
 static
@@ -498,6 +508,11 @@ static bool handle_kvm_event(struct perf_kvm *kvm,
        if (!vcpu_record)
                return true;
 
+       /* only process events for vcpus user cares about */
+       if ((kvm->trace_vcpu != -1) &&
+           (kvm->trace_vcpu != vcpu_record->vcpu_id))
+               return true;
+
        if (kvm->events_ops->is_begin_event(evsel, sample, &key))
                return handle_begin_event(kvm, vcpu_record, &key, sample->time);
 
@@ -596,13 +611,15 @@ static void sort_result(struct perf_kvm *kvm)
        int vcpu = kvm->trace_vcpu;
        struct kvm_event *event;
 
-       for (i = 0; i < EVENTS_CACHE_SIZE; i++)
-               list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry)
+       for (i = 0; i < EVENTS_CACHE_SIZE; i++) {
+               list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry) {
                        if (event_is_valid(event, vcpu)) {
                                update_total_count(kvm, event);
                                insert_to_result(&kvm->result, event,
                                                 kvm->compare, vcpu);
                        }
+               }
+       }
 }
 
 /* returns left most element of result, and erase it */
@@ -659,8 +676,8 @@ static void print_result(struct perf_kvm *kvm)
                pr_info("\n");
        }
 
-       pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n",
-               (unsigned long long)kvm->total_count, kvm->total_time / 1e3);
+       pr_info("\nTotal Samples:%" PRIu64 ", Total events handled time:%.2fus.\n\n",
+               kvm->total_count, kvm->total_time / 1e3);
 }
 
 static int process_sample_event(struct perf_tool *tool,
index e9231659754d97ae25d0688c4144d19bffbb1bcd..73b5d7f9119482759be56761f17f01c21226e297 100644 (file)
 #include <sched.h>
 #include <sys/mman.h>
 
+#ifndef HAVE_ON_EXIT
+#ifndef ATEXIT_MAX
+#define ATEXIT_MAX 32
+#endif
+static int __on_exit_count = 0;
+typedef void (*on_exit_func_t) (int, void *);
+static on_exit_func_t __on_exit_funcs[ATEXIT_MAX];
+static void *__on_exit_args[ATEXIT_MAX];
+static int __exitcode = 0;
+static void __handle_on_exit_funcs(void);
+static int on_exit(on_exit_func_t function, void *arg);
+#define exit(x) (exit)(__exitcode = (x))
+
+static int on_exit(on_exit_func_t function, void *arg)
+{
+       if (__on_exit_count == ATEXIT_MAX)
+               return -ENOMEM;
+       else if (__on_exit_count == 0)
+               atexit(__handle_on_exit_funcs);
+       __on_exit_funcs[__on_exit_count] = function;
+       __on_exit_args[__on_exit_count++] = arg;
+       return 0;
+}
+
+static void __handle_on_exit_funcs(void)
+{
+       int i;
+       for (i = 0; i < __on_exit_count; i++)
+               __on_exit_funcs[i] (__exitcode, __on_exit_args[i]);
+}
+#endif
+
 enum write_mode_t {
        WRITE_FORCE,
        WRITE_APPEND
index a61725d89d3ee4188dbe7c4b542c6e1f3685d506..5104a40af5634fb62f0089a81d85e2c73bc2219f 100644 (file)
@@ -556,8 +556,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
                        .sample          = process_sample_event,
                        .mmap            = perf_event__process_mmap,
                        .comm            = perf_event__process_comm,
-                       .exit            = perf_event__process_task,
-                       .fork            = perf_event__process_task,
+                       .exit            = perf_event__process_exit,
+                       .fork            = perf_event__process_fork,
                        .lost            = perf_event__process_lost,
                        .read            = process_read_event,
                        .attr            = perf_event__process_attr,
index 3488ead3b60ce80707493e93f821945bad8a6455..30e53360d3c22e536d66539282d4db1b8736638d 100644 (file)
@@ -1672,7 +1672,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
                        .sample          = perf_sched__process_tracepoint_sample,
                        .comm            = perf_event__process_comm,
                        .lost            = perf_event__process_lost,
-                       .fork            = perf_event__process_task,
+                       .exit            = perf_event__process_exit,
+                       .fork            = perf_event__process_fork,
                        .ordered_samples = true,
                },
                .cmp_pid              = LIST_HEAD_INIT(sched.cmp_pid),
index fb9625083a2ed6d9d4bd25b94bc306895f18d6fc..04ceb0779d399037567cc80b0f97a7e8e131ebc3 100644 (file)
@@ -520,8 +520,8 @@ static struct perf_tool perf_script = {
        .sample          = process_sample_event,
        .mmap            = perf_event__process_mmap,
        .comm            = perf_event__process_comm,
-       .exit            = perf_event__process_task,
-       .fork            = perf_event__process_task,
+       .exit            = perf_event__process_exit,
+       .fork            = perf_event__process_fork,
        .attr            = perf_event__process_attr,
        .event_type      = perf_event__process_event_type,
        .tracing_data    = perf_event__process_tracing_data,
index 484f26cc0c00c6ee80d74e93bddc3fe24eae4c1f..e2d9872de3d78144b89bdadfb0a0bf9b06e38b43 100644 (file)
@@ -35,7 +35,6 @@ static int test__vmlinux_matches_kallsyms(void)
        struct map *kallsyms_map, *vmlinux_map;
        struct machine kallsyms, vmlinux;
        enum map_type type = MAP__FUNCTION;
-       long page_size = sysconf(_SC_PAGE_SIZE);
        struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", };
 
        /*
@@ -1007,7 +1006,6 @@ static void segfault_handler(int sig __maybe_unused,
 
 static int __test__rdpmc(void)
 {
-       long page_size = sysconf(_SC_PAGE_SIZE);
        volatile int tmp = 0;
        u64 i, loops = 1000;
        int n;
index ff6db8086805e68caa29e2b232ae0d271dc7b47a..fb9da71eba1f63fdcd9e4a8fcbb20ac62f7ed107 100644 (file)
@@ -26,6 +26,7 @@
 #include "util/color.h"
 #include "util/evlist.h"
 #include "util/evsel.h"
+#include "util/machine.h"
 #include "util/session.h"
 #include "util/symbol.h"
 #include "util/thread.h"
@@ -871,7 +872,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
                                                   &sample, machine);
                } else if (event->header.type < PERF_RECORD_MAX) {
                        hists__inc_nr_events(&evsel->hists, event->header.type);
-                       perf_event__process(&top->tool, event, &sample, machine);
+                       machine__process_event(machine, event);
                } else
                        ++session->hists.stats.nr_unknown_events;
        }
index 7aaee39f6774f1fc49131dd7a3d67f002bee823c..14b322961807eac9d7a5626a89f882a108d9f5e5 100644 (file)
@@ -52,6 +52,13 @@ struct trace {
        struct perf_record_opts opts;
 };
 
+static bool done = false;
+
+static void sig_handler(int sig __maybe_unused)
+{
+       done = true;
+}
+
 static int trace__read_syscall_info(struct trace *trace, int id)
 {
        char tp_name[128];
@@ -190,11 +197,12 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
        return 0;
 }
 
-static int trace__run(struct trace *trace)
+static int trace__run(struct trace *trace, int argc, const char **argv)
 {
        struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
        struct perf_evsel *evsel;
        int err = -1, i, nr_events = 0, before;
+       const bool forks = argc > 0;
 
        if (evlist == NULL) {
                printf("Not enough memory to run!\n");
@@ -215,6 +223,17 @@ static int trace__run(struct trace *trace)
 
        perf_evlist__config_attrs(evlist, &trace->opts);
 
+       signal(SIGCHLD, sig_handler);
+       signal(SIGINT, sig_handler);
+
+       if (forks) {
+               err = perf_evlist__prepare_workload(evlist, &trace->opts, argv);
+               if (err < 0) {
+                       printf("Couldn't run the workload!\n");
+                       goto out_delete_evlist;
+               }
+       }
+
        err = perf_evlist__open(evlist);
        if (err < 0) {
                printf("Couldn't create the events: %s\n", strerror(errno));
@@ -228,6 +247,10 @@ static int trace__run(struct trace *trace)
        }
 
        perf_evlist__enable(evlist);
+
+       if (forks)
+               perf_evlist__start_workload(evlist);
+
 again:
        before = nr_events;
 
@@ -280,8 +303,15 @@ static int trace__run(struct trace *trace)
                }
        }
 
-       if (nr_events == before)
+       if (nr_events == before) {
+               if (done)
+                       goto out_delete_evlist;
+
                poll(evlist->pollfd, evlist->nr_fds, -1);
+       }
+
+       if (done)
+               perf_evlist__disable(evlist);
 
        goto again;
 
@@ -294,7 +324,8 @@ static int trace__run(struct trace *trace)
 int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        const char * const trace_usage[] = {
-               "perf trace [<options>]",
+               "perf trace [<options>] [<command>]",
+               "perf trace [<options>] -- <command> [<options>]",
                NULL
        };
        struct trace trace = {
@@ -331,18 +362,26 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_END()
        };
        int err;
+       char bf[BUFSIZ];
 
        argc = parse_options(argc, argv, trace_options, trace_usage, 0);
-       if (argc)
-               usage_with_options(trace_usage, trace_options);
+
+       err = perf_target__validate(&trace.opts.target);
+       if (err) {
+               perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
+               printf("%s", bf);
+               return err;
+       }
 
        err = perf_target__parse_uid(&trace.opts.target);
        if (err) {
-               char bf[BUFSIZ];
                perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
                printf("%s", bf);
                return err;
        }
 
-       return trace__run(&trace);
+       if (!argc && perf_target__none(&trace.opts.target))
+               trace.opts.target.system_wide = true;
+
+       return trace__run(&trace, argc, argv);
 }
index 4add41bb0c7eeca264353ffa60603651c0051503..3ef5ec9cdff8ca750bb5864a4fd475c9dd389ee6 100644 (file)
@@ -43,6 +43,15 @@ int main(void)
 }
 endef
 
+define SOURCE_BIONIC
+#include <android/api-level.h>
+
+int main(void)
+{
+       return __ANDROID_API__;
+}
+endef
+
 define SOURCE_ELF_MMAP
 #include <libelf.h>
 int main(void)
@@ -203,4 +212,13 @@ int main(void)
        return audit_open();
 }
 endef
-endif
\ No newline at end of file
+endif
+
+define SOURCE_ON_EXIT
+#include <stdio.h>
+
+int main(void)
+{
+       return on_exit(NULL, NULL);
+}
+endef
index 6d50eb0b425196aea150f699cd97ae09b8840ab8..d480d8a412b88addb457f580b5d0fa0160604d77 100644 (file)
@@ -440,6 +440,8 @@ int main(int argc, const char **argv)
 {
        const char *cmd;
 
+       page_size = sysconf(_SC_PAGE_SIZE);
+
        cmd = perf_extract_argv0_path(argv[0]);
        if (!cmd)
                cmd = "perf-help";
index f5a1e4f65263fa0c03468bde22e49364b0ba2c2f..4f5f4756faacdb6e5d1638d4b876655b2116823f 100644 (file)
@@ -179,7 +179,10 @@ static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
 {
        double percent = baseline_percent(he);
 
-       return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
+       if (he->pair)
+               return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
+       else
+               return scnprintf(hpp->buf, hpp->size, "        ");
 }
 
 static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
@@ -187,7 +190,10 @@ static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
        double percent = baseline_percent(he);
        const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
 
-       return scnprintf(hpp->buf, hpp->size, fmt, percent);
+       if (he->pair || symbol_conf.field_sep)
+               return scnprintf(hpp->buf, hpp->size, fmt, percent);
+       else
+               return scnprintf(hpp->buf, hpp->size, "            ");
 }
 
 static int hpp__header_samples(struct perf_hpp *hpp)
@@ -228,6 +234,26 @@ static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
        return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period);
 }
 
+static int hpp__header_period_baseline(struct perf_hpp *hpp)
+{
+       const char *fmt = symbol_conf.field_sep ? "%s" : "%12s";
+
+       return scnprintf(hpp->buf, hpp->size, fmt, "Period Base");
+}
+
+static int hpp__width_period_baseline(struct perf_hpp *hpp __maybe_unused)
+{
+       return 12;
+}
+
+static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *he)
+{
+       struct hist_entry *pair = he->pair;
+       u64 period = pair ? pair->stat.period : 0;
+       const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
+
+       return scnprintf(hpp->buf, hpp->size, fmt, period);
+}
 static int hpp__header_delta(struct perf_hpp *hpp)
 {
        const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
@@ -242,30 +268,79 @@ static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)
 
 static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
 {
-       struct hist_entry *pair = he->pair;
-       struct hists *pair_hists = pair ? pair->hists : NULL;
-       struct hists *hists = he->hists;
-       u64 old_total, new_total;
-       double old_percent = 0, new_percent = 0;
-       double diff;
        const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
        char buf[32] = " ";
+       double diff;
 
-       old_total = pair_hists ? pair_hists->stats.total_period : 0;
-       if (old_total > 0 && pair)
-               old_percent = 100.0 * pair->stat.period / old_total;
-
-       new_total = hists->stats.total_period;
-       if (new_total > 0)
-               new_percent = 100.0 * he->stat.period / new_total;
+       if (he->diff.computed)
+               diff = he->diff.period_ratio_delta;
+       else
+               diff = perf_diff__compute_delta(he);
 
-       diff = new_percent - old_percent;
        if (fabs(diff) >= 0.01)
                scnprintf(buf, sizeof(buf), "%+4.2F%%", diff);
 
        return scnprintf(hpp->buf, hpp->size, fmt, buf);
 }
 
+static int hpp__header_ratio(struct perf_hpp *hpp)
+{
+       const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
+
+       return scnprintf(hpp->buf, hpp->size, fmt, "Ratio");
+}
+
+static int hpp__width_ratio(struct perf_hpp *hpp __maybe_unused)
+{
+       return 14;
+}
+
+static int hpp__entry_ratio(struct perf_hpp *hpp, struct hist_entry *he)
+{
+       const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
+       char buf[32] = " ";
+       double ratio;
+
+       if (he->diff.computed)
+               ratio = he->diff.period_ratio;
+       else
+               ratio = perf_diff__compute_ratio(he);
+
+       if (ratio > 0.0)
+               scnprintf(buf, sizeof(buf), "%+14.6F", ratio);
+
+       return scnprintf(hpp->buf, hpp->size, fmt, buf);
+}
+
+static int hpp__header_wdiff(struct perf_hpp *hpp)
+{
+       const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
+
+       return scnprintf(hpp->buf, hpp->size, fmt, "Weighted diff");
+}
+
+static int hpp__width_wdiff(struct perf_hpp *hpp __maybe_unused)
+{
+       return 14;
+}
+
+static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he)
+{
+       const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
+       char buf[32] = " ";
+       s64 wdiff;
+
+       if (he->diff.computed)
+               wdiff = he->diff.wdiff;
+       else
+               wdiff = perf_diff__compute_wdiff(he);
+
+       if (wdiff != 0)
+               scnprintf(buf, sizeof(buf), "%14ld", wdiff);
+
+       return scnprintf(hpp->buf, hpp->size, fmt, buf);
+}
+
 static int hpp__header_displ(struct perf_hpp *hpp)
 {
        return scnprintf(hpp->buf, hpp->size, "Displ.");
@@ -290,6 +365,27 @@ static int hpp__entry_displ(struct perf_hpp *hpp,
        return scnprintf(hpp->buf, hpp->size, fmt, buf);
 }
 
+static int hpp__header_formula(struct perf_hpp *hpp)
+{
+       const char *fmt = symbol_conf.field_sep ? "%s" : "%70s";
+
+       return scnprintf(hpp->buf, hpp->size, fmt, "Formula");
+}
+
+static int hpp__width_formula(struct perf_hpp *hpp __maybe_unused)
+{
+       return 70;
+}
+
+static int hpp__entry_formula(struct perf_hpp *hpp, struct hist_entry *he)
+{
+       const char *fmt = symbol_conf.field_sep ? "%s" : "%-70s";
+       char buf[96] = " ";
+
+       perf_diff__formula(buf, sizeof(buf), he);
+       return scnprintf(hpp->buf, hpp->size, fmt, buf);
+}
+
 #define HPP__COLOR_PRINT_FNS(_name)            \
        .header = hpp__header_ ## _name,                \
        .width  = hpp__width_ ## _name,         \
@@ -310,8 +406,12 @@ struct perf_hpp_fmt perf_hpp__format[] = {
        { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_us) },
        { .cond = false, HPP__PRINT_FNS(samples) },
        { .cond = false, HPP__PRINT_FNS(period) },
+       { .cond = false, HPP__PRINT_FNS(period_baseline) },
        { .cond = false, HPP__PRINT_FNS(delta) },
-       { .cond = false, HPP__PRINT_FNS(displ) }
+       { .cond = false, HPP__PRINT_FNS(ratio) },
+       { .cond = false, HPP__PRINT_FNS(wdiff) },
+       { .cond = false, HPP__PRINT_FNS(displ) },
+       { .cond = false, HPP__PRINT_FNS(formula) }
 };
 
 #undef HPP__COLOR_PRINT_FNS
index fbd4e32d07437280623cf913acfbb35583fdc1be..f0ee204f99bb4bffddedd7434d276f05d98cfb9c 100644 (file)
@@ -342,7 +342,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
        const char *sep = symbol_conf.field_sep;
        const char *col_width = symbol_conf.col_width_list_str;
        int idx, nr_rows = 0;
-       char bf[64];
+       char bf[96];
        struct perf_hpp dummy_hpp = {
                .buf    = bf,
                .size   = sizeof(bf),
index 8e3a740ddbd4eed2059aa08d8d7592fea4075833..6a6399955ef2ddee6b163e0a8e1f2c18dfda250b 100644 (file)
@@ -64,7 +64,7 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
 struct perf_tool build_id__mark_dso_hit_ops = {
        .sample = build_id__mark_dso_hit,
        .mmap   = perf_event__process_mmap,
-       .fork   = perf_event__process_task,
+       .fork   = perf_event__process_fork,
        .exit   = perf_event__exit_del_thread,
        .attr            = perf_event__process_attr,
        .build_id        = perf_event__process_build_id,
index 6715b19387258cd184bba45d88a00e76eaebbeba..0ae444ef1429939e5fbc7891ac65485eb5bb4c50 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/types.h>
 #include "event.h"
 #include "debug.h"
+#include "machine.h"
 #include "sort.h"
 #include "string.h"
 #include "strlist.h"
@@ -519,134 +520,15 @@ int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
                             struct perf_sample *sample __maybe_unused,
                             struct machine *machine)
 {
-       struct thread *thread = machine__findnew_thread(machine, event->comm.tid);
-
-       if (dump_trace)
-               perf_event__fprintf_comm(event, stdout);
-
-       if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
-               dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
-               return -1;
-       }
-
-       return 0;
+       return machine__process_comm_event(machine, event);
 }
 
 int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
                             union perf_event *event,
                             struct perf_sample *sample __maybe_unused,
-                            struct machine *machine __maybe_unused)
-{
-       dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
-                   event->lost.id, event->lost.lost);
-       return 0;
-}
-
-static void perf_event__set_kernel_mmap_len(union perf_event *event,
-                                           struct map **maps)
+                            struct machine *machine)
 {
-       maps[MAP__FUNCTION]->start = event->mmap.start;
-       maps[MAP__FUNCTION]->end   = event->mmap.start + event->mmap.len;
-       /*
-        * Be a bit paranoid here, some perf.data file came with
-        * a zero sized synthesized MMAP event for the kernel.
-        */
-       if (maps[MAP__FUNCTION]->end == 0)
-               maps[MAP__FUNCTION]->end = ~0ULL;
-}
-
-static int perf_event__process_kernel_mmap(struct perf_tool *tool
-                                          __maybe_unused,
-                                          union perf_event *event,
-                                          struct machine *machine)
-{
-       struct map *map;
-       char kmmap_prefix[PATH_MAX];
-       enum dso_kernel_type kernel_type;
-       bool is_kernel_mmap;
-
-       machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
-       if (machine__is_host(machine))
-               kernel_type = DSO_TYPE_KERNEL;
-       else
-               kernel_type = DSO_TYPE_GUEST_KERNEL;
-
-       is_kernel_mmap = memcmp(event->mmap.filename,
-                               kmmap_prefix,
-                               strlen(kmmap_prefix) - 1) == 0;
-       if (event->mmap.filename[0] == '/' ||
-           (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
-
-               char short_module_name[1024];
-               char *name, *dot;
-
-               if (event->mmap.filename[0] == '/') {
-                       name = strrchr(event->mmap.filename, '/');
-                       if (name == NULL)
-                               goto out_problem;
-
-                       ++name; /* skip / */
-                       dot = strrchr(name, '.');
-                       if (dot == NULL)
-                               goto out_problem;
-                       snprintf(short_module_name, sizeof(short_module_name),
-                                       "[%.*s]", (int)(dot - name), name);
-                       strxfrchar(short_module_name, '-', '_');
-               } else
-                       strcpy(short_module_name, event->mmap.filename);
-
-               map = machine__new_module(machine, event->mmap.start,
-                                         event->mmap.filename);
-               if (map == NULL)
-                       goto out_problem;
-
-               name = strdup(short_module_name);
-               if (name == NULL)
-                       goto out_problem;
-
-               map->dso->short_name = name;
-               map->dso->sname_alloc = 1;
-               map->end = map->start + event->mmap.len;
-       } else if (is_kernel_mmap) {
-               const char *symbol_name = (event->mmap.filename +
-                               strlen(kmmap_prefix));
-               /*
-                * Should be there already, from the build-id table in
-                * the header.
-                */
-               struct dso *kernel = __dsos__findnew(&machine->kernel_dsos,
-                                                    kmmap_prefix);
-               if (kernel == NULL)
-                       goto out_problem;
-
-               kernel->kernel = kernel_type;
-               if (__machine__create_kernel_maps(machine, kernel) < 0)
-                       goto out_problem;
-
-               perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps);
-
-               /*
-                * Avoid using a zero address (kptr_restrict) for the ref reloc
-                * symbol. Effectively having zero here means that at record
-                * time /proc/sys/kernel/kptr_restrict was non zero.
-                */
-               if (event->mmap.pgoff != 0) {
-                       maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
-                                                        symbol_name,
-                                                        event->mmap.pgoff);
-               }
-
-               if (machine__is_default_guest(machine)) {
-                       /*
-                        * preload dso of guest kernel and modules
-                        */
-                       dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION],
-                                 NULL);
-               }
-       }
-       return 0;
-out_problem:
-       return -1;
+       return machine__process_lost_event(machine, event);
 }
 
 size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
@@ -656,43 +538,12 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
                       event->mmap.len, event->mmap.pgoff, event->mmap.filename);
 }
 
-int perf_event__process_mmap(struct perf_tool *tool,
+int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
                             union perf_event *event,
                             struct perf_sample *sample __maybe_unused,
                             struct machine *machine)
 {
-       struct thread *thread;
-       struct map *map;
-       u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
-       int ret = 0;
-
-       if (dump_trace)
-               perf_event__fprintf_mmap(event, stdout);
-
-       if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
-           cpumode == PERF_RECORD_MISC_KERNEL) {
-               ret = perf_event__process_kernel_mmap(tool, event, machine);
-               if (ret < 0)
-                       goto out_problem;
-               return 0;
-       }
-
-       thread = machine__findnew_thread(machine, event->mmap.pid);
-       if (thread == NULL)
-               goto out_problem;
-       map = map__new(&machine->user_dsos, event->mmap.start,
-                       event->mmap.len, event->mmap.pgoff,
-                       event->mmap.pid, event->mmap.filename,
-                       MAP__FUNCTION);
-       if (map == NULL)
-               goto out_problem;
-
-       thread__insert_map(thread, map);
-       return 0;
-
-out_problem:
-       dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
-       return 0;
+       return machine__process_mmap_event(machine, event);
 }
 
 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
@@ -702,29 +553,20 @@ size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
                       event->fork.ppid, event->fork.ptid);
 }
 
-int perf_event__process_task(struct perf_tool *tool __maybe_unused,
+int perf_event__process_fork(struct perf_tool *tool __maybe_unused,
                             union perf_event *event,
                             struct perf_sample *sample __maybe_unused,
-                             struct machine *machine)
+                            struct machine *machine)
 {
-       struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
-       struct thread *parent = machine__findnew_thread(machine, event->fork.ptid);
-
-       if (dump_trace)
-               perf_event__fprintf_task(event, stdout);
-
-       if (event->header.type == PERF_RECORD_EXIT) {
-               machine__remove_thread(machine, thread);
-               return 0;
-       }
-
-       if (thread == NULL || parent == NULL ||
-           thread__fork(thread, parent) < 0) {
-               dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
-               return -1;
-       }
+       return machine__process_fork_event(machine, event);
+}
 
-       return 0;
+int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
+                            union perf_event *event,
+                            struct perf_sample *sample __maybe_unused,
+                            struct machine *machine)
+{
+       return machine__process_exit_event(machine, event);
 }
 
 size_t perf_event__fprintf(union perf_event *event, FILE *fp)
@@ -750,27 +592,12 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
        return ret;
 }
 
-int perf_event__process(struct perf_tool *tool, union perf_event *event,
-                       struct perf_sample *sample, struct machine *machine)
+int perf_event__process(struct perf_tool *tool __maybe_unused,
+                       union perf_event *event,
+                       struct perf_sample *sample __maybe_unused,
+                       struct machine *machine)
 {
-       switch (event->header.type) {
-       case PERF_RECORD_COMM:
-               perf_event__process_comm(tool, event, sample, machine);
-               break;
-       case PERF_RECORD_MMAP:
-               perf_event__process_mmap(tool, event, sample, machine);
-               break;
-       case PERF_RECORD_FORK:
-       case PERF_RECORD_EXIT:
-               perf_event__process_task(tool, event, sample, machine);
-               break;
-       case PERF_RECORD_LOST:
-               perf_event__process_lost(tool, event, sample, machine);
-       default:
-               break;
-       }
-
-       return 0;
+       return machine__process_event(machine, event);
 }
 
 void thread__find_addr_map(struct thread *self,
index 21b99e741a87c016ab383d683492dfd2aa2017b9..da97aff5bd7592222a7656825f96538eec911361 100644 (file)
@@ -191,7 +191,11 @@ int perf_event__process_mmap(struct perf_tool *tool,
                             union perf_event *event,
                             struct perf_sample *sample,
                             struct machine *machine);
-int perf_event__process_task(struct perf_tool *tool,
+int perf_event__process_fork(struct perf_tool *tool,
+                            union perf_event *event,
+                            struct perf_sample *sample,
+                            struct machine *machine);
+int perf_event__process_exit(struct perf_tool *tool,
                             union perf_event *event,
                             struct perf_sample *sample,
                             struct machine *machine);
index 186b87730396712d6fbfcbc95837168b81287ca4..a41dc4a5c2deeeefbe4794ebd9774e517c3363db 100644 (file)
@@ -325,8 +325,6 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
 
 union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
 {
-       /* XXX Move this to perf.c, making it generally available */
-       unsigned int page_size = sysconf(_SC_PAGE_SIZE);
        struct perf_mmap *md = &evlist->mmap[idx];
        unsigned int head = perf_mmap__read_head(md);
        unsigned int old = md->prev;
@@ -528,7 +526,6 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, in
 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
                      bool overwrite)
 {
-       unsigned int page_size = sysconf(_SC_PAGE_SIZE);
        struct perf_evsel *evsel;
        const struct cpu_map *cpus = evlist->cpus;
        const struct thread_map *threads = evlist->threads;
index 66cb31fe81d2a7c3b7a45e925a5fc6d3cb7a4e63..c751624d415308fb51457a365baffb779f577397 100644 (file)
@@ -140,8 +140,12 @@ enum {
        PERF_HPP__OVERHEAD_GUEST_US,
        PERF_HPP__SAMPLES,
        PERF_HPP__PERIOD,
+       PERF_HPP__PERIOD_BASELINE,
        PERF_HPP__DELTA,
+       PERF_HPP__RATIO,
+       PERF_HPP__WEIGHTED_DIFF,
        PERF_HPP__DISPL,
+       PERF_HPP__FORMULA,
 
        PERF_HPP__MAX_INDEX
 };
@@ -204,4 +208,8 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
 
 unsigned int hists__sort_list_width(struct hists *self);
 
+double perf_diff__compute_delta(struct hist_entry *he);
+double perf_diff__compute_ratio(struct hist_entry *he);
+s64 perf_diff__compute_wdiff(struct hist_entry *he);
+int perf_diff__formula(char *buf, size_t size, struct hist_entry *he);
 #endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
new file mode 100644 (file)
index 0000000..502eec0
--- /dev/null
@@ -0,0 +1,277 @@
+#include "debug.h"
+#include "event.h"
+#include "machine.h"
+#include "map.h"
+#include "thread.h"
+#include <stdbool.h>
+
+static struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid,
+                                               bool create)
+{
+       struct rb_node **p = &machine->threads.rb_node;
+       struct rb_node *parent = NULL;
+       struct thread *th;
+
+       /*
+        * Font-end cache - PID lookups come in blocks,
+        * so most of the time we dont have to look up
+        * the full rbtree:
+        */
+       if (machine->last_match && machine->last_match->pid == pid)
+               return machine->last_match;
+
+       while (*p != NULL) {
+               parent = *p;
+               th = rb_entry(parent, struct thread, rb_node);
+
+               if (th->pid == pid) {
+                       machine->last_match = th;
+                       return th;
+               }
+
+               if (pid < th->pid)
+                       p = &(*p)->rb_left;
+               else
+                       p = &(*p)->rb_right;
+       }
+
+       if (!create)
+               return NULL;
+
+       th = thread__new(pid);
+       if (th != NULL) {
+               rb_link_node(&th->rb_node, parent, p);
+               rb_insert_color(&th->rb_node, &machine->threads);
+               machine->last_match = th;
+       }
+
+       return th;
+}
+
+struct thread *machine__findnew_thread(struct machine *machine, pid_t pid)
+{
+       return __machine__findnew_thread(machine, pid, true);
+}
+
+struct thread *machine__find_thread(struct machine *machine, pid_t pid)
+{
+       return __machine__findnew_thread(machine, pid, false);
+}
+
+int machine__process_comm_event(struct machine *machine, union perf_event *event)
+{
+       struct thread *thread = machine__findnew_thread(machine, event->comm.tid);
+
+       if (dump_trace)
+               perf_event__fprintf_comm(event, stdout);
+
+       if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
+               dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+int machine__process_lost_event(struct machine *machine __maybe_unused,
+                               union perf_event *event)
+{
+       dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
+                   event->lost.id, event->lost.lost);
+       return 0;
+}
+
+static void machine__set_kernel_mmap_len(struct machine *machine,
+                                        union perf_event *event)
+{
+       machine->vmlinux_maps[MAP__FUNCTION]->start = event->mmap.start;
+       machine->vmlinux_maps[MAP__FUNCTION]->end   = (event->mmap.start +
+                                                      event->mmap.len);
+       /*
+        * Be a bit paranoid here, some perf.data file came with
+        * a zero sized synthesized MMAP event for the kernel.
+        */
+       if (machine->vmlinux_maps[MAP__FUNCTION]->end == 0)
+               machine->vmlinux_maps[MAP__FUNCTION]->end = ~0ULL;
+}
+
+static int machine__process_kernel_mmap_event(struct machine *machine,
+                                             union perf_event *event)
+{
+       struct map *map;
+       char kmmap_prefix[PATH_MAX];
+       enum dso_kernel_type kernel_type;
+       bool is_kernel_mmap;
+
+       machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
+       if (machine__is_host(machine))
+               kernel_type = DSO_TYPE_KERNEL;
+       else
+               kernel_type = DSO_TYPE_GUEST_KERNEL;
+
+       is_kernel_mmap = memcmp(event->mmap.filename,
+                               kmmap_prefix,
+                               strlen(kmmap_prefix) - 1) == 0;
+       if (event->mmap.filename[0] == '/' ||
+           (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
+
+               char short_module_name[1024];
+               char *name, *dot;
+
+               if (event->mmap.filename[0] == '/') {
+                       name = strrchr(event->mmap.filename, '/');
+                       if (name == NULL)
+                               goto out_problem;
+
+                       ++name; /* skip / */
+                       dot = strrchr(name, '.');
+                       if (dot == NULL)
+                               goto out_problem;
+                       snprintf(short_module_name, sizeof(short_module_name),
+                                       "[%.*s]", (int)(dot - name), name);
+                       strxfrchar(short_module_name, '-', '_');
+               } else
+                       strcpy(short_module_name, event->mmap.filename);
+
+               map = machine__new_module(machine, event->mmap.start,
+                                         event->mmap.filename);
+               if (map == NULL)
+                       goto out_problem;
+
+               name = strdup(short_module_name);
+               if (name == NULL)
+                       goto out_problem;
+
+               map->dso->short_name = name;
+               map->dso->sname_alloc = 1;
+               map->end = map->start + event->mmap.len;
+       } else if (is_kernel_mmap) {
+               const char *symbol_name = (event->mmap.filename +
+                               strlen(kmmap_prefix));
+               /*
+                * Should be there already, from the build-id table in
+                * the header.
+                */
+               struct dso *kernel = __dsos__findnew(&machine->kernel_dsos,
+                                                    kmmap_prefix);
+               if (kernel == NULL)
+                       goto out_problem;
+
+               kernel->kernel = kernel_type;
+               if (__machine__create_kernel_maps(machine, kernel) < 0)
+                       goto out_problem;
+
+               machine__set_kernel_mmap_len(machine, event);
+
+               /*
+                * Avoid using a zero address (kptr_restrict) for the ref reloc
+                * symbol. Effectively having zero here means that at record
+                * time /proc/sys/kernel/kptr_restrict was non zero.
+                */
+               if (event->mmap.pgoff != 0) {
+                       maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
+                                                        symbol_name,
+                                                        event->mmap.pgoff);
+               }
+
+               if (machine__is_default_guest(machine)) {
+                       /*
+                        * preload dso of guest kernel and modules
+                        */
+                       dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION],
+                                 NULL);
+               }
+       }
+       return 0;
+out_problem:
+       return -1;
+}
+
+int machine__process_mmap_event(struct machine *machine, union perf_event *event)
+{
+       u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+       struct thread *thread;
+       struct map *map;
+       int ret = 0;
+
+       if (dump_trace)
+               perf_event__fprintf_mmap(event, stdout);
+
+       if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
+           cpumode == PERF_RECORD_MISC_KERNEL) {
+               ret = machine__process_kernel_mmap_event(machine, event);
+               if (ret < 0)
+                       goto out_problem;
+               return 0;
+       }
+
+       thread = machine__findnew_thread(machine, event->mmap.pid);
+       if (thread == NULL)
+               goto out_problem;
+       map = map__new(&machine->user_dsos, event->mmap.start,
+                       event->mmap.len, event->mmap.pgoff,
+                       event->mmap.pid, event->mmap.filename,
+                       MAP__FUNCTION);
+       if (map == NULL)
+               goto out_problem;
+
+       thread__insert_map(thread, map);
+       return 0;
+
+out_problem:
+       dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
+       return 0;
+}
+
+int machine__process_fork_event(struct machine *machine, union perf_event *event)
+{
+       struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
+       struct thread *parent = machine__findnew_thread(machine, event->fork.ptid);
+
+       if (dump_trace)
+               perf_event__fprintf_task(event, stdout);
+
+       if (thread == NULL || parent == NULL ||
+           thread__fork(thread, parent) < 0) {
+               dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+int machine__process_exit_event(struct machine *machine, union perf_event *event)
+{
+       struct thread *thread = machine__find_thread(machine, event->fork.tid);
+
+       if (dump_trace)
+               perf_event__fprintf_task(event, stdout);
+
+       if (thread != NULL)
+               machine__remove_thread(machine, thread);
+
+       return 0;
+}
+
+int machine__process_event(struct machine *machine, union perf_event *event)
+{
+       int ret;
+
+       switch (event->header.type) {
+       case PERF_RECORD_COMM:
+               ret = machine__process_comm_event(machine, event); break;
+       case PERF_RECORD_MMAP:
+               ret = machine__process_mmap_event(machine, event); break;
+       case PERF_RECORD_FORK:
+               ret = machine__process_fork_event(machine, event); break;
+       case PERF_RECORD_EXIT:
+               ret = machine__process_exit_event(machine, event); break;
+       case PERF_RECORD_LOST:
+               ret = machine__process_lost_event(machine, event); break;
+       default:
+               ret = -1;
+               break;
+       }
+
+       return ret;
+}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
new file mode 100644 (file)
index 0000000..df152f1
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef __PERF_MACHINE_H
+#define __PERF_MACHINE_H
+
+#include <sys/types.h>
+
+struct thread;
+struct machine;
+union perf_event;
+
+struct thread *machine__find_thread(struct machine *machine, pid_t pid);
+
+int machine__process_comm_event(struct machine *machine, union perf_event *event);
+int machine__process_exit_event(struct machine *machine, union perf_event *event);
+int machine__process_fork_event(struct machine *machine, union perf_event *event);
+int machine__process_lost_event(struct machine *machine, union perf_event *event);
+int machine__process_mmap_event(struct machine *machine, union perf_event *event);
+int machine__process_event(struct machine *machine, union perf_event *event);
+
+#endif /* __PERF_MACHINE_H */
index 730c6630cba5ac254054c0ecc57d7363bd51f6e0..14683dfca2eeb9cfaeac762dc5964d48c093328c 100644 (file)
@@ -32,7 +32,6 @@
 #include "../event.h"
 #include "../thread.h"
 #include "../trace-event.h"
-#include "../evsel.h"
 
 PyMODINIT_FUNC initperf_trace_context(void);
 
index 8cdd23239c9023e8a8659a42b363239ded45cf4c..15abe40dc7021bd8229563a092ce63e67e4d2ccd 100644 (file)
@@ -1375,15 +1375,13 @@ int __perf_session__process_events(struct perf_session *session,
 {
        u64 head, page_offset, file_offset, file_pos, progress_next;
        int err, mmap_prot, mmap_flags, map_idx = 0;
-       size_t  page_size, mmap_size;
+       size_t  mmap_size;
        char *buf, *mmaps[8];
        union perf_event *event;
        uint32_t size;
 
        perf_tool__fill_defaults(tool);
 
-       page_size = sysconf(_SC_PAGESIZE);
-
        page_offset = page_size * (data_offset / page_size);
        file_offset = page_offset;
        head = data_offset - page_offset;
index 5786f323b597226a4668f1342ec0f06f5e8ec38c..13761d83a5a07a61d80f8c5841b98531e13625b0 100644 (file)
@@ -52,6 +52,22 @@ struct he_stat {
        u32                     nr_events;
 };
 
+struct hist_entry_diff {
+       bool    computed;
+
+       /* PERF_HPP__DISPL */
+       int     displacement;
+
+       /* PERF_HPP__DELTA */
+       double  period_ratio_delta;
+
+       /* PERF_HPP__RATIO */
+       double  period_ratio;
+
+       /* HISTC_WEIGHTED_DIFF */
+       s64     wdiff;
+};
+
 /**
  * struct hist_entry - histogram entry
  *
@@ -67,6 +83,8 @@ struct hist_entry {
        u64                     ip;
        s32                     cpu;
 
+       struct hist_entry_diff  diff;
+
        /* XXX These two should move to some tree widget lib */
        u16                     row_offset;
        u16                     nr_rows;
index 8b3e5939afb6ea00ef6cd74275eae99f35de0c25..df59623ac7630ccc67ee6f5cbaf5fae1c2847782 100644 (file)
@@ -7,7 +7,7 @@
 #include "util.h"
 #include "debug.h"
 
-static struct thread *thread__new(pid_t pid)
+struct thread *thread__new(pid_t pid)
 {
        struct thread *self = zalloc(sizeof(*self));
 
@@ -60,45 +60,6 @@ static size_t thread__fprintf(struct thread *self, FILE *fp)
               map_groups__fprintf(&self->mg, verbose, fp);
 }
 
-struct thread *machine__findnew_thread(struct machine *self, pid_t pid)
-{
-       struct rb_node **p = &self->threads.rb_node;
-       struct rb_node *parent = NULL;
-       struct thread *th;
-
-       /*
-        * Font-end cache - PID lookups come in blocks,
-        * so most of the time we dont have to look up
-        * the full rbtree:
-        */
-       if (self->last_match && self->last_match->pid == pid)
-               return self->last_match;
-
-       while (*p != NULL) {
-               parent = *p;
-               th = rb_entry(parent, struct thread, rb_node);
-
-               if (th->pid == pid) {
-                       self->last_match = th;
-                       return th;
-               }
-
-               if (pid < th->pid)
-                       p = &(*p)->rb_left;
-               else
-                       p = &(*p)->rb_right;
-       }
-
-       th = thread__new(pid);
-       if (th != NULL) {
-               rb_link_node(&th->rb_node, parent, p);
-               rb_insert_color(&th->rb_node, &self->threads);
-               self->last_match = th;
-       }
-
-       return th;
-}
-
 void thread__insert_map(struct thread *self, struct map *map)
 {
        map_groups__fixup_overlappings(&self->mg, map, verbose, stderr);
index f66610b7bacf344ef0cae7fd01dfefb69c69e073..f2fa17caa7d599e129a6901e0772e9a3916fd2d8 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/rbtree.h>
 #include <unistd.h>
+#include <sys/types.h>
 #include "symbol.h"
 
 struct thread {
@@ -22,6 +23,7 @@ struct thread {
 
 struct machine;
 
+struct thread *thread__new(pid_t pid);
 void thread__delete(struct thread *self);
 
 int thread__set_comm(struct thread *self, const char *comm);
index 719ed74a85652541d19e1f7dc15d26e2348a31fc..3741572696af4446c08a2c3b60ac674496323de6 100644 (file)
@@ -47,8 +47,6 @@ int file_bigendian;
 int host_bigendian;
 static int long_size;
 
-static unsigned long   page_size;
-
 static ssize_t calc_data_size;
 static bool repipe;
 
index 99664598bc1acfa3d03e0aaa1b0a44834be5f2d8..637b5cc5436299d317c71d84af6b64e5e774f58e 100644 (file)
@@ -10,6 +10,8 @@
 /*
  * XXX We need to find a better place for these things...
  */
+unsigned int page_size;
+
 bool perf_host  = true;
 bool perf_guest = false;
 
index 70fa70b535b2ebb2c389efa4ebbc78cfcdfaace2..a6b83f8ebef8726466d110644512a41eb87cf457 100644 (file)
@@ -263,4 +263,6 @@ char *rtrim(char *s);
 
 void dump_stack(void);
 
+extern unsigned int page_size;
+
 #endif