Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 052b0f6e authored by Davidlohr Bueso's avatar Davidlohr Bueso Committed by Arnaldo Carvalho de Melo
Browse files

perf bench futex: Fix hung wakeup tasks after requeueing



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: default avatarDavidlohr 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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent d13855ef
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -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,
			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);