summaryrefslogtreecommitdiffstats
path: root/src/cyclictest/cyclictest.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cyclictest/cyclictest.c')
-rw-r--r--src/cyclictest/cyclictest.c92
1 files changed, 75 insertions, 17 deletions
diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
index 7ca621b..ca3286f 100644
--- a/src/cyclictest/cyclictest.c
+++ b/src/cyclictest/cyclictest.c
@@ -975,9 +975,18 @@ static void display_help(int error)
printf("cyclictest V %1.2f\n", VERSION_STRING);
printf("Usage:\n"
"cyclictest <options>\n\n"
+#if LIBNUMA_API_VERSION >= 2
+ "-a [CPUSET] --affinity Run thread #N on processor #N, if possible, or if CPUSET\n"
+ " given, pin threads to that set of processors in round-\n"
+ " robin order. E.g. -a 2 pins all threads to CPU 2,\n"
+ " but -a 3-5,0 -t 5 will run the first and fifth\n"
+ " threads on CPU (0),thread #2 on CPU 3, thread #3\n"
+ " on CPU 4, and thread #5 on CPU 5.\n"
+#else
"-a [NUM] --affinity run thread #N on processor #N, if possible\n"
" with NUM pin all threads to the processor NUM\n"
"-A USEC --aligned=USEC align thread wakeups to a specific offset\n"
+#endif
"-b USEC --breaktrace=USEC send break trace command when latency > USEC\n"
"-B --preemptirqs both preempt and irqsoff tracing (used with -b)\n"
"-c CLOCK --clock=CLOCK select clock\n"
@@ -1050,7 +1059,7 @@ static int clocksel = 0;
static int quiet;
static int interval = DEFAULT_INTERVAL;
static int distance = -1;
-static int affinity = 0;
+static struct bitmask *affinity_mask = NULL;
static int smp = 0;
enum {
@@ -1065,6 +1074,50 @@ static int clocksources[] = {
CLOCK_REALTIME,
};
+static unsigned int is_cpumask_zero(const struct bitmask *mask)
+{
+ return (rt_numa_bitmask_count(mask) == 0);
+}
+
+static int cpu_for_thread(int thread_num, int max_cpus)
+{
+ unsigned int m, cpu, i, num_cpus;
+ num_cpus = rt_numa_bitmask_count(affinity_mask);
+
+ m = thread_num % num_cpus;
+
+ /* there are num_cpus bits set, we want position of m'th one */
+ for (i = 0, cpu = 0; i < max_cpus; i++) {
+ if (rt_numa_bitmask_isbitset(affinity_mask, i)) {
+ if (cpu == m)
+ return i;
+ cpu++;
+ }
+ }
+ fprintf(stderr, "Bug in cpu mask handling code.\n");
+ return 0;
+}
+
+
+static void parse_cpumask(const char *option, const int max_cpus)
+{
+ affinity_mask = rt_numa_parse_cpustring(option, max_cpus);
+ if (affinity_mask) {
+ if (is_cpumask_zero(affinity_mask)) {
+ rt_bitmask_free(affinity_mask);
+ affinity_mask = NULL;
+ }
+ }
+ if (!affinity_mask)
+ display_help(1);
+
+ if (verbose) {
+ printf("%s: Using %u cpus.\n", __func__,
+ rt_numa_bitmask_count(affinity_mask));
+ }
+}
+
+
static void handlepolicy(char *polname)
{
if (strncasecmp(polname, "other", 5) == 0)
@@ -1119,11 +1172,10 @@ enum option_values {
};
/* Process commandline options */
-static void process_options (int argc, char *argv[])
+static void process_options (int argc, char *argv[], int max_cpus)
{
int error = 0;
int option_affinity = 0;
- int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
for (;;) {
int option_index = 0;
@@ -1187,10 +1239,10 @@ static void process_options (int argc, char *argv[])
if (smp || numa)
break;
if (optarg != NULL) {
- affinity = atoi(optarg);
+ parse_cpumask(optarg, max_cpus);
setaffinity = AFFINITY_SPECIFIED;
} else if (optind<argc && atoi(argv[optind])) {
- affinity = atoi(argv[optind]);
+ parse_cpumask(argv[optind], max_cpus);
setaffinity = AFFINITY_SPECIFIED;
} else {
setaffinity = AFFINITY_USEALL;
@@ -1389,15 +1441,7 @@ static void process_options (int argc, char *argv[])
}
}
- if (setaffinity == AFFINITY_SPECIFIED) {
- if (affinity < 0)
- error = 1;
- if (affinity >= max_cpus) {
- warn("CPU #%d not found, only %d CPUs available\n",
- affinity, max_cpus);
- error = 1;
- }
- } else if (tracelimit)
+ if (tracelimit)
fileprefix = procfileprefix;
if (clocksel < 0 || clocksel > ARRAY_SIZE(clocksources))
@@ -1450,8 +1494,11 @@ static void process_options (int argc, char *argv[])
pthread_barrier_init(&align_barr, NULL, num_threads);
}
- if (error)
+ if (error) {
+ if (affinity_mask)
+ rt_bitmask_free(affinity_mask);
display_help(1);
+ }
}
static int check_kernel(void)
@@ -1693,11 +1740,14 @@ int main(int argc, char **argv)
int i, ret = -1;
int status;
- process_options(argc, argv);
+ process_options(argc, argv, max_cpus);
if (check_privs())
exit(EXIT_FAILURE);
+ if (verbose)
+ printf("Max CPUs = %d\n", max_cpus);
+
/* Checks if numa is on, program exits if numa on but not available */
numa_on_and_available();
@@ -1929,7 +1979,12 @@ int main(int argc, char **argv)
par->tnum = i;
switch (setaffinity) {
case AFFINITY_UNSPECIFIED: par->cpu = -1; break;
- case AFFINITY_SPECIFIED: par->cpu = affinity; break;
+ case AFFINITY_SPECIFIED:
+ par->cpu = cpu_for_thread(i, max_cpus);
+ if (verbose)
+ printf("Thread %d using cpu %d.\n", i,
+ par->cpu);
+ break;
case AFFINITY_USEALL: par->cpu = i % max_cpus; break;
}
stat->min = 1000000;
@@ -2073,5 +2128,8 @@ int main(int argc, char **argv)
if (latency_target_fd >= 0)
close(latency_target_fd);
+ if (affinity_mask)
+ rt_bitmask_free(affinity_mask);
+
exit(ret);
}