Using conditional variable logic to synchronize between
reading and processing threads. Currently it's done by
having mutex around rotation code.

Using posix cond variable to sync both threads after queues
rotation:

  process thread:
    - detects data
    - switches queues
    - set rotate variable
    - waits in pthread_cond_wait

  read thread:
    - detects rotate is set
    - kicks process thread with pthread_cond_signal

After this rotation is safely completed and both threads
can continue with the new queue.

Link: http://lkml.kernel.org/n/tip-3rdeg23rv3brvy1pwt3ig...@git.kernel.org
Signed-off-by: Jiri Olsa <jo...@kernel.org>
---
 tools/perf/builtin-top.c | 24 +++++++++++++++++-------
 tools/perf/util/top.h    |  4 +++-
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index f8dcdf0f54e1..ca2a1557ac07 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -846,13 +846,18 @@ static void perf_top__mmap_read_idx(struct perf_top *top, 
int idx)
                if (ret && ret != -1)
                        break;
 
-               pthread_mutex_lock(&top->qe.lock);
                ret = ordered_events__queue(top->qe.in, event, timestamp, 0);
-               pthread_mutex_unlock(&top->qe.lock);
-
-               perf_mmap__consume(md);
                if (ret)
                        break;
+
+               perf_mmap__consume(md);
+
+               if (top->qe.rotate) {
+                       pthread_mutex_lock(&top->qe.mutex);
+                       top->qe.rotate = false;
+                       pthread_cond_signal(&top->qe.cond);
+                       pthread_mutex_unlock(&top->qe.mutex);
+               }
        }
 
        perf_mmap__read_done(md);
@@ -1059,9 +1064,12 @@ static void *process_thread(void *arg)
                        continue;
                }
 
-               pthread_mutex_lock(&top->qe.lock);
                out = rotate_queues(top);
-               pthread_mutex_unlock(&top->qe.lock);
+
+               pthread_mutex_lock(&top->qe.mutex);
+               top->qe.rotate = true;
+               pthread_cond_wait(&top->qe.cond, &top->qe.mutex);
+               pthread_mutex_unlock(&top->qe.mutex);
 
                if (ordered_events__flush(out, OE_FLUSH__TOP))
                        pr_err("failed to process events\n");
@@ -1151,7 +1159,8 @@ static void init_process_thread(struct perf_top *top)
        ordered_events__set_copy_on_queue(&top->qe.data[0], true);
        ordered_events__set_copy_on_queue(&top->qe.data[1], true);
        top->qe.in = &top->qe.data[0];
-       pthread_mutex_init(&top->qe.lock, NULL);
+       pthread_mutex_init(&top->qe.mutex, NULL);
+       pthread_cond_init(&top->qe.cond, NULL);
 }
 
 static int __cmd_top(struct perf_top *top)
@@ -1272,6 +1281,7 @@ static int __cmd_top(struct perf_top *top)
 out_join:
        pthread_join(thread, NULL);
 out_join_thread:
+       pthread_cond_signal(&top->qe.cond);
        pthread_join(thread_process, NULL);
 out_delete:
        perf_session__delete(top->session);
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 5f503293cfd8..5bce62ebcf14 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -44,7 +44,9 @@ struct perf_top {
        struct {
                struct ordered_events   *in;
                struct ordered_events    data[2];
-               pthread_mutex_t          lock;
+               bool                     rotate;
+               pthread_mutex_t          mutex;
+               pthread_cond_t           cond;
        } qe;
 };
 
-- 
2.17.2

Reply via email to