summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavidlohr Bueso <dave@stgolabs.net>2017-11-26 23:20:59 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2017-11-30 12:02:05 -0500
commit3b2323c2c1c4acf8961cfcdddcee9889daaa21e3 (patch)
treea366e8b5137d89f10885ff7d0e6ade8ed0cbf047
parent17a68b835921c4664929376447cae5e3374ce2a7 (diff)
perf bench futex: Use cpumaps
It was reported that the whole futex bench breaks when dealing with non-contiguously numbered cpus. $ echo 0 | sudo tee /sys/devices/system/cpu/cpu3/online $ ./perf bench futex all perf: pthread_create: Operation not permitted Run summary [PID 14934]: 7 threads, each .... James had implemented an approach with cpumaps that use an in house flavor. Instead of re-inventing the wheel, I've redone the patch such that we use the perf's util/cpumap.c interface instead. Applies to all futex benchmarks. Suggested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Originally-from: James Yang <james.yang@arm.com> Signed-off-by: Davidlohr Bueso <dbueso@suse.de> Cc: Davidlohr Bueso <dbueso@suse.de> Cc: Kim Phillips <kim.phillips@arm.com> Link: http://lkml.kernel.org/r/20171127042101.3659-2-dave@stgolabs.net Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/bench/futex-hash.c19
-rw-r--r--tools/perf/bench/futex-lock-pi.c23
-rw-r--r--tools/perf/bench/futex-requeue.c22
-rw-r--r--tools/perf/bench/futex-wake-parallel.c24
-rw-r--r--tools/perf/bench/futex-wake.c18
5 files changed, 65 insertions, 41 deletions
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index 58ae6ed8f38b..2defb6df7fd0 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -24,6 +24,7 @@
24#include <subcmd/parse-options.h> 24#include <subcmd/parse-options.h>
25#include "bench.h" 25#include "bench.h"
26#include "futex.h" 26#include "futex.h"
27#include "cpumap.h"
27 28
28#include <err.h> 29#include <err.h>
29#include <sys/time.h> 30#include <sys/time.h>
@@ -118,11 +119,12 @@ static void print_summary(void)
118int bench_futex_hash(int argc, const char **argv) 119int bench_futex_hash(int argc, const char **argv)
119{ 120{
120 int ret = 0; 121 int ret = 0;
121 cpu_set_t cpu; 122 cpu_set_t cpuset;
122 struct sigaction act; 123 struct sigaction act;
123 unsigned int i, ncpus; 124 unsigned int i;
124 pthread_attr_t thread_attr; 125 pthread_attr_t thread_attr;
125 struct worker *worker = NULL; 126 struct worker *worker = NULL;
127 struct cpu_map *cpu;
126 128
127 argc = parse_options(argc, argv, options, bench_futex_hash_usage, 0); 129 argc = parse_options(argc, argv, options, bench_futex_hash_usage, 0);
128 if (argc) { 130 if (argc) {
@@ -130,14 +132,16 @@ int bench_futex_hash(int argc, const char **argv)
130 exit(EXIT_FAILURE); 132 exit(EXIT_FAILURE);
131 } 133 }
132 134
133 ncpus = sysconf(_SC_NPROCESSORS_ONLN); 135 cpu = cpu_map__new(NULL);
136 if (!cpu)
137 goto errmem;
134 138
135 sigfillset(&act.sa_mask); 139 sigfillset(&act.sa_mask);
136 act.sa_sigaction = toggle_done; 140 act.sa_sigaction = toggle_done;
137 sigaction(SIGINT, &act, NULL); 141 sigaction(SIGINT, &act, NULL);
138 142
139 if (!nthreads) /* default to the number of CPUs */ 143 if (!nthreads) /* default to the number of CPUs */
140 nthreads = ncpus; 144 nthreads = cpu->nr;
141 145
142 worker = calloc(nthreads, sizeof(*worker)); 146 worker = calloc(nthreads, sizeof(*worker));
143 if (!worker) 147 if (!worker)
@@ -163,10 +167,10 @@ int bench_futex_hash(int argc, const char **argv)
163 if (!worker[i].futex) 167 if (!worker[i].futex)
164 goto errmem; 168 goto errmem;
165 169
166 CPU_ZERO(&cpu); 170 CPU_ZERO(&cpuset);
167 CPU_SET(i % ncpus, &cpu); 171 CPU_SET(cpu->map[i % cpu->nr], &cpuset);
168 172
169 ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu); 173 ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset);
170 if (ret) 174 if (ret)
171 err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); 175 err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
172 176
@@ -217,6 +221,7 @@ int bench_futex_hash(int argc, const char **argv)
217 print_summary(); 221 print_summary();
218 222
219 free(worker); 223 free(worker);
224 free(cpu);
220 return ret; 225 return ret;
221errmem: 226errmem:
222 err(EXIT_FAILURE, "calloc"); 227 err(EXIT_FAILURE, "calloc");
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index 08653ae8a8c4..8e9c4753e304 100644
--- a/tools/perf/bench/futex-lock-pi.c
+++ b/tools/perf/bench/futex-lock-pi.c
@@ -15,6 +15,7 @@
15#include <errno.h> 15#include <errno.h>
16#include "bench.h" 16#include "bench.h"
17#include "futex.h" 17#include "futex.h"
18#include "cpumap.h"
18 19
19#include <err.h> 20#include <err.h>
20#include <stdlib.h> 21#include <stdlib.h>
@@ -32,7 +33,7 @@ static struct worker *worker;
32static unsigned int nsecs = 10; 33static unsigned int nsecs = 10;
33static bool silent = false, multi = false; 34static bool silent = false, multi = false;
34static bool done = false, fshared = false; 35static bool done = false, fshared = false;
35static unsigned int ncpus, nthreads = 0; 36static unsigned int nthreads = 0;
36static int futex_flag = 0; 37static int futex_flag = 0;
37struct timeval start, end, runtime; 38struct timeval start, end, runtime;
38static pthread_mutex_t thread_lock; 39static pthread_mutex_t thread_lock;
@@ -113,9 +114,10 @@ static void *workerfn(void *arg)
113 return NULL; 114 return NULL;
114} 115}
115 116
116static void create_threads(struct worker *w, pthread_attr_t thread_attr) 117static void create_threads(struct worker *w, pthread_attr_t thread_attr,
118 struct cpu_map *cpu)
117{ 119{
118 cpu_set_t cpu; 120 cpu_set_t cpuset;
119 unsigned int i; 121 unsigned int i;
120 122
121 threads_starting = nthreads; 123 threads_starting = nthreads;
@@ -130,10 +132,10 @@ static void create_threads(struct worker *w, pthread_attr_t thread_attr)
130 } else 132 } else
131 worker[i].futex = &global_futex; 133 worker[i].futex = &global_futex;
132 134
133 CPU_ZERO(&cpu); 135 CPU_ZERO(&cpuset);
134 CPU_SET(i % ncpus, &cpu); 136 CPU_SET(cpu->map[i % cpu->nr], &cpuset);
135 137
136 if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu)) 138 if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset))
137 err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); 139 err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
138 140
139 if (pthread_create(&w[i].thread, &thread_attr, workerfn, &worker[i])) 141 if (pthread_create(&w[i].thread, &thread_attr, workerfn, &worker[i]))
@@ -147,19 +149,22 @@ int bench_futex_lock_pi(int argc, const char **argv)
147 unsigned int i; 149 unsigned int i;
148 struct sigaction act; 150 struct sigaction act;
149 pthread_attr_t thread_attr; 151 pthread_attr_t thread_attr;
152 struct cpu_map *cpu;
150 153
151 argc = parse_options(argc, argv, options, bench_futex_lock_pi_usage, 0); 154 argc = parse_options(argc, argv, options, bench_futex_lock_pi_usage, 0);
152 if (argc) 155 if (argc)
153 goto err; 156 goto err;
154 157
155 ncpus = sysconf(_SC_NPROCESSORS_ONLN); 158 cpu = cpu_map__new(NULL);
159 if (!cpu)
160 err(EXIT_FAILURE, "calloc");
156 161
157 sigfillset(&act.sa_mask); 162 sigfillset(&act.sa_mask);
158 act.sa_sigaction = toggle_done; 163 act.sa_sigaction = toggle_done;
159 sigaction(SIGINT, &act, NULL); 164 sigaction(SIGINT, &act, NULL);
160 165
161 if (!nthreads) 166 if (!nthreads)
162 nthreads = ncpus; 167 nthreads = cpu->nr;
163 168
164 worker = calloc(nthreads, sizeof(*worker)); 169 worker = calloc(nthreads, sizeof(*worker));
165 if (!worker) 170 if (!worker)
@@ -180,7 +185,7 @@ int bench_futex_lock_pi(int argc, const char **argv)
180 pthread_attr_init(&thread_attr); 185 pthread_attr_init(&thread_attr);
181 gettimeofday(&start, NULL); 186 gettimeofday(&start, NULL);
182 187
183 create_threads(worker, thread_attr); 188 create_threads(worker, thread_attr, cpu);
184 pthread_attr_destroy(&thread_attr); 189 pthread_attr_destroy(&thread_attr);
185 190
186 pthread_mutex_lock(&thread_lock); 191 pthread_mutex_lock(&thread_lock);
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index 1058c194608a..fc692efa0c05 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -22,6 +22,7 @@
22#include <errno.h> 22#include <errno.h>
23#include "bench.h" 23#include "bench.h"
24#include "futex.h" 24#include "futex.h"
25#include "cpumap.h"
25 26
26#include <err.h> 27#include <err.h>
27#include <stdlib.h> 28#include <stdlib.h>
@@ -40,7 +41,7 @@ static bool done = false, silent = false, fshared = false;
40static pthread_mutex_t thread_lock; 41static pthread_mutex_t thread_lock;
41static pthread_cond_t thread_parent, thread_worker; 42static pthread_cond_t thread_parent, thread_worker;
42static struct stats requeuetime_stats, requeued_stats; 43static struct stats requeuetime_stats, requeued_stats;
43static unsigned int ncpus, threads_starting, nthreads = 0; 44static unsigned int threads_starting, nthreads = 0;
44static int futex_flag = 0; 45static int futex_flag = 0;
45 46
46static const struct option options[] = { 47static const struct option options[] = {
@@ -83,19 +84,19 @@ static void *workerfn(void *arg __maybe_unused)
83} 84}
84 85
85static void block_threads(pthread_t *w, 86static void block_threads(pthread_t *w,
86 pthread_attr_t thread_attr) 87 pthread_attr_t thread_attr, struct cpu_map *cpu)
87{ 88{
88 cpu_set_t cpu; 89 cpu_set_t cpuset;
89 unsigned int i; 90 unsigned int i;
90 91
91 threads_starting = nthreads; 92 threads_starting = nthreads;
92 93
93 /* create and block all threads */ 94 /* create and block all threads */
94 for (i = 0; i < nthreads; i++) { 95 for (i = 0; i < nthreads; i++) {
95 CPU_ZERO(&cpu); 96 CPU_ZERO(&cpuset);
96 CPU_SET(i % ncpus, &cpu); 97 CPU_SET(cpu->map[i % cpu->nr], &cpuset);
97 98
98 if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu)) 99 if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset))
99 err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); 100 err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
100 101
101 if (pthread_create(&w[i], &thread_attr, workerfn, NULL)) 102 if (pthread_create(&w[i], &thread_attr, workerfn, NULL))
@@ -116,19 +117,22 @@ int bench_futex_requeue(int argc, const char **argv)
116 unsigned int i, j; 117 unsigned int i, j;
117 struct sigaction act; 118 struct sigaction act;
118 pthread_attr_t thread_attr; 119 pthread_attr_t thread_attr;
120 struct cpu_map *cpu;
119 121
120 argc = parse_options(argc, argv, options, bench_futex_requeue_usage, 0); 122 argc = parse_options(argc, argv, options, bench_futex_requeue_usage, 0);
121 if (argc) 123 if (argc)
122 goto err; 124 goto err;
123 125
124 ncpus = sysconf(_SC_NPROCESSORS_ONLN); 126 cpu = cpu_map__new(NULL);
127 if (!cpu)
128 err(EXIT_FAILURE, "cpu_map__new");
125 129
126 sigfillset(&act.sa_mask); 130 sigfillset(&act.sa_mask);
127 act.sa_sigaction = toggle_done; 131 act.sa_sigaction = toggle_done;
128 sigaction(SIGINT, &act, NULL); 132 sigaction(SIGINT, &act, NULL);
129 133
130 if (!nthreads) 134 if (!nthreads)
131 nthreads = ncpus; 135 nthreads = cpu->nr;
132 136
133 worker = calloc(nthreads, sizeof(*worker)); 137 worker = calloc(nthreads, sizeof(*worker));
134 if (!worker) 138 if (!worker)
@@ -156,7 +160,7 @@ int bench_futex_requeue(int argc, const char **argv)
156 struct timeval start, end, runtime; 160 struct timeval start, end, runtime;
157 161
158 /* create, launch & block all threads */ 162 /* create, launch & block all threads */
159 block_threads(worker, thread_attr); 163 block_threads(worker, thread_attr, cpu);
160 164
161 /* make sure all threads are already blocked */ 165 /* make sure all threads are already blocked */
162 pthread_mutex_lock(&thread_lock); 166 pthread_mutex_lock(&thread_lock);
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index b4732dad9f89..4488c27e8a43 100644
--- a/tools/perf/bench/futex-wake-parallel.c
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -21,6 +21,7 @@
21#include <errno.h> 21#include <errno.h>
22#include "bench.h" 22#include "bench.h"
23#include "futex.h" 23#include "futex.h"
24#include "cpumap.h"
24 25
25#include <err.h> 26#include <err.h>
26#include <stdlib.h> 27#include <stdlib.h>
@@ -43,7 +44,7 @@ static unsigned int nblocked_threads = 0, nwaking_threads = 0;
43static pthread_mutex_t thread_lock; 44static pthread_mutex_t thread_lock;
44static pthread_cond_t thread_parent, thread_worker; 45static pthread_cond_t thread_parent, thread_worker;
45static struct stats waketime_stats, wakeup_stats; 46static struct stats waketime_stats, wakeup_stats;
46static unsigned int ncpus, threads_starting; 47static unsigned int threads_starting;
47static int futex_flag = 0; 48static int futex_flag = 0;
48 49
49static const struct option options[] = { 50static const struct option options[] = {
@@ -119,19 +120,20 @@ static void *blocked_workerfn(void *arg __maybe_unused)
119 return NULL; 120 return NULL;
120} 121}
121 122
122static void block_threads(pthread_t *w, pthread_attr_t thread_attr) 123static void block_threads(pthread_t *w, pthread_attr_t thread_attr,
124 struct cpu_map *cpu)
123{ 125{
124 cpu_set_t cpu; 126 cpu_set_t cpuset;
125 unsigned int i; 127 unsigned int i;
126 128
127 threads_starting = nblocked_threads; 129 threads_starting = nblocked_threads;
128 130
129 /* create and block all threads */ 131 /* create and block all threads */
130 for (i = 0; i < nblocked_threads; i++) { 132 for (i = 0; i < nblocked_threads; i++) {
131 CPU_ZERO(&cpu); 133 CPU_ZERO(&cpuset);
132 CPU_SET(i % ncpus, &cpu); 134 CPU_SET(cpu->map[i % cpu->nr], &cpuset);
133 135
134 if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu)) 136 if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset))
135 err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); 137 err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
136 138
137 if (pthread_create(&w[i], &thread_attr, blocked_workerfn, NULL)) 139 if (pthread_create(&w[i], &thread_attr, blocked_workerfn, NULL))
@@ -205,6 +207,7 @@ int bench_futex_wake_parallel(int argc, const char **argv)
205 struct sigaction act; 207 struct sigaction act;
206 pthread_attr_t thread_attr; 208 pthread_attr_t thread_attr;
207 struct thread_data *waking_worker; 209 struct thread_data *waking_worker;
210 struct cpu_map *cpu;
208 211
209 argc = parse_options(argc, argv, options, 212 argc = parse_options(argc, argv, options,
210 bench_futex_wake_parallel_usage, 0); 213 bench_futex_wake_parallel_usage, 0);
@@ -217,9 +220,12 @@ int bench_futex_wake_parallel(int argc, const char **argv)
217 act.sa_sigaction = toggle_done; 220 act.sa_sigaction = toggle_done;
218 sigaction(SIGINT, &act, NULL); 221 sigaction(SIGINT, &act, NULL);
219 222
220 ncpus = sysconf(_SC_NPROCESSORS_ONLN); 223 cpu = cpu_map__new(NULL);
224 if (!cpu)
225 err(EXIT_FAILURE, "calloc");
226
221 if (!nblocked_threads) 227 if (!nblocked_threads)
222 nblocked_threads = ncpus; 228 nblocked_threads = cpu->nr;
223 229
224 /* some sanity checks */ 230 /* some sanity checks */
225 if (nwaking_threads > nblocked_threads || !nwaking_threads) 231 if (nwaking_threads > nblocked_threads || !nwaking_threads)
@@ -259,7 +265,7 @@ int bench_futex_wake_parallel(int argc, const char **argv)
259 err(EXIT_FAILURE, "calloc"); 265 err(EXIT_FAILURE, "calloc");
260 266
261 /* create, launch & block all threads */ 267 /* create, launch & block all threads */
262 block_threads(blocked_worker, thread_attr); 268 block_threads(blocked_worker, thread_attr, cpu);
263 269
264 /* make sure all threads are already blocked */ 270 /* make sure all threads are already blocked */
265 pthread_mutex_lock(&thread_lock); 271 pthread_mutex_lock(&thread_lock);
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index 8c5c0b6b5c97..e8181ad7d088 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -22,6 +22,7 @@
22#include <errno.h> 22#include <errno.h>
23#include "bench.h" 23#include "bench.h"
24#include "futex.h" 24#include "futex.h"
25#include "cpumap.h"
25 26
26#include <err.h> 27#include <err.h>
27#include <stdlib.h> 28#include <stdlib.h>
@@ -89,19 +90,19 @@ static void print_summary(void)
89} 90}
90 91
91static void block_threads(pthread_t *w, 92static void block_threads(pthread_t *w,
92 pthread_attr_t thread_attr) 93 pthread_attr_t thread_attr, struct cpu_map *cpu)
93{ 94{
94 cpu_set_t cpu; 95 cpu_set_t cpuset;
95 unsigned int i; 96 unsigned int i;
96 97
97 threads_starting = nthreads; 98 threads_starting = nthreads;
98 99
99 /* create and block all threads */ 100 /* create and block all threads */
100 for (i = 0; i < nthreads; i++) { 101 for (i = 0; i < nthreads; i++) {
101 CPU_ZERO(&cpu); 102 CPU_ZERO(&cpuset);
102 CPU_SET(i % ncpus, &cpu); 103 CPU_SET(cpu->map[i % cpu->nr], &cpuset);
103 104
104 if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu)) 105 if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset))
105 err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); 106 err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
106 107
107 if (pthread_create(&w[i], &thread_attr, workerfn, NULL)) 108 if (pthread_create(&w[i], &thread_attr, workerfn, NULL))
@@ -122,6 +123,7 @@ int bench_futex_wake(int argc, const char **argv)
122 unsigned int i, j; 123 unsigned int i, j;
123 struct sigaction act; 124 struct sigaction act;
124 pthread_attr_t thread_attr; 125 pthread_attr_t thread_attr;
126 struct cpu_map *cpu;
125 127
126 argc = parse_options(argc, argv, options, bench_futex_wake_usage, 0); 128 argc = parse_options(argc, argv, options, bench_futex_wake_usage, 0);
127 if (argc) { 129 if (argc) {
@@ -129,7 +131,9 @@ int bench_futex_wake(int argc, const char **argv)
129 exit(EXIT_FAILURE); 131 exit(EXIT_FAILURE);
130 } 132 }
131 133
132 ncpus = sysconf(_SC_NPROCESSORS_ONLN); 134 cpu = cpu_map__new(NULL);
135 if (!cpu)
136 err(EXIT_FAILURE, "calloc");
133 137
134 sigfillset(&act.sa_mask); 138 sigfillset(&act.sa_mask);
135 act.sa_sigaction = toggle_done; 139 act.sa_sigaction = toggle_done;
@@ -161,7 +165,7 @@ int bench_futex_wake(int argc, const char **argv)
161 struct timeval start, end, runtime; 165 struct timeval start, end, runtime;
162 166
163 /* create, launch & block all threads */ 167 /* create, launch & block all threads */
164 block_threads(worker, thread_attr); 168 block_threads(worker, thread_attr, cpu);
165 169
166 /* make sure all threads are already blocked */ 170 /* make sure all threads are already blocked */
167 pthread_mutex_lock(&thread_lock); 171 pthread_mutex_lock(&thread_lock);