perf bench futex: Fix hung wakeup tasks after requeueing
authorDavidlohr Bueso <dave@stgolabs.net>
Fri, 24 Apr 2015 17:00:48 +0000 (10:00 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 27 Apr 2015 16:57:49 +0000 (13:57 -0300)
The futex-requeue benchmark can hang because of missing wakeups once the
benchmark is done, ie:

[Run 1]: Requeued 1024 of 1024 threads in 0.3290 ms
perf: couldn't wakeup all tasks (135/1024)

This bug, while perhaps suggesting missing wakeups in kernel futex code,
is merely a consequence of the crappy FUTEX_CMP_REQUEUE man page,
incorrectly mentioning that the number of requeued tasks is in fact
returned, not the wakeups.

This patch acknowledges this and updates the corresponding futex_wake
code around it.

Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
Cc: Mel Gorman <mgorman@suse.de>
Link: http://lkml.kernel.org/r/1429894848.10273.44.camel@stgolabs.net
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/bench/futex-requeue.c

index bedff6b..ad0d9b5 100644 (file)
@@ -132,6 +132,9 @@ int bench_futex_requeue(int argc, const char **argv,
        if (!fshared)
                futex_flag = FUTEX_PRIVATE_FLAG;
 
+       if (nrequeue > nthreads)
+               nrequeue = nthreads;
+
        printf("Run summary [PID %d]: Requeuing %d threads (from [%s] %p to %p), "
               "%d at a time.\n\n",  getpid(), nthreads,
               fshared ? "shared":"private", &futex1, &futex2, nrequeue);
@@ -161,20 +164,18 @@ int bench_futex_requeue(int argc, const char **argv,
 
                /* Ok, all threads are patiently blocked, start requeueing */
                gettimeofday(&start, NULL);
-               for (nrequeued = 0; nrequeued < nthreads; nrequeued += nrequeue) {
+               while (nrequeued < nthreads) {
                        /*
                         * Do not wakeup any tasks blocked on futex1, allowing
                         * us to really measure futex_wait functionality.
                         */
-                       futex_cmp_requeue(&futex1, 0, &futex2, 0,
-                                         nrequeue, futex_flag);
+                       nrequeued += futex_cmp_requeue(&futex1, 0, &futex2, 0,
+                                                      nrequeue, futex_flag);
                }
+
                gettimeofday(&end, NULL);
                timersub(&end, &start, &runtime);
 
-               if (nrequeued > nthreads)
-                       nrequeued = nthreads;
-
                update_stats(&requeued_stats, nrequeued);
                update_stats(&requeuetime_stats, runtime.tv_usec);
 
@@ -184,7 +185,7 @@ int bench_futex_requeue(int argc, const char **argv,
                }
 
                /* everybody should be blocked on futex2, wake'em up */
-               nrequeued = futex_wake(&futex2, nthreads, futex_flag);
+               nrequeued = futex_wake(&futex2, nrequeued, futex_flag);
                if (nthreads != nrequeued)
                        warnx("couldn't wakeup all tasks (%d/%d)", nrequeued, nthreads);