Commit 3b2323c2 authored by Davidlohr Bueso's avatar Davidlohr Bueso Committed by Arnaldo Carvalho de Melo

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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Originally-from: James Yang <james.yang@arm.com>
Signed-off-by: default avatarDavidlohr 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.netSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 17a68b83
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <subcmd/parse-options.h> #include <subcmd/parse-options.h>
#include "bench.h" #include "bench.h"
#include "futex.h" #include "futex.h"
#include "cpumap.h"
#include <err.h> #include <err.h>
#include <sys/time.h> #include <sys/time.h>
...@@ -118,11 +119,12 @@ static void print_summary(void) ...@@ -118,11 +119,12 @@ static void print_summary(void)
int bench_futex_hash(int argc, const char **argv) int bench_futex_hash(int argc, const char **argv)
{ {
int ret = 0; int ret = 0;
cpu_set_t cpu; cpu_set_t cpuset;
struct sigaction act; struct sigaction act;
unsigned int i, ncpus; unsigned int i;
pthread_attr_t thread_attr; pthread_attr_t thread_attr;
struct worker *worker = NULL; struct worker *worker = NULL;
struct cpu_map *cpu;
argc = parse_options(argc, argv, options, bench_futex_hash_usage, 0); argc = parse_options(argc, argv, options, bench_futex_hash_usage, 0);
if (argc) { if (argc) {
...@@ -130,14 +132,16 @@ int bench_futex_hash(int argc, const char **argv) ...@@ -130,14 +132,16 @@ int bench_futex_hash(int argc, const char **argv)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
ncpus = sysconf(_SC_NPROCESSORS_ONLN); cpu = cpu_map__new(NULL);
if (!cpu)
goto errmem;
sigfillset(&act.sa_mask); sigfillset(&act.sa_mask);
act.sa_sigaction = toggle_done; act.sa_sigaction = toggle_done;
sigaction(SIGINT, &act, NULL); sigaction(SIGINT, &act, NULL);
if (!nthreads) /* default to the number of CPUs */ if (!nthreads) /* default to the number of CPUs */
nthreads = ncpus; nthreads = cpu->nr;
worker = calloc(nthreads, sizeof(*worker)); worker = calloc(nthreads, sizeof(*worker));
if (!worker) if (!worker)
...@@ -163,10 +167,10 @@ int bench_futex_hash(int argc, const char **argv) ...@@ -163,10 +167,10 @@ int bench_futex_hash(int argc, const char **argv)
if (!worker[i].futex) if (!worker[i].futex)
goto errmem; goto errmem;
CPU_ZERO(&cpu); CPU_ZERO(&cpuset);
CPU_SET(i % ncpus, &cpu); CPU_SET(cpu->map[i % cpu->nr], &cpuset);
ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu); ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset);
if (ret) if (ret)
err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
...@@ -217,6 +221,7 @@ int bench_futex_hash(int argc, const char **argv) ...@@ -217,6 +221,7 @@ int bench_futex_hash(int argc, const char **argv)
print_summary(); print_summary();
free(worker); free(worker);
free(cpu);
return ret; return ret;
errmem: errmem:
err(EXIT_FAILURE, "calloc"); err(EXIT_FAILURE, "calloc");
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <errno.h> #include <errno.h>
#include "bench.h" #include "bench.h"
#include "futex.h" #include "futex.h"
#include "cpumap.h"
#include <err.h> #include <err.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -32,7 +33,7 @@ static struct worker *worker; ...@@ -32,7 +33,7 @@ static struct worker *worker;
static unsigned int nsecs = 10; static unsigned int nsecs = 10;
static bool silent = false, multi = false; static bool silent = false, multi = false;
static bool done = false, fshared = false; static bool done = false, fshared = false;
static unsigned int ncpus, nthreads = 0; static unsigned int nthreads = 0;
static int futex_flag = 0; static int futex_flag = 0;
struct timeval start, end, runtime; struct timeval start, end, runtime;
static pthread_mutex_t thread_lock; static pthread_mutex_t thread_lock;
...@@ -113,9 +114,10 @@ static void *workerfn(void *arg) ...@@ -113,9 +114,10 @@ static void *workerfn(void *arg)
return NULL; return NULL;
} }
static void create_threads(struct worker *w, pthread_attr_t thread_attr) static void create_threads(struct worker *w, pthread_attr_t thread_attr,
struct cpu_map *cpu)
{ {
cpu_set_t cpu; cpu_set_t cpuset;
unsigned int i; unsigned int i;
threads_starting = nthreads; threads_starting = nthreads;
...@@ -130,10 +132,10 @@ static void create_threads(struct worker *w, pthread_attr_t thread_attr) ...@@ -130,10 +132,10 @@ static void create_threads(struct worker *w, pthread_attr_t thread_attr)
} else } else
worker[i].futex = &global_futex; worker[i].futex = &global_futex;
CPU_ZERO(&cpu); CPU_ZERO(&cpuset);
CPU_SET(i % ncpus, &cpu); CPU_SET(cpu->map[i % cpu->nr], &cpuset);
if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu)) if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset))
err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
if (pthread_create(&w[i].thread, &thread_attr, workerfn, &worker[i])) 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,19 +149,22 @@ int bench_futex_lock_pi(int argc, const char **argv)
unsigned int i; unsigned int i;
struct sigaction act; struct sigaction act;
pthread_attr_t thread_attr; pthread_attr_t thread_attr;
struct cpu_map *cpu;
argc = parse_options(argc, argv, options, bench_futex_lock_pi_usage, 0); argc = parse_options(argc, argv, options, bench_futex_lock_pi_usage, 0);
if (argc) if (argc)
goto err; goto err;
ncpus = sysconf(_SC_NPROCESSORS_ONLN); cpu = cpu_map__new(NULL);
if (!cpu)
err(EXIT_FAILURE, "calloc");
sigfillset(&act.sa_mask); sigfillset(&act.sa_mask);
act.sa_sigaction = toggle_done; act.sa_sigaction = toggle_done;
sigaction(SIGINT, &act, NULL); sigaction(SIGINT, &act, NULL);
if (!nthreads) if (!nthreads)
nthreads = ncpus; nthreads = cpu->nr;
worker = calloc(nthreads, sizeof(*worker)); worker = calloc(nthreads, sizeof(*worker));
if (!worker) if (!worker)
...@@ -180,7 +185,7 @@ int bench_futex_lock_pi(int argc, const char **argv) ...@@ -180,7 +185,7 @@ int bench_futex_lock_pi(int argc, const char **argv)
pthread_attr_init(&thread_attr); pthread_attr_init(&thread_attr);
gettimeofday(&start, NULL); gettimeofday(&start, NULL);
create_threads(worker, thread_attr); create_threads(worker, thread_attr, cpu);
pthread_attr_destroy(&thread_attr); pthread_attr_destroy(&thread_attr);
pthread_mutex_lock(&thread_lock); pthread_mutex_lock(&thread_lock);
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <errno.h> #include <errno.h>
#include "bench.h" #include "bench.h"
#include "futex.h" #include "futex.h"
#include "cpumap.h"
#include <err.h> #include <err.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -40,7 +41,7 @@ static bool done = false, silent = false, fshared = false; ...@@ -40,7 +41,7 @@ static bool done = false, silent = false, fshared = false;
static pthread_mutex_t thread_lock; static pthread_mutex_t thread_lock;
static pthread_cond_t thread_parent, thread_worker; static pthread_cond_t thread_parent, thread_worker;
static struct stats requeuetime_stats, requeued_stats; static struct stats requeuetime_stats, requeued_stats;
static unsigned int ncpus, threads_starting, nthreads = 0; static unsigned int threads_starting, nthreads = 0;
static int futex_flag = 0; static int futex_flag = 0;
static const struct option options[] = { static const struct option options[] = {
...@@ -83,19 +84,19 @@ static void *workerfn(void *arg __maybe_unused) ...@@ -83,19 +84,19 @@ static void *workerfn(void *arg __maybe_unused)
} }
static void block_threads(pthread_t *w, static void block_threads(pthread_t *w,
pthread_attr_t thread_attr) pthread_attr_t thread_attr, struct cpu_map *cpu)
{ {
cpu_set_t cpu; cpu_set_t cpuset;
unsigned int i; unsigned int i;
threads_starting = nthreads; threads_starting = nthreads;
/* create and block all threads */ /* create and block all threads */
for (i = 0; i < nthreads; i++) { for (i = 0; i < nthreads; i++) {
CPU_ZERO(&cpu); CPU_ZERO(&cpuset);
CPU_SET(i % ncpus, &cpu); CPU_SET(cpu->map[i % cpu->nr], &cpuset);
if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu)) if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset))
err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
if (pthread_create(&w[i], &thread_attr, workerfn, NULL)) if (pthread_create(&w[i], &thread_attr, workerfn, NULL))
...@@ -116,19 +117,22 @@ int bench_futex_requeue(int argc, const char **argv) ...@@ -116,19 +117,22 @@ int bench_futex_requeue(int argc, const char **argv)
unsigned int i, j; unsigned int i, j;
struct sigaction act; struct sigaction act;
pthread_attr_t thread_attr; pthread_attr_t thread_attr;
struct cpu_map *cpu;
argc = parse_options(argc, argv, options, bench_futex_requeue_usage, 0); argc = parse_options(argc, argv, options, bench_futex_requeue_usage, 0);
if (argc) if (argc)
goto err; goto err;
ncpus = sysconf(_SC_NPROCESSORS_ONLN); cpu = cpu_map__new(NULL);
if (!cpu)
err(EXIT_FAILURE, "cpu_map__new");
sigfillset(&act.sa_mask); sigfillset(&act.sa_mask);
act.sa_sigaction = toggle_done; act.sa_sigaction = toggle_done;
sigaction(SIGINT, &act, NULL); sigaction(SIGINT, &act, NULL);
if (!nthreads) if (!nthreads)
nthreads = ncpus; nthreads = cpu->nr;
worker = calloc(nthreads, sizeof(*worker)); worker = calloc(nthreads, sizeof(*worker));
if (!worker) if (!worker)
...@@ -156,7 +160,7 @@ int bench_futex_requeue(int argc, const char **argv) ...@@ -156,7 +160,7 @@ int bench_futex_requeue(int argc, const char **argv)
struct timeval start, end, runtime; struct timeval start, end, runtime;
/* create, launch & block all threads */ /* create, launch & block all threads */
block_threads(worker, thread_attr); block_threads(worker, thread_attr, cpu);
/* make sure all threads are already blocked */ /* make sure all threads are already blocked */
pthread_mutex_lock(&thread_lock); pthread_mutex_lock(&thread_lock);
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <errno.h> #include <errno.h>
#include "bench.h" #include "bench.h"
#include "futex.h" #include "futex.h"
#include "cpumap.h"
#include <err.h> #include <err.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -43,7 +44,7 @@ static unsigned int nblocked_threads = 0, nwaking_threads = 0; ...@@ -43,7 +44,7 @@ static unsigned int nblocked_threads = 0, nwaking_threads = 0;
static pthread_mutex_t thread_lock; static pthread_mutex_t thread_lock;
static pthread_cond_t thread_parent, thread_worker; static pthread_cond_t thread_parent, thread_worker;
static struct stats waketime_stats, wakeup_stats; static struct stats waketime_stats, wakeup_stats;
static unsigned int ncpus, threads_starting; static unsigned int threads_starting;
static int futex_flag = 0; static int futex_flag = 0;
static const struct option options[] = { static const struct option options[] = {
...@@ -119,19 +120,20 @@ static void *blocked_workerfn(void *arg __maybe_unused) ...@@ -119,19 +120,20 @@ static void *blocked_workerfn(void *arg __maybe_unused)
return NULL; return NULL;
} }
static void block_threads(pthread_t *w, pthread_attr_t thread_attr) static void block_threads(pthread_t *w, pthread_attr_t thread_attr,
struct cpu_map *cpu)
{ {
cpu_set_t cpu; cpu_set_t cpuset;
unsigned int i; unsigned int i;
threads_starting = nblocked_threads; threads_starting = nblocked_threads;
/* create and block all threads */ /* create and block all threads */
for (i = 0; i < nblocked_threads; i++) { for (i = 0; i < nblocked_threads; i++) {
CPU_ZERO(&cpu); CPU_ZERO(&cpuset);
CPU_SET(i % ncpus, &cpu); CPU_SET(cpu->map[i % cpu->nr], &cpuset);
if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu)) if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset))
err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
if (pthread_create(&w[i], &thread_attr, blocked_workerfn, NULL)) 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,6 +207,7 @@ int bench_futex_wake_parallel(int argc, const char **argv)
struct sigaction act; struct sigaction act;
pthread_attr_t thread_attr; pthread_attr_t thread_attr;
struct thread_data *waking_worker; struct thread_data *waking_worker;
struct cpu_map *cpu;
argc = parse_options(argc, argv, options, argc = parse_options(argc, argv, options,
bench_futex_wake_parallel_usage, 0); bench_futex_wake_parallel_usage, 0);
...@@ -217,9 +220,12 @@ int bench_futex_wake_parallel(int argc, const char **argv) ...@@ -217,9 +220,12 @@ int bench_futex_wake_parallel(int argc, const char **argv)
act.sa_sigaction = toggle_done; act.sa_sigaction = toggle_done;
sigaction(SIGINT, &act, NULL); sigaction(SIGINT, &act, NULL);
ncpus = sysconf(_SC_NPROCESSORS_ONLN); cpu = cpu_map__new(NULL);
if (!cpu)
err(EXIT_FAILURE, "calloc");
if (!nblocked_threads) if (!nblocked_threads)
nblocked_threads = ncpus; nblocked_threads = cpu->nr;
/* some sanity checks */ /* some sanity checks */
if (nwaking_threads > nblocked_threads || !nwaking_threads) if (nwaking_threads > nblocked_threads || !nwaking_threads)
...@@ -259,7 +265,7 @@ int bench_futex_wake_parallel(int argc, const char **argv) ...@@ -259,7 +265,7 @@ int bench_futex_wake_parallel(int argc, const char **argv)
err(EXIT_FAILURE, "calloc"); err(EXIT_FAILURE, "calloc");
/* create, launch & block all threads */ /* create, launch & block all threads */
block_threads(blocked_worker, thread_attr); block_threads(blocked_worker, thread_attr, cpu);
/* make sure all threads are already blocked */ /* make sure all threads are already blocked */
pthread_mutex_lock(&thread_lock); pthread_mutex_lock(&thread_lock);
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <errno.h> #include <errno.h>
#include "bench.h" #include "bench.h"
#include "futex.h" #include "futex.h"
#include "cpumap.h"
#include <err.h> #include <err.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -89,19 +90,19 @@ static void print_summary(void) ...@@ -89,19 +90,19 @@ static void print_summary(void)
} }
static void block_threads(pthread_t *w, static void block_threads(pthread_t *w,
pthread_attr_t thread_attr) pthread_attr_t thread_attr, struct cpu_map *cpu)
{ {
cpu_set_t cpu; cpu_set_t cpuset;
unsigned int i; unsigned int i;
threads_starting = nthreads; threads_starting = nthreads;
/* create and block all threads */ /* create and block all threads */
for (i = 0; i < nthreads; i++) { for (i = 0; i < nthreads; i++) {
CPU_ZERO(&cpu); CPU_ZERO(&cpuset);
CPU_SET(i % ncpus, &cpu); CPU_SET(cpu->map[i % cpu->nr], &cpuset);
if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu)) if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset))
err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
if (pthread_create(&w[i], &thread_attr, workerfn, NULL)) if (pthread_create(&w[i], &thread_attr, workerfn, NULL))
...@@ -122,6 +123,7 @@ int bench_futex_wake(int argc, const char **argv) ...@@ -122,6 +123,7 @@ int bench_futex_wake(int argc, const char **argv)
unsigned int i, j; unsigned int i, j;
struct sigaction act; struct sigaction act;
pthread_attr_t thread_attr; pthread_attr_t thread_attr;
struct cpu_map *cpu;
argc = parse_options(argc, argv, options, bench_futex_wake_usage, 0); argc = parse_options(argc, argv, options, bench_futex_wake_usage, 0);
if (argc) { if (argc) {
...@@ -129,7 +131,9 @@ int bench_futex_wake(int argc, const char **argv) ...@@ -129,7 +131,9 @@ int bench_futex_wake(int argc, const char **argv)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
ncpus = sysconf(_SC_NPROCESSORS_ONLN); cpu = cpu_map__new(NULL);
if (!cpu)
err(EXIT_FAILURE, "calloc");
sigfillset(&act.sa_mask); sigfillset(&act.sa_mask);
act.sa_sigaction = toggle_done; act.sa_sigaction = toggle_done;
...@@ -161,7 +165,7 @@ int bench_futex_wake(int argc, const char **argv) ...@@ -161,7 +165,7 @@ int bench_futex_wake(int argc, const char **argv)
struct timeval start, end, runtime; struct timeval start, end, runtime;
/* create, launch & block all threads */ /* create, launch & block all threads */
block_threads(worker, thread_attr); block_threads(worker, thread_attr, cpu);
/* make sure all threads are already blocked */ /* make sure all threads are already blocked */
pthread_mutex_lock(&thread_lock); pthread_mutex_lock(&thread_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment