summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Yang <james.yang@arm.com>2017-11-26 23:21:01 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2017-12-05 08:23:44 -0500
commit8085e5ab41dadce558808b4186a6ea9d0862d3c0 (patch)
tree0e126a5c26338d3997f44794f58db0e427e0c80a
parent25ab5abf5b141d7fd13eed506c7458aa04749c29 (diff)
perf bench futex: Sync waker threads
Waker threads in the futex wake-parallel benchmark are started by a loop using pthread_create(). However, there is no synchronization for when the waker threads wake the waiting threads. Comparison of the waker threads' measurement timestamps show they are not all running concurrently because older waker threads finish their task before newer waker threads even start. This patch uses a barrier to better synchronize the waker threads. Signed-off-by: James Yang <james.yang@arm.com Cc: Kim Phillips <kim.phillips@arm.com> Link: http://lkml.kernel.org/r/20171127042101.3659-4-dave@stgolabs.net Signed-off-by: Davidlohr Bueso <dave@stgolabs.net> [ Disable the wake-parallel test for systems without pthread_barrier_t ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/bench/futex-wake-parallel.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index 4488c27e8a43..69d8fdc87315 100644
--- a/tools/perf/bench/futex-wake-parallel.c
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -7,7 +7,17 @@
7 * for each individual thread to service its share of work. Ultimately 7 * for each individual thread to service its share of work. Ultimately
8 * it can be used to measure futex_wake() changes. 8 * it can be used to measure futex_wake() changes.
9 */ 9 */
10#include "bench.h"
11#include <linux/compiler.h>
12#include "../util/debug.h"
10 13
14#ifndef HAVE_PTHREAD_BARRIER
15int bench_futex_wake_parallel(int argc __maybe_unused, const char **argv __maybe_unused)
16{
17 pr_err("%s: pthread_barrier_t unavailable, disabling this test...\n", __func__);
18 return 0;
19}
20#else /* HAVE_PTHREAD_BARRIER */
11/* For the CLR_() macros */ 21/* For the CLR_() macros */
12#include <string.h> 22#include <string.h>
13#include <pthread.h> 23#include <pthread.h>
@@ -15,11 +25,9 @@
15#include <signal.h> 25#include <signal.h>
16#include "../util/stat.h" 26#include "../util/stat.h"
17#include <subcmd/parse-options.h> 27#include <subcmd/parse-options.h>
18#include <linux/compiler.h>
19#include <linux/kernel.h> 28#include <linux/kernel.h>
20#include <linux/time64.h> 29#include <linux/time64.h>
21#include <errno.h> 30#include <errno.h>
22#include "bench.h"
23#include "futex.h" 31#include "futex.h"
24#include "cpumap.h" 32#include "cpumap.h"
25 33
@@ -43,6 +51,7 @@ static bool done = false, silent = false, fshared = false;
43static unsigned int nblocked_threads = 0, nwaking_threads = 0; 51static unsigned int nblocked_threads = 0, nwaking_threads = 0;
44static pthread_mutex_t thread_lock; 52static pthread_mutex_t thread_lock;
45static pthread_cond_t thread_parent, thread_worker; 53static pthread_cond_t thread_parent, thread_worker;
54static pthread_barrier_t barrier;
46static struct stats waketime_stats, wakeup_stats; 55static struct stats waketime_stats, wakeup_stats;
47static unsigned int threads_starting; 56static unsigned int threads_starting;
48static int futex_flag = 0; 57static int futex_flag = 0;
@@ -65,6 +74,8 @@ static void *waking_workerfn(void *arg)
65 struct thread_data *waker = (struct thread_data *) arg; 74 struct thread_data *waker = (struct thread_data *) arg;
66 struct timeval start, end; 75 struct timeval start, end;
67 76
77 pthread_barrier_wait(&barrier);
78
68 gettimeofday(&start, NULL); 79 gettimeofday(&start, NULL);
69 80
70 waker->nwoken = futex_wake(&futex, nwakes, futex_flag); 81 waker->nwoken = futex_wake(&futex, nwakes, futex_flag);
@@ -85,6 +96,8 @@ static void wakeup_threads(struct thread_data *td, pthread_attr_t thread_attr)
85 96
86 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE); 97 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
87 98
99 pthread_barrier_init(&barrier, NULL, nwaking_threads + 1);
100
88 /* create and block all threads */ 101 /* create and block all threads */
89 for (i = 0; i < nwaking_threads; i++) { 102 for (i = 0; i < nwaking_threads; i++) {
90 /* 103 /*
@@ -97,9 +110,13 @@ static void wakeup_threads(struct thread_data *td, pthread_attr_t thread_attr)
97 err(EXIT_FAILURE, "pthread_create"); 110 err(EXIT_FAILURE, "pthread_create");
98 } 111 }
99 112
113 pthread_barrier_wait(&barrier);
114
100 for (i = 0; i < nwaking_threads; i++) 115 for (i = 0; i < nwaking_threads; i++)
101 if (pthread_join(td[i].worker, NULL)) 116 if (pthread_join(td[i].worker, NULL))
102 err(EXIT_FAILURE, "pthread_join"); 117 err(EXIT_FAILURE, "pthread_join");
118
119 pthread_barrier_destroy(&barrier);
103} 120}
104 121
105static void *blocked_workerfn(void *arg __maybe_unused) 122static void *blocked_workerfn(void *arg __maybe_unused)
@@ -303,3 +320,4 @@ int bench_futex_wake_parallel(int argc, const char **argv)
303 free(blocked_worker); 320 free(blocked_worker);
304 return ret; 321 return ret;
305} 322}
323#endif /* HAVE_PTHREAD_BARRIER */