All of lore.kernel.org
 help / color / mirror / Atom feed
From: Darren Hart <dvhltc@us.ibm.com>
To: Michel Lespinasse <walken@google.com>
Cc: linux-kernel@vger.kernel.org
Subject: Re: [PATCH] futex: add FUTEX_SET_WAIT operation
Date: Thu, 19 Nov 2009 09:03:56 -0800	[thread overview]
Message-ID: <4B057A7C.80300@us.ibm.com> (raw)
In-Reply-To: <20091118221331.GA1300@google.com>

Michel Lespinasse wrote:
> On Tue, Nov 17, 2009 at 08:16:06AM -0800, Darren Hart wrote:
>>> http://git.kernel.org/?p=linux/kernel/git/dvhart/futextest.git
>> Michael, would you be willing to include a version of this test in the  
>> above test suite? If so, then in keeping with the rest of the test suite, 
>> I would recommend splitting into two tests, one of each opcode being 
>> tested, and  add argument to define thread count. The run.sh script would 
>> then run each thread count as a separate test run.
> 
> There you go. Hope this helps. Feel free to adapt as needed.
> 
> Signed-off-by: Michel Lespinasse <walken@google.com>

My core-duo laptop hung after 256 threads. I left it running all night 
and woke to it still sitting at:

256 threads: 11792 Kiter/s (14.18s user 0.28s system 8.48s wall 1.71 cores)

Have experienced a hang with this test on any platform? I'll take a 
closer look at the source today to see if there is anything in there 
that requires a certain number of CPUs to function properly.

--
Darren

