The perf top maintains various stats regarding samples.  Separate out
those stats so that it can be updated concurrently.

Signed-off-by: Namhyung Kim <namhy...@kernel.org>
---
 tools/perf/builtin-top.c | 36 ++++++++++++++++++++++++++++--------
 tools/perf/util/top.c    | 18 ++++++++----------
 tools/perf/util/top.h    | 12 ++++++++----
 3 files changed, 44 insertions(+), 22 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 5987986b5203..f3ab46b234b6 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -902,8 +902,26 @@ struct reader_arg {
        int                     idx;
        struct perf_top         *top;
        struct hists            *hists;
+       struct perf_top_stats   stats;
 };
 
+static void perf_top_stats__add(struct perf_top_stats *dst,
+                               struct perf_top_stats *src)
+{
+       static pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER;
+
+       pthread_mutex_lock(&stats_lock);
+
+       dst->samples              += src->samples;
+       dst->exact_samples        += src->exact_samples;
+       dst->kernel_samples       += src->kernel_samples;
+       dst->us_samples           += src->us_samples;
+       dst->guest_kernel_samples += src->guest_kernel_samples;
+       dst->guest_us_samples     += src->guest_us_samples;
+
+       pthread_mutex_unlock(&stats_lock);
+}
+
 static void perf_event__process_sample(struct reader_arg *rarg,
                                       const union perf_event *event,
                                       struct perf_evsel *evsel,
@@ -938,7 +956,7 @@ static void perf_event__process_sample(struct reader_arg 
*rarg,
        }
 
        if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
-               top->exact_samples++;
+               rarg->stats.exact_samples++;
 
        if (perf_event__preprocess_sample(event, machine, &al, sample) < 0)
                return;
@@ -1000,28 +1018,28 @@ static void perf_top__mmap_read(struct reader_arg *rarg)
                origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 
                if (event->header.type == PERF_RECORD_SAMPLE)
-                       ++top->samples;
+                       ++rarg->stats.samples;
 
                switch (origin) {
                case PERF_RECORD_MISC_USER:
-                       ++top->us_samples;
+                       ++rarg->stats.us_samples;
                        if (top->hide_user_symbols)
                                goto next_event;
                        machine = &session->machines.host;
                        break;
                case PERF_RECORD_MISC_KERNEL:
-                       ++top->kernel_samples;
+                       ++rarg->stats.kernel_samples;
                        if (top->hide_kernel_symbols)
                                goto next_event;
                        machine = &session->machines.host;
                        break;
                case PERF_RECORD_MISC_GUEST_KERNEL:
-                       ++top->guest_kernel_samples;
+                       ++rarg->stats.guest_kernel_samples;
                        machine = perf_session__find_machine(session,
                                                             sample.pid);
                        break;
                case PERF_RECORD_MISC_GUEST_USER:
-                       ++top->guest_us_samples;
+                       ++rarg->stats.guest_us_samples;
                        /*
                         * TODO: we don't process guest user from host side
                         * except simple counting.
@@ -1065,12 +1083,14 @@ static void *mmap_read_worker(void *arg)
        }
 
        while (!done) {
-               u64 hits = top->samples;
+               u64 hits = rarg->stats.samples;
 
                perf_top__mmap_read(rarg);
 
-               if (hits == top->samples)
+               if (hits == rarg->stats.samples)
                        perf_evlist__poll(top->evlist, 100);
+               else
+                       perf_top_stats__add(&top->stats, &rarg->stats);
        }
        return NULL;
 }
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index 8e517def925b..95d6bba1a2a0 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -30,10 +30,10 @@ size_t perf_top__header_snprintf(struct perf_top *top, char 
*bf, size_t size)
        struct target *target = &opts->target;
        size_t ret = 0;
 
-       if (top->samples) {
-               samples_per_sec = top->samples / top->delay_secs;
-               ksamples_per_sec = top->kernel_samples / top->delay_secs;
-               esamples_percent = (100.0 * top->exact_samples) / top->samples;
+       if (top->stats.samples) {
+               samples_per_sec = top->stats.samples / top->delay_secs;
+               ksamples_per_sec = top->stats.kernel_samples / top->delay_secs;
+               esamples_percent = (100.0 * top->stats.exact_samples) / 
top->stats.samples;
        } else {
                samples_per_sec = ksamples_per_sec = esamples_percent = 0.0;
        }
@@ -49,9 +49,9 @@ size_t perf_top__header_snprintf(struct perf_top *top, char 
*bf, size_t size)
                               "  exact: %4.1f%% [", samples_per_sec,
                               ksamples_percent, esamples_percent);
        } else {
-               float us_samples_per_sec = top->us_samples / top->delay_secs;
-               float guest_kernel_samples_per_sec = top->guest_kernel_samples 
/ top->delay_secs;
-               float guest_us_samples_per_sec = top->guest_us_samples / 
top->delay_secs;
+               float us_samples_per_sec = top->stats.us_samples / 
top->delay_secs;
+               float guest_kernel_samples_per_sec = 
top->stats.guest_kernel_samples / top->delay_secs;
+               float guest_us_samples_per_sec = top->stats.guest_us_samples / 
top->delay_secs;
 
                ret = SNPRINTF(bf, size,
                               "   PerfTop:%8.0f irqs/sec  kernel:%4.1f%% 
us:%4.1f%%"
@@ -111,7 +111,5 @@ size_t perf_top__header_snprintf(struct perf_top *top, char 
*bf, size_t size)
 
 void perf_top__reset_sample_counters(struct perf_top *top)
 {
-       top->samples = top->us_samples = top->kernel_samples =
-       top->exact_samples = top->guest_kernel_samples =
-       top->guest_us_samples = 0;
+       memset(&top->stats, 0, sizeof(top->stats));
 }
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index c56a00cff5b4..55eb5aebae59 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -11,18 +11,22 @@ struct perf_evlist;
 struct perf_evsel;
 struct perf_session;
 
+struct perf_top_stats {
+       u64                samples;
+       u64                exact_samples;
+       u64                kernel_samples, us_samples;
+       u64                guest_kernel_samples, guest_us_samples;
+};
+
 struct perf_top {
        struct perf_tool   tool;
        struct perf_evlist *evlist;
        struct record_opts record_opts;
+       struct perf_top_stats stats;
        /*
         * Symbols will be added here in perf_event__process_sample and will
         * get out after decayed.
         */
-       u64                samples;
-       u64                kernel_samples, us_samples;
-       u64                exact_samples;
-       u64                guest_us_samples, guest_kernel_samples;
        int                print_entries, count_filter, delay_secs;
        int                max_stack;
        bool               hide_kernel_symbols, hide_user_symbols, zero;
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to