The current code assumes that the number of index item and cpu are
matched so it creates that number of threads.  But it's not the case
of non-system-wide session or data came from different machine.

Just creates threads at most number of online cpus and process data.

Signed-off-by: Namhyung Kim <namhy...@kernel.org>
---
 tools/perf/util/session.c | 68 ++++++++++++++++++++++++++++++++++-------------
 tools/perf/util/tool.h    |  1 -
 2 files changed, 50 insertions(+), 19 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 6d34c880010f..ccf9371ef292 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1431,26 +1431,51 @@ static struct ui_progress_ops mt_progress__ops = {
        .update = mt_progress__update,
 };
 
+static int perf_session__get_index(struct perf_session *session)
+{
+       int ret;
+       static unsigned index;
+       static pthread_mutex_t idx_lock = PTHREAD_MUTEX_INITIALIZER;
+
+       pthread_mutex_lock(&idx_lock);
+       if (index < session->header.nr_index)
+               ret = index++;
+       else
+               ret = -1;
+       pthread_mutex_unlock(&idx_lock);
+
+       return ret;
+}
+
 static void *processing_thread_idx(void *arg)
 {
        struct perf_tool_mt *mt_tool = arg;
        struct perf_session *session = mt_tool->session;
        int fd = perf_data_file__fd(session->file);
-       u64 offset = session->header.index[mt_tool->idx].offset;
-       u64 size = session->header.index[mt_tool->idx].size;
        u64 file_size = perf_data_file__size(session->file);
+       int idx;
 
-       ui_progress__init(&mt_tool->prog, size, "");
+       while ((idx = perf_session__get_index(session)) >= 0) {
+               u64 offset = session->header.index[idx].offset;
+               u64 size = session->header.index[idx].size;
+               struct perf_tool_mt *mtt = &mt_tool[idx];
 
-       pr_debug("processing samples using thread [%d]\n", mt_tool->idx);
-       if (__perf_session__process_events(session, &mt_tool->stats,
-                                          fd, offset, size, file_size,
-                                          &mt_tool->tool, &mt_tool->prog) < 0) 
{
-               pr_err("processing samples failed (thread [%d)\n", 
mt_tool->idx);
-               return NULL;
+               if (size == 0)
+                       continue;
+
+               pr_debug("processing samples [index %d]\n", idx);
+
+               ui_progress__init(&mtt->prog, size, "");
+
+               if (__perf_session__process_events(session, &mtt->stats,
+                                                  fd, offset, size, file_size,
+                                                  &mtt->tool, &mtt->prog) < 0) 
{
+                       pr_err("processing samples failed [index %d]\n", idx);
+                       return NULL;
+               }
+               pr_debug("processing samples done [index %d]\n", idx);
        }
 
-       pr_debug("processing samples done for thread [%d]\n", mt_tool->idx);
        return arg;
 }
 
@@ -1468,6 +1493,7 @@ int perf_session__process_events_mt(struct perf_session 
*session,
        int err, i, k;
        int nr_index = session->header.nr_index;
        u64 size = perf_data_file__size(file);
+       int nr_thread = sysconf(_SC_NPROCESSORS_ONLN);
 
        if (perf_session__register_idle_thread(session) == NULL)
                return -ENOMEM;
@@ -1491,10 +1517,6 @@ int perf_session__process_events_mt(struct perf_session 
*session,
        ui_progress__ops = &mt_progress__ops;
        ui_progress__ops->finish = orig_progress__ops->finish;
 
-       th_id = calloc(nr_index, sizeof(*th_id));
-       if (th_id == NULL)
-               goto out;
-
        mt_tools = calloc(nr_index, sizeof(*mt_tools));
        if (mt_tools == NULL)
                goto out;
@@ -1513,20 +1535,30 @@ int perf_session__process_events_mt(struct perf_session 
*session,
 
                mt->session = session;
                mt->tool.ordered_events = false;
-               mt->idx = i;
                mt->priv = arg;
                mt->global_prog = &prog;
-
-               pthread_create(&th_id[i], NULL, processing_thread_idx, mt);
        }
 
-       for (i = 0; i < nr_index; i++) {
+       if (nr_thread > nr_index)
+               nr_thread = nr_index;
+
+       th_id = calloc(nr_thread, sizeof(*th_id));
+       if (th_id == NULL)
+               goto out;
+
+       for (i = 0; i < nr_thread; i++)
+               pthread_create(&th_id[i], NULL, processing_thread_idx, 
mt_tools);
+
+       for (i = 0; i < nr_thread; i++) {
                pthread_join(th_id[i], (void **)&mt);
                if (mt == NULL) {
                        err = -EINVAL;
                        continue;
                }
+       }
 
+       for (i = 0; i < nr_index; i++) {
+               mt = &mt_tools[i];
                events_stats__add(&session->stats, &mt->stats);
 
                evlist__for_each(evlist, evsel) {
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index aa7f110b9425..e52c936d1b9e 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -55,7 +55,6 @@ struct perf_tool_mt {
        struct perf_session     *session;
        struct ui_progress      prog;
        struct ui_progress      *global_prog;
-       int                     idx;
 
        void                    *priv;
 };
-- 
2.2.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