> 
> diff --git a/functional/futex_requeue_pi_mismatched_ops.c b/functional/futex_requeue_pi_mismatched_ops.c
> index 50bd07b..529f5a8 100644
> --- a/functional/futex_requeue_pi_mismatched_ops.c
> +++ b/functional/futex_requeue_pi_mismatched_ops.c
> @@ -113,7 +113,7 @@ int main(int argc, char *argv[])
>  			 * requeue_pi target and aborted. Wake the child with
>  			 * FUTEX_WAKE.
>  			 */
> -			ret = futex_wake(&f1, f1, 1, FUTEX_PRIVATE_FLAG);
> +			ret = futex_wake(&f1, 1, FUTEX_PRIVATE_FLAG);
>  			if (ret == 1)
>  				ret = 0;
>  			else if (ret < 0)
> diff --git a/include/futextest.h b/include/futextest.h
> index 2b64f79..853c3c4 100644
> --- a/include/futextest.h
> +++ b/include/futextest.h
> @@ -78,6 +78,9 @@ int _verbose = VCRITICAL;
>  #ifndef FUTEX_CMP_REQUEUE_PI
>  #define FUTEX_CMP_REQUEUE_PI		12
>  #endif
> +#ifndef FUTEX_SET_WAIT
> +#define FUTEX_SET_WAIT			13
> +#endif
>  #ifndef FUTEX_WAIT_REQUEUE_PI_PRIVATE
>  #define FUTEX_WAIT_REQUEUE_PI_PRIVATE	(FUTEX_WAIT_REQUEUE_PI | \
>  					 FUTEX_PRIVATE_FLAG)
> @@ -86,6 +89,9 @@ int _verbose = VCRITICAL;
>  #define FUTEX_CMP_REQUEUE_PI_PRIVATE	(FUTEX_CMP_REQUEUE_PI | \
>  					 FUTEX_PRIVATE_FLAG)
>  #endif
> +#ifndef FUTEX_SET_WAIT_PRIVATE
> +#define FUTEX_SET_WAIT_PRIVATE		(FUTEX_SET_WAIT | FUTEX_PRIVATE_FLAG)
> +#endif
> 
>  /** 
>   * futex() - SYS_futex syscall wrapper
> @@ -106,7 +112,7 @@ int _verbose = VCRITICAL;
>   * like-named arguments in the following wrappers except where noted below.
>   */
>  #define futex(uaddr, op, val, timeout, uaddr2, val3, opflags) \
> -	syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3);
> +	syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3)
> 
>  /**
>   * futex_wait() - block on uaddr with optional timeout
> @@ -119,8 +125,8 @@ int _verbose = VCRITICAL;
>   * futex_wake() - wake one or more tasks blocked on uaddr
>   * @nr_wake:	wake up to this many tasks
>   */
> -#define futex_wake(uaddr, val, nr_wake, opflags) \
> -	futex(uaddr, FUTEX_WAKE, val, NULL, NULL, nr_wake, opflags)
> +#define futex_wake(uaddr, nr_wake, opflags) \
> +	futex(uaddr, FUTEX_WAKE, nr_wake, NULL, NULL, 0, opflags)
> 
>  /**
>   * futex_wait_bitset() - block on uaddr with bitset
> @@ -133,8 +139,8 @@ int _verbose = VCRITICAL;
>   * futex_wake_bitset() - wake one or more tasks blocked on uaddr with bitset
>   * @bitset:	bitset to compare with that used in futex_wait_bitset
>   */
> -#define futex_wake_bitset(uaddr, val, nr_wake, bitset, opflags) \
> -	futex(uaddr, FUTEX_WAKE_BITSET, val, NULL, NULL, bitset, opflags)
> +#define futex_wake_bitset(uaddr, nr_wake, bitset, opflags) \
> +	futex(uaddr, FUTEX_WAKE_BITSET, nr_wake, NULL, NULL, bitset, opflags)
> 
>  /**
>   * futex_lock_pi() - block on uaddr as a PI mutex
> @@ -198,6 +204,14 @@ int _verbose = VCRITICAL;
>  	      opflags)
> 
>  /**
> + * futex_set_wait() - block on uaddr with bitset
> + * @setval:	value to set futex to if blocking
> + * @bitset:	bitset to be used with futex_wake_bitset
> + */
> +#define futex_set_wait(uaddr, val, setval, timeout, bitset, opflags) \
> +	futex(uaddr, FUTEX_SET_WAIT, val, timeout, setval, bitset, opflags)
> +
> +/**
>   * futex_cmpxchg() - Atomic compare and exchange
>   * @uaddr:	The address of the futex to be modified
>   * @oldval:	The expected value of the futex
> diff --git a/performance/Makefile b/performance/Makefile
> index 9589e49..c4999a8 100644
> --- a/performance/Makefile
> +++ b/performance/Makefile
> @@ -3,7 +3,7 @@ CFLAGS := $(CFLAGS) -g -O2 -Wall -D_GNU_SOURCE $(INCLUDES)
>  LDFLAGS := $(LDFLAGS) -lpthread -lrt
> 
>  HEADERS := ../include/futextest.h
> -TARGETS :=
> +TARGETS := futex_wait_test futex_setwait_test
> 
>  .PHONY: all clean
>  all: $(TARGETS)
> diff --git a/performance/futex_setwait_test.c b/performance/futex_setwait_test.c
> new file mode 100644
> index 0000000..0d09365
> --- /dev/null
> +++ b/performance/futex_setwait_test.c
> @@ -0,0 +1,71 @@
> +// Copyright 2009 Google Inc.
> +// Author: walken@google.com (Michel Lespinasse)
> +
> +#include "futextest.h"
> +#include "harness.h"
> +
> +#include <stdio.h>
> +#include <errno.h>
> +
> +
> +static inline void futex_setwait_lock(futex_t *futex)
> +{
> +	int status = *futex;
> +	if (status == 0)
> +		status = futex_cmpxchg(futex, 0, 1);
> +	if (status != 0) {
> +		int desired_status = 1;
> +		do {
> +			if (futex_set_wait(futex, 1, 2, NULL, ~0,
> +					   FUTEX_PRIVATE_FLAG) == 0) {
> +				/* We absorbed a wakeup; so make sure to
> +				   unblock next thread */
> +				desired_status = 2;
> +			}
> +			status = *futex;
> +			if (status == 0)
> +				status = futex_cmpxchg(futex, 0,
> +						       desired_status);
> +		} while (status != 0);
> +	}
> +}
> +
> +static inline void futex_cmpxchg_unlock(futex_t *futex)
> +{
> +	int status = *futex;
> +	if (status == 1)
> +		status = futex_cmpxchg(futex, 1, 0);
> +	if (status == 2) {
> +		futex_cmpxchg(futex, 2, 0);
> +		futex_wake(futex, 1, FUTEX_PRIVATE_FLAG);
> +	}
> +}
> +
> +static void * futex_setwait_test(void * dummy)
> +{
> +	struct locktest_shared * shared = dummy;
> +	int i = shared->loops;
> +	barrier_sync(&shared->barrier_before);
> +	while (i--) {
> +		futex_setwait_lock(&shared->futex);
> +		futex_cmpxchg_unlock(&shared->futex);
> +	}
> +	barrier_sync(&shared->barrier_after);
> +	return NULL;
> +}
> +
> +static int futex_setwait_supported(void)
> +{
> +	int futex = 0;
> +	futex_set_wait(futex, 1, 2, NULL, ~0, FUTEX_PRIVATE_FLAG);
> +	return errno == EWOULDBLOCK;
> +}
> +
> +int main (void)
> +{
> +	if (futex_setwait_supported()) {
> +		printf("\nFUTEX_SET_WAIT test\n");
> +		locktest(futex_setwait_test, 100000000);
> +	}
> +	return 0;
> +}
> diff --git a/performance/futex_wait_test.c b/performance/futex_wait_test.c
> new file mode 100644
> index 0000000..88ce2f2
> --- /dev/null
> +++ b/performance/futex_wait_test.c
> @@ -0,0 +1,56 @@
> +// Copyright 2009 Google Inc.
> +// Author: walken@google.com (Michel Lespinasse)
> +
> +#include "futextest.h"
> +#include "harness.h"
> +
> +#include <stdio.h>
> +
> +
> +static inline void futex_wait_lock(futex_t *futex)
> +{
> +	int status = *futex;
> +	if (status == 0)
> +		status = futex_cmpxchg(futex, 0, 1);
> +	while (status != 0) {
> +		if (status == 1)
> +			status = futex_cmpxchg(futex, 1, 2);
> +		if (status != 0) {
> +			futex_wait(futex, 2, NULL, FUTEX_PRIVATE_FLAG);
> +			status = *futex;
> +		}
> +		if (status == 0)
> +			status = futex_cmpxchg(futex, 0, 2);
> +	}
> +}
> +
> +static inline void futex_cmpxchg_unlock(futex_t *futex)
> +{
> +	int status = *futex;
> +	if (status == 1)
> +		status = futex_cmpxchg(futex, 1, 0);
> +	if (status == 2) {
> +		futex_cmpxchg(futex, 2, 0);
> +		futex_wake(futex, 1, FUTEX_PRIVATE_FLAG);
> +	}
> +}
> +
> +static void * futex_wait_test(void * dummy)
> +{
> +	struct locktest_shared * shared = dummy;
> +	int i = shared->loops;
> +	barrier_sync(&shared->barrier_before);
> +	while (i--) {
> +		futex_wait_lock(&shared->futex);
> +		futex_cmpxchg_unlock(&shared->futex);
> +	}
> +	barrier_sync(&shared->barrier_after);
> +	return NULL;
> +}
> +
> +int main (void)
> +{
> +	printf("FUTEX_WAIT test\n");
> +	locktest(futex_wait_test, 100000000);
> +	return 0;
> +}
> diff --git a/performance/harness.h b/performance/harness.h
> new file mode 100644
> index 0000000..9d74d17
> --- /dev/null
> +++ b/performance/harness.h
> @@ -0,0 +1,103 @@
> +// Copyright 2009 Google Inc.
> +// Author: walken@google.com (Michel Lespinasse)
> +
> +#include <limits.h>
> +#include <sys/times.h>
> +#include <stdio.h>
> +#include <pthread.h>
> +
> +
> +struct thread_barrier {
> +	futex_t threads;
> +	futex_t unblock;
> +};
> +
> +struct locktest_shared {
> +	struct thread_barrier barrier_before;
> +	struct thread_barrier barrier_after;
> +	int loops;
> +	futex_t futex;
> +};
> +
> +static inline void decrement(futex_t *ptr)
> +{
> +	__sync_fetch_and_add(ptr, -1);
> +}
> +
> +/* Called by main thread to initialize barrier */
> +static void barrier_init(struct thread_barrier *barrier, int threads)
> +{
> +	barrier->threads = threads;
> +	barrier->unblock = 0;
> +}
> +
> +/* Called by worker threads to synchronize with main thread */
> +static void barrier_sync(struct thread_barrier *barrier)
> +{
> +	decrement(&barrier->threads);
> +	if (barrier->threads == 0)
> +		futex_wake(&barrier->threads, 1, FUTEX_PRIVATE_FLAG);
> +	while (barrier->unblock == 0)
> +		futex_wait(&barrier->unblock, 0, NULL, FUTEX_PRIVATE_FLAG);
> +}
> +
> +/* Called by main thread to wait for all workers to reach sync point */
> +static void barrier_wait(struct thread_barrier *barrier)
> +{
> +	int threads;
> +	while ((threads = barrier->threads) > 0)
> +		futex_wait(&barrier->threads, threads, NULL,
> +			   FUTEX_PRIVATE_FLAG);
> +}
> +
> +/* Called by main thread to unblock worker threads from their sync point */
> +static void barrier_unblock(struct thread_barrier *barrier)
> +{
> +	barrier->unblock = 1;
> +	futex_wake(&barrier->unblock, INT_MAX, FUTEX_PRIVATE_FLAG);
> +}
> +
> +
> +static void locktest(void * thread_function(void *), int iterations)
> +{
> +	int threads[] = { 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 24, 32,
> +			  64, 128, 256, 512, 1024, 0 };
> +	int t;
> +	for (t = 0; threads[t]; t++) {
> +		int num_threads = threads[t];
> +		struct locktest_shared shared;
> +		pthread_t thread[num_threads];
> +		int i;
> +		clock_t before, after;
> +		struct tms tms_before, tms_after;
> +		int wall, user, system;
> +		double tick;
> +
> +		barrier_init(&shared.barrier_before, num_threads);
> +		barrier_init(&shared.barrier_after, num_threads);
> +		shared.loops = iterations / num_threads;
> +		shared.futex = 0;
> +
> +		for (i = 0; i < num_threads; i++)
> +			pthread_create(thread + i, NULL, thread_function,
> +				       &shared);
> +		barrier_wait(&shared.barrier_before);
> +		before = times(&tms_before);
> +		barrier_unblock(&shared.barrier_before);
> +		barrier_wait(&shared.barrier_after);
> +		after = times(&tms_after);
> +		wall = after - before;
> +		user = tms_after.tms_utime - tms_before.tms_utime;
> +		system = tms_after.tms_stime - tms_before.tms_stime;
> +		tick = 1.0 / sysconf(_SC_CLK_TCK);
> +		printf("%d threads: %.0f Kiter/s "
> +		       "(%.2fs user %.2fs system %.2fs wall %.2f cores)\n",
> +		       num_threads,
> +		       (num_threads * shared.loops) / (wall * tick * 1000),
> +		       user * tick, system * tick, wall * tick,
> +		       wall ? (user + system) * 1. / wall : 1.);
> +		barrier_unblock(&shared.barrier_after);
> +		for (i = 0; i < num_threads; i++)
> +			pthread_join(thread[i], NULL);
> +	}
> +}
> 
> 


