perf top: Use cond variable instead of a lock
tip-bot for Jiri Olsa
merge botCommit-ID: bc67057cab13c1571de499e94d491e6115da86c9 Gitweb: https://git.kernel.org/tip/bc67057cab13c1571de499e94d491e6115da86c9 Author: Jiri Olsa <[email protected]> AuthorDate: Mon, 5 Nov 2018 21:23:40 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 6 Dec 2018 14:12:33 -0300
perf top: Use cond variable instead of a lock
Use conditional variable logic to synchronize between the reading and processing threads. Currently it's done by having mutex around rotation code.
Using a POSIX cond variable to sync both threads after queues rotation:
Process thread:
- Detects data
- Switches queues
- Sets rotate variable
- Waits in pthread_cond_wait()
Read thread:
- Detects rotate is set
- Kicks the process thread with a pthread_cond_signal()
After this rotation is safely completed and both threads can continue with the new queue.
Acked-by David S. Miller <[email protected]>
Acked-by Namhyung Kim <[email protected]>
Cc Alexander Shishkin <[email protected]>
Cc Peter Zijlstra <[email protected]>
Signed-off-by Jiri Olsa <[email protected]>
--- tools/perf/builtin-top.c | 24 +++++++++++++++++------- tools/perf/util/top.h | 4 +++- 2 files changed, 20 insertions(+), 8 deletions(-)
tools/perf/builtin-top.c +17 -7
@@ -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)
@@ -1271,6 +1280,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);
tools/perf/util/top.h +3 -1
@@ -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; };