aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/bench/futex-wake-parallel.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/bench/futex-wake-parallel.c')
-rw-r--r--tools/perf/bench/futex-wake-parallel.c46
1 files changed, 35 insertions, 11 deletions
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index b4732dad9f89..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,12 +25,11 @@
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"
32#include "cpumap.h"
24 33
25#include <err.h> 34#include <err.h>
26#include <stdlib.h> 35#include <stdlib.h>
@@ -42,8 +51,9 @@ static bool done = false, silent = false, fshared = false;
42static unsigned int nblocked_threads = 0, nwaking_threads = 0; 51static unsigned int nblocked_threads = 0, nwaking_threads = 0;
43static pthread_mutex_t thread_lock; 52static pthread_mutex_t thread_lock;
44static pthread_cond_t thread_parent, thread_worker; 53static pthread_cond_t thread_parent, thread_worker;
54static pthread_barrier_t barrier;
45static struct stats waketime_stats, wakeup_stats; 55static struct stats waketime_stats, wakeup_stats;
46static unsigned int ncpus, threads_starting; 56static unsigned int threads_starting;
47static int futex_flag = 0; 57static int futex_flag = 0;
48 58
49static const struct option options[] = { 59static const struct option options[] = {
@@ -64,6 +74,8 @@ static void *waking_workerfn(void *arg)
64 struct thread_data *waker = (struct thread_data *) arg; 74 struct thread_data *waker = (struct thread_data *) arg;
65 struct timeval start, end; 75 struct timeval start, end;
66 76
77 pthread_barrier_wait(&barrier);
78
67 gettimeofday(&start, NULL); 79 gettimeofday(&start, NULL);
68 80
69 waker->nwoken = futex_wake(&futex, nwakes, futex_flag); 81 waker->nwoken = futex_wake(&futex, nwakes, futex_flag);
@@ -84,6 +96,8 @@ static void wakeup_threads(struct thread_data *td, pthread_attr_t thread_attr)
84 96
85 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE); 97 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
86 98
99 pthread_barrier_init(&barrier, NULL, nwaking_threads + 1);
100
87 /* create and block all threads */ 101 /* create and block all threads */
88 for (i = 0; i < nwaking_threads; i++) { 102 for (i = 0; i < nwaking_threads; i++) {
89 /* 103 /*
@@ -96,9 +110,13 @@ static void wakeup_threads(struct thread_data *td, pthread_attr_t thread_attr)
96 err(EXIT_FAILURE, "pthread_create"); 110 err(EXIT_FAILURE, "pthread_create");
97 } 111 }
98 112
113 pthread_barrier_wait(&barrier);
114
99 for (i = 0; i < nwaking_threads; i++) 115 for (i = 0; i < nwaking_threads; i++)
100 if (pthread_join(td[i].worker, NULL)) 116 if (pthread_join(td[i].worker, NULL))
101 err(EXIT_FAILURE, "pthread_join"); 117 err(EXIT_FAILURE, "pthread_join");
118
119 pthread_barrier_destroy(&barrier);
102} 120}
103 121
104static void *blocked_workerfn(void *arg __maybe_unused) 122static void *blocked_workerfn(void *arg __maybe_unused)
@@ -119,19 +137,20 @@ static void *blocked_workerfn(void *arg __maybe_unused)
119 return NULL; 137 return NULL;
120} 138}
121 139
122static void block_threads(pthread_t *w, pthread_attr_t thread_attr) 140static void block_threads(pthread_t *w, pthread_attr_t thread_attr,
141 struct cpu_map *cpu)
123{ 142{
124 cpu_set_t cpu; 143 cpu_set_t cpuset;
125 unsigned int i; 144 unsigned int i;
126 145
127 threads_starting = nblocked_threads; 146 threads_starting = nblocked_threads;
128 147
129 /* create and block all threads */ 148 /* create and block all threads */
130 for (i = 0; i < nblocked_threads; i++) { 149 for (i = 0; i < nblocked_threads; i++) {
131 CPU_ZERO(&cpu); 150 CPU_ZERO(&cpuset);
132 CPU_SET(i % ncpus, &cpu); 151 CPU_SET(cpu->map[i % cpu->nr], &cpuset);
133 152
134 if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu)) 153 if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset))
135 err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); 154 err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
136 155
137 if (pthread_create(&w[i], &thread_attr, blocked_workerfn, NULL)) 156 if (pthread_create(&w[i], &thread_attr, blocked_workerfn, NULL))
@@ -205,6 +224,7 @@ int bench_futex_wake_parallel(int argc, const char **argv)
205 struct sigaction act; 224 struct sigaction act;
206 pthread_attr_t thread_attr; 225 pthread_attr_t thread_attr;
207 struct thread_data *waking_worker; 226 struct thread_data *waking_worker;
227 struct cpu_map *cpu;
208 228
209 argc = parse_options(argc, argv, options, 229 argc = parse_options(argc, argv, options,
210 bench_futex_wake_parallel_usage, 0); 230 bench_futex_wake_parallel_usage, 0);
@@ -217,9 +237,12 @@ int bench_futex_wake_parallel(int argc, const char **argv)
217 act.sa_sigaction = toggle_done; 237 act.sa_sigaction = toggle_done;
218 sigaction(SIGINT, &act, NULL); 238 sigaction(SIGINT, &act, NULL);
219 239
220 ncpus = sysconf(_SC_NPROCESSORS_ONLN); 240 cpu = cpu_map__new(NULL);
241 if (!cpu)
242 err(EXIT_FAILURE, "calloc");
243
221 if (!nblocked_threads) 244 if (!nblocked_threads)
222 nblocked_threads = ncpus; 245 nblocked_threads = cpu->nr;
223 246
224 /* some sanity checks */ 247 /* some sanity checks */
225 if (nwaking_threads > nblocked_threads || !nwaking_threads) 248 if (nwaking_threads > nblocked_threads || !nwaking_threads)
@@ -259,7 +282,7 @@ int bench_futex_wake_parallel(int argc, const char **argv)
259 err(EXIT_FAILURE, "calloc"); 282 err(EXIT_FAILURE, "calloc");
260 283
261 /* create, launch & block all threads */ 284 /* create, launch & block all threads */
262 block_threads(blocked_worker, thread_attr); 285 block_threads(blocked_worker, thread_attr, cpu);
263 286
264 /* make sure all threads are already blocked */ 287 /* make sure all threads are already blocked */
265 pthread_mutex_lock(&thread_lock); 288 pthread_mutex_lock(&thread_lock);
@@ -297,3 +320,4 @@ int bench_futex_wake_parallel(int argc, const char **argv)
297 free(blocked_worker); 320 free(blocked_worker);
298 return ret; 321 return ret;
299} 322}
323#endif /* HAVE_PTHREAD_BARRIER */