-- 
Darren Hart
IBM Linux Technology Center
Real-Time Linux Team

  parent reply	other threads:[~2009-11-19 17:04 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-11-17  7:46 [PATCH] futex: add FUTEX_SET_WAIT operation Michel Lespinasse
2009-11-17  8:18 ` Ingo Molnar
2009-11-17  8:55   ` Peter Zijlstra
2009-11-17 16:16     ` Darren Hart
2009-11-18  3:37       ` Michel Lespinasse
2009-11-18  5:29         ` Darren Hart
2009-11-24 14:39         ` [PATCH 0/3] perf bench: Add new benchmark for futex subsystem Hitoshi Mitake
2009-11-24 14:39         ` [PATCH 1/3] perf bench: Add wrappers for atomic operation of GCC Hitoshi Mitake
2009-11-24 16:20           ` Darren Hart
2009-11-26  5:44             ` Hitoshi Mitake
2009-11-24 14:39         ` [PATCH 2/3] perf bench: Add new files for futex performance test Hitoshi Mitake
2009-11-24 16:33           ` Darren Hart
2009-11-26  5:53             ` Hitoshi Mitake
2009-11-26  5:56               ` [PATCH] futextest: Make locktest() in harness.h more general Hitoshi Mitake
2009-11-24 14:39         ` [PATCH 3/3] perf bench: Fix misc files to build files related to futex Hitoshi Mitake
2009-11-18 22:13       ` [PATCH] futex: add FUTEX_SET_WAIT operation Michel Lespinasse
2009-11-19  6:51         ` Darren Hart
2009-11-19 17:03         ` Darren Hart [this message]
     [not found]           ` <8d20b11a0911191325u49624854u6132594f13b0718c@mail.gmail.com>
2009-11-19 23:13             ` Darren Hart
2009-11-21  2:36               ` Michel Lespinasse
2009-11-23 17:21                 ` Darren Hart
2009-11-17 17:24     ` Ingo Molnar
2009-11-17 17:27       ` Darren Hart
2009-11-18  1:49       ` Hitoshi Mitake
2009-11-17  8:50 ` Peter Zijlstra
2009-11-17 15:24   ` Linus Torvalds
2009-11-18  4:21     ` Michel Lespinasse
2009-11-18  5:40       ` Darren Hart
2009-11-30 22:09   ` Darren Hart
2009-12-03  6:55   ` [PATCH] futex: add FUTEX_SET_WAIT operation (and ADAPTIVE) Darren Hart
2009-11-17 17:22 ` [PATCH] futex: add FUTEX_SET_WAIT operation Darren Hart
2009-11-18  3:29   ` Michel Lespinasse
2009-11-18  0:13 ` Darren Hart

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4B057A7C.80300@us.ibm.com \
    --to=dvhltc@us.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=walken@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.