Home | History | Annotate | Line # | Download | only in sys
t_futex_ops.c revision 1.5.2.1
      1  1.5.2.1   thorpej /* $NetBSD: t_futex_ops.c,v 1.5.2.1 2020/11/01 15:22:58 thorpej Exp $ */
      2      1.1   thorpej 
      3      1.1   thorpej /*-
      4      1.1   thorpej  * Copyright (c) 2019, 2020 The NetBSD Foundation, Inc.
      5      1.1   thorpej  * All rights reserved.
      6      1.1   thorpej  *
      7      1.1   thorpej  * Redistribution and use in source and binary forms, with or without
      8      1.1   thorpej  * modification, are permitted provided that the following conditions
      9      1.1   thorpej  * are met:
     10      1.1   thorpej  * 1. Redistributions of source code must retain the above copyright
     11      1.1   thorpej  *    notice, this list of conditions and the following disclaimer.
     12      1.1   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     13      1.1   thorpej  *    notice, this list of conditions and the following disclaimer in the
     14      1.1   thorpej  *    documentation and/or other materials provided with the distribution.
     15      1.1   thorpej  *
     16      1.1   thorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17      1.1   thorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18      1.1   thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19      1.1   thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20      1.1   thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21      1.1   thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22      1.1   thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23      1.1   thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24      1.1   thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25      1.1   thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26      1.1   thorpej  * POSSIBILITY OF SUCH DAMAGE.
     27      1.1   thorpej  */
     28      1.1   thorpej 
     29      1.1   thorpej #include <sys/cdefs.h>
     30      1.1   thorpej __COPYRIGHT("@(#) Copyright (c) 2019, 2020\
     31      1.1   thorpej  The NetBSD Foundation, inc. All rights reserved.");
     32  1.5.2.1   thorpej __RCSID("$NetBSD: t_futex_ops.c,v 1.5.2.1 2020/11/01 15:22:58 thorpej Exp $");
     33      1.1   thorpej 
     34      1.1   thorpej #include <sys/fcntl.h>
     35      1.1   thorpej #include <sys/mman.h>
     36      1.1   thorpej #include <sys/wait.h>
     37      1.1   thorpej #include <atomic.h>
     38      1.1   thorpej #include <errno.h>
     39      1.1   thorpej #include <lwp.h>
     40      1.1   thorpej #include <stdlib.h>
     41      1.1   thorpej #include <stdio.h>
     42      1.3   thorpej #include <signal.h>
     43      1.1   thorpej #include <time.h>
     44      1.1   thorpej #include <limits.h>
     45      1.4   thorpej #include <sched.h>
     46      1.1   thorpej #include <unistd.h>
     47      1.1   thorpej 
     48      1.1   thorpej #include <atf-c.h>
     49      1.1   thorpej 
     50      1.1   thorpej #include <libc/include/futex_private.h>
     51      1.1   thorpej 
     52      1.1   thorpej #define	LOAD(x)		(*(volatile int *)(x))
     53      1.1   thorpej #define	STORE(x, y)	*(volatile int *)(x) = (y)
     54      1.1   thorpej 
     55      1.1   thorpej #if 0
     56      1.1   thorpej #define	DPRINTF(x)	printf x
     57      1.1   thorpej #else
     58      1.1   thorpej #define	DPRINTF(x)	__nothing
     59      1.1   thorpej #endif
     60      1.1   thorpej 
     61      1.1   thorpej #define	STACK_SIZE	65536
     62      1.1   thorpej 
     63      1.1   thorpej static volatile int futex_word;
     64      1.1   thorpej static volatile int futex_word1;
     65      1.1   thorpej 
     66      1.1   thorpej static volatile unsigned int nlwps_running;
     67      1.1   thorpej 
     68      1.1   thorpej struct lwp_data {
     69      1.1   thorpej 	ucontext_t	context;
     70      1.1   thorpej 	void		(*func)(void *);
     71      1.1   thorpej 	void		*stack_base;
     72      1.1   thorpej 	lwpid_t		lwpid;
     73      1.1   thorpej 	pid_t		child;
     74      1.1   thorpej 	lwpid_t		threadid;
     75      1.1   thorpej 	int		wait_op;
     76      1.1   thorpej 	int		op_flags;
     77      1.1   thorpej 	int		bitset;
     78      1.1   thorpej 	volatile int	*futex_ptr;
     79      1.1   thorpej 	volatile int	*error_ptr;
     80      1.1   thorpej 	int		block_val;
     81  1.5.2.1   thorpej 	pri_t		rt_prio;
     82      1.1   thorpej 
     83      1.1   thorpej 	void		(*exit_func)(void);
     84      1.1   thorpej 
     85      1.1   thorpej 	int		futex_error;
     86      1.1   thorpej };
     87      1.1   thorpej 
     88      1.1   thorpej #define	WAITER_LWP0		0
     89      1.1   thorpej #define	WAITER_LWP1		1
     90      1.1   thorpej #define	WAITER_LWP2		2
     91      1.1   thorpej #define	WAITER_LWP3		3
     92      1.1   thorpej #define	WAITER_LWP4		4
     93      1.1   thorpej #define	WAITER_LWP5		5
     94      1.1   thorpej #define	NLWPS			6
     95      1.1   thorpej 
     96      1.1   thorpej struct lwp_data lwp_data[NLWPS];
     97      1.1   thorpej 
     98      1.1   thorpej static const char *bs_path = "t_futex_ops_backing_store";
     99      1.1   thorpej static int bs_fd = -1;
    100      1.1   thorpej static int *bs_addr = MAP_FAILED;
    101      1.1   thorpej static void *bs_source_buffer = NULL;
    102      1.1   thorpej static void *bs_verify_buffer = NULL;
    103      1.1   thorpej static long bs_pagesize;
    104      1.1   thorpej 
    105  1.5.2.1   thorpej static int pri_min;
    106  1.5.2.1   thorpej static int pri_max;
    107  1.5.2.1   thorpej 
    108  1.5.2.1   thorpej static void
    109  1.5.2.1   thorpej setup_rt_params(void)
    110  1.5.2.1   thorpej {
    111  1.5.2.1   thorpej 	long pri;
    112  1.5.2.1   thorpej 
    113  1.5.2.1   thorpej 	ATF_REQUIRE((pri = sysconf(_SC_SCHED_PRI_MIN)) != -1);
    114  1.5.2.1   thorpej 	pri_min = (int)pri;
    115  1.5.2.1   thorpej 	ATF_REQUIRE((pri = sysconf(_SC_SCHED_PRI_MAX)) != -1);
    116  1.5.2.1   thorpej 	pri_max = (int)pri;
    117  1.5.2.1   thorpej }
    118  1.5.2.1   thorpej 
    119      1.1   thorpej static void
    120      1.1   thorpej create_lwp_waiter(struct lwp_data *d)
    121      1.1   thorpej {
    122      1.1   thorpej 	ATF_REQUIRE(_lwp_create(&d->context, 0, &d->lwpid) == 0);
    123      1.1   thorpej }
    124      1.1   thorpej 
    125      1.1   thorpej static void
    126      1.1   thorpej exit_lwp_waiter(void)
    127      1.1   thorpej {
    128      1.1   thorpej 	_lwp_exit();
    129      1.1   thorpej }
    130      1.1   thorpej 
    131      1.1   thorpej static void
    132      1.1   thorpej reap_lwp_waiter(struct lwp_data *d)
    133      1.1   thorpej {
    134      1.1   thorpej 	ATF_REQUIRE(_lwp_wait(d->lwpid, NULL) == 0);
    135      1.1   thorpej }
    136      1.1   thorpej 
    137      1.1   thorpej static void
    138      1.1   thorpej create_proc_waiter(struct lwp_data *d)
    139      1.1   thorpej {
    140      1.1   thorpej 	pid_t pid;
    141      1.1   thorpej 
    142      1.1   thorpej 	ATF_REQUIRE((pid = fork()) != -1);
    143      1.1   thorpej 	if (pid == 0) {
    144      1.1   thorpej 		(*d->func)(d);
    145      1.1   thorpej 		_exit(666);		/* backstop */
    146      1.1   thorpej 	} else
    147      1.1   thorpej 		d->child = pid;
    148      1.1   thorpej }
    149      1.1   thorpej 
    150      1.1   thorpej static void
    151      1.1   thorpej exit_proc_waiter(void)
    152      1.1   thorpej {
    153      1.1   thorpej 	_exit(0);
    154      1.1   thorpej }
    155      1.1   thorpej 
    156      1.1   thorpej static void
    157      1.1   thorpej reap_proc_waiter(struct lwp_data *d)
    158      1.1   thorpej {
    159      1.1   thorpej 	int status;
    160      1.1   thorpej 
    161      1.1   thorpej 	ATF_REQUIRE(waitpid(d->child, &status, 0) == d->child);
    162      1.1   thorpej 	ATF_REQUIRE(WIFEXITED(status));
    163      1.1   thorpej 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
    164      1.1   thorpej }
    165      1.1   thorpej 
    166      1.1   thorpej static void
    167      1.1   thorpej setup_lwp_context(struct lwp_data *d, void (*func)(void *))
    168      1.1   thorpej {
    169      1.1   thorpej 
    170      1.1   thorpej 	memset(d, 0, sizeof(*d));
    171      1.1   thorpej 	d->stack_base = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
    172      1.1   thorpej 	    MAP_ANON | MAP_STACK | MAP_PRIVATE, -1, 0);
    173      1.1   thorpej 	ATF_REQUIRE(d->stack_base != MAP_FAILED);
    174      1.1   thorpej 	_lwp_makecontext(&d->context, func, d, NULL, d->stack_base, STACK_SIZE);
    175      1.1   thorpej 	d->threadid = 0;
    176      1.1   thorpej 	d->func = func;
    177      1.1   thorpej }
    178      1.1   thorpej 
    179      1.1   thorpej static void
    180      1.1   thorpej simple_test_waiter_lwp(void *arg)
    181      1.1   thorpej {
    182      1.1   thorpej 	struct lwp_data *d = arg;
    183      1.1   thorpej 
    184      1.1   thorpej 	d->threadid = _lwp_self();
    185      1.1   thorpej 
    186      1.3   thorpej 	membar_producer();
    187      1.1   thorpej 	atomic_inc_uint(&nlwps_running);
    188      1.1   thorpej 	membar_sync();
    189      1.1   thorpej 
    190      1.1   thorpej 	if (__futex(d->futex_ptr, d->wait_op | d->op_flags,
    191      1.1   thorpej 		    d->block_val, NULL, NULL, 0, d->bitset) == -1) {
    192      1.1   thorpej 		d->futex_error = errno;
    193      1.3   thorpej 		membar_sync();
    194      1.3   thorpej 		atomic_dec_uint(&nlwps_running);
    195      1.1   thorpej 		_lwp_exit();
    196      1.1   thorpej 	} else {
    197      1.1   thorpej 		d->futex_error = 0;
    198      1.1   thorpej 	}
    199      1.1   thorpej 
    200      1.1   thorpej 	membar_sync();
    201      1.1   thorpej 	atomic_dec_uint(&nlwps_running);
    202      1.1   thorpej 
    203      1.1   thorpej 	_lwp_exit();
    204      1.1   thorpej }
    205      1.1   thorpej 
    206  1.5.2.1   thorpej static void
    207  1.5.2.1   thorpej rt_simple_test_waiter_lwp(void *arg)
    208  1.5.2.1   thorpej {
    209  1.5.2.1   thorpej 	struct lwp_data *d = arg;
    210  1.5.2.1   thorpej 	struct sched_param sp;
    211  1.5.2.1   thorpej 	int policy;
    212  1.5.2.1   thorpej 
    213  1.5.2.1   thorpej 	d->threadid = _lwp_self();
    214  1.5.2.1   thorpej 
    215  1.5.2.1   thorpej 	ATF_REQUIRE(_sched_getparam(getpid(), d->threadid, &policy, &sp) == 0);
    216  1.5.2.1   thorpej 	policy = SCHED_RR;
    217  1.5.2.1   thorpej 	sp.sched_priority = d->rt_prio;
    218  1.5.2.1   thorpej 	ATF_REQUIRE(_sched_setparam(getpid(), d->threadid, policy, &sp) == 0);
    219  1.5.2.1   thorpej 
    220  1.5.2.1   thorpej 	simple_test_waiter_lwp(arg);
    221  1.5.2.1   thorpej }
    222  1.5.2.1   thorpej 
    223      1.1   thorpej static bool
    224      1.1   thorpej verify_zero_bs(void)
    225      1.1   thorpej {
    226      1.1   thorpej 
    227      1.1   thorpej 	if (bs_verify_buffer == NULL) {
    228      1.1   thorpej 		bs_verify_buffer = malloc(bs_pagesize);
    229      1.1   thorpej 		ATF_REQUIRE(bs_verify_buffer != NULL);
    230      1.1   thorpej 	}
    231      1.1   thorpej 
    232      1.1   thorpej 	ATF_REQUIRE(pread(bs_fd, bs_verify_buffer,
    233      1.1   thorpej 			  bs_pagesize, 0) == bs_pagesize);
    234      1.1   thorpej 
    235      1.1   thorpej 	return (memcmp(bs_verify_buffer, bs_source_buffer, bs_pagesize) == 0);
    236      1.1   thorpej }
    237      1.1   thorpej 
    238      1.1   thorpej static void
    239      1.1   thorpej create_bs(int map_flags)
    240      1.1   thorpej {
    241      1.1   thorpej 
    242      1.1   thorpej 	bs_pagesize = sysconf(_SC_PAGESIZE);
    243      1.1   thorpej 	ATF_REQUIRE(bs_pagesize > 0);
    244      1.1   thorpej 
    245      1.1   thorpej 	if ((map_flags & (MAP_FILE | MAP_ANON)) == MAP_FILE) {
    246      1.1   thorpej 		bs_source_buffer = calloc(1, bs_pagesize);
    247      1.1   thorpej 		ATF_REQUIRE(bs_source_buffer != NULL);
    248      1.1   thorpej 
    249      1.1   thorpej 		bs_fd = open(bs_path, O_RDWR | O_CREAT | O_EXCL, 0644);
    250      1.1   thorpej 		ATF_REQUIRE(bs_fd != -1);
    251      1.1   thorpej 
    252      1.1   thorpej 		ATF_REQUIRE(pwrite(bs_fd, bs_source_buffer,
    253      1.1   thorpej 				   bs_pagesize, 0) == bs_pagesize);
    254      1.1   thorpej 		ATF_REQUIRE(verify_zero_bs());
    255      1.1   thorpej 	}
    256      1.1   thorpej 
    257      1.1   thorpej 	bs_addr = mmap(NULL, bs_pagesize, PROT_READ | PROT_WRITE,
    258      1.1   thorpej 		       map_flags | MAP_HASSEMAPHORE, bs_fd, 0);
    259      1.1   thorpej 	ATF_REQUIRE(bs_addr != MAP_FAILED);
    260      1.1   thorpej }
    261      1.1   thorpej 
    262      1.1   thorpej static void
    263      1.1   thorpej cleanup_bs(void)
    264      1.1   thorpej {
    265      1.1   thorpej 
    266      1.1   thorpej 	if (bs_fd != -1) {
    267      1.1   thorpej 		(void) close(bs_fd);
    268      1.1   thorpej 		bs_fd = -1;
    269      1.1   thorpej 		(void) unlink(bs_path);
    270      1.1   thorpej 	}
    271      1.1   thorpej 	if (bs_source_buffer != NULL) {
    272      1.1   thorpej 		free(bs_source_buffer);
    273      1.1   thorpej 		bs_source_buffer = NULL;
    274      1.1   thorpej 	}
    275      1.1   thorpej 	if (bs_verify_buffer != NULL) {
    276      1.1   thorpej 		free(bs_verify_buffer);
    277      1.1   thorpej 		bs_verify_buffer = NULL;
    278      1.1   thorpej 	}
    279      1.1   thorpej 	if (bs_addr != MAP_FAILED) {
    280      1.1   thorpej 		munmap(bs_addr, bs_pagesize);
    281      1.1   thorpej 		bs_addr = MAP_FAILED;
    282      1.1   thorpej 	}
    283      1.1   thorpej }
    284      1.1   thorpej 
    285      1.1   thorpej static void
    286      1.1   thorpej do_cleanup(void)
    287      1.1   thorpej {
    288      1.1   thorpej 	int i;
    289      1.1   thorpej 
    290      1.1   thorpej 	for (i = 0; i < NLWPS; i++) {
    291      1.1   thorpej 		struct lwp_data *d = &lwp_data[i];
    292      1.1   thorpej 		if (d->stack_base != NULL && d->stack_base != MAP_FAILED) {
    293      1.1   thorpej 			(void) munmap(d->stack_base, STACK_SIZE);
    294      1.1   thorpej 		}
    295      1.1   thorpej 	}
    296      1.1   thorpej 	memset(lwp_data, 0, sizeof(lwp_data));
    297      1.1   thorpej 	STORE(&futex_word, 0);
    298      1.1   thorpej 	STORE(&futex_word1, 0);
    299      1.1   thorpej 	nlwps_running = 0;
    300      1.1   thorpej 
    301      1.1   thorpej 	cleanup_bs();
    302      1.1   thorpej }
    303      1.1   thorpej 
    304      1.1   thorpej /*****************************************************************************/
    305      1.1   thorpej 
    306      1.1   thorpej static void
    307      1.1   thorpej wait_wake_test_waiter_lwp(void *arg)
    308      1.1   thorpej {
    309      1.1   thorpej 	struct lwp_data *d = arg;
    310      1.1   thorpej 
    311      1.1   thorpej 	d->threadid = _lwp_self();
    312      1.1   thorpej 
    313      1.1   thorpej 	STORE(d->futex_ptr, 1);
    314      1.1   thorpej 	membar_sync();
    315      1.1   thorpej 
    316      1.1   thorpej 	/* This will block because *futex_ptr == 1. */
    317      1.1   thorpej 	if (__futex(d->futex_ptr, FUTEX_WAIT | d->op_flags,
    318      1.1   thorpej 		    1, NULL, NULL, 0, 0) == -1) {
    319      1.1   thorpej 		STORE(d->error_ptr, errno);
    320      1.1   thorpej 		(*d->exit_func)();
    321      1.1   thorpej 	} else {
    322      1.1   thorpej 		STORE(d->error_ptr, 0);
    323      1.1   thorpej 	}
    324      1.1   thorpej 
    325      1.1   thorpej 	do {
    326      1.1   thorpej 		membar_sync();
    327      1.1   thorpej 		sleep(1);
    328      1.1   thorpej 	} while (LOAD(d->futex_ptr) != 0);
    329      1.1   thorpej 
    330      1.1   thorpej 	STORE(d->futex_ptr, 2);
    331      1.1   thorpej 	membar_sync();
    332      1.1   thorpej 
    333      1.1   thorpej 	do {
    334      1.1   thorpej 		membar_sync();
    335      1.1   thorpej 		sleep(1);
    336      1.1   thorpej 	} while (LOAD(d->futex_ptr) != 3);
    337      1.1   thorpej 
    338      1.1   thorpej 	/* This will not block because futex_word != 666. */
    339      1.1   thorpej 	if (__futex(d->futex_ptr, FUTEX_WAIT | d->op_flags,
    340      1.1   thorpej 		    666, NULL, NULL, 0, 0) == -1) {
    341      1.1   thorpej 		/* This SHOULD be EAGAIN. */
    342      1.1   thorpej 		STORE(d->error_ptr, errno);
    343      1.1   thorpej 	}
    344      1.1   thorpej 
    345      1.1   thorpej 	STORE(d->futex_ptr, 4);
    346      1.1   thorpej 	membar_sync();
    347      1.1   thorpej 
    348      1.1   thorpej 	(*d->exit_func)();
    349      1.1   thorpej }
    350      1.1   thorpej 
    351      1.1   thorpej static void
    352      1.1   thorpej do_futex_wait_wake_test(volatile int *futex_ptr, volatile int *error_ptr,
    353      1.1   thorpej 			void (*create_func)(struct lwp_data *),
    354      1.1   thorpej 			void (*exit_func)(void),
    355      1.1   thorpej 			void (*reap_func)(struct lwp_data *),
    356      1.1   thorpej 			int flags)
    357      1.1   thorpej {
    358      1.1   thorpej 	struct lwp_data *wlwp = &lwp_data[WAITER_LWP0];
    359      1.1   thorpej 	int tries;
    360      1.1   thorpej 
    361      1.1   thorpej 	if (error_ptr == NULL)
    362      1.1   thorpej 		error_ptr = &wlwp->futex_error;
    363      1.1   thorpej 
    364      1.1   thorpej 	if (create_func == NULL)
    365      1.1   thorpej 		create_func = create_lwp_waiter;
    366      1.1   thorpej 	if (exit_func == NULL)
    367      1.1   thorpej 		exit_func = exit_lwp_waiter;
    368      1.1   thorpej 	if (reap_func == NULL)
    369      1.1   thorpej 		reap_func = reap_lwp_waiter;
    370      1.1   thorpej 
    371      1.1   thorpej 	setup_lwp_context(wlwp, wait_wake_test_waiter_lwp);
    372      1.1   thorpej 
    373      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: testing with flags 0x%x\n", flags));
    374      1.1   thorpej 	wlwp->op_flags = flags;
    375      1.1   thorpej 	wlwp->error_ptr = error_ptr;
    376      1.1   thorpej 	STORE(error_ptr, -1);
    377      1.1   thorpej 	wlwp->futex_ptr = futex_ptr;
    378      1.1   thorpej 	STORE(futex_ptr, 0);
    379      1.1   thorpej 	wlwp->exit_func = exit_func;
    380      1.1   thorpej 	membar_sync();
    381      1.1   thorpej 
    382      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: creating watier LWP\n"));
    383      1.1   thorpej 	(*create_func)(wlwp);
    384      1.1   thorpej 
    385      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: waiting for LWP %d to enter futex\n",
    386      1.1   thorpej 	    wlwp->lwpid));
    387      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    388      1.1   thorpej 		membar_sync();
    389      1.1   thorpej 		if (LOAD(futex_ptr) == 1)
    390      1.1   thorpej 			break;
    391      1.1   thorpej 		sleep(1);
    392      1.1   thorpej 	}
    393      1.1   thorpej 	membar_sync();
    394      1.1   thorpej 	ATF_REQUIRE(LOAD(futex_ptr) == 1);
    395      1.1   thorpej 
    396      1.1   thorpej 	/*
    397      1.1   thorpej 	 * If the LWP is blocked in the futex, it will not have yet
    398      1.1   thorpej 	 * modified *error_ptr.
    399      1.1   thorpej 	 */
    400      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: checking for successful wait (%d)\n",
    401      1.1   thorpej 	    LOAD(error_ptr)));
    402      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    403      1.1   thorpej 		membar_sync();
    404      1.1   thorpej 		if (LOAD(error_ptr) == -1)
    405      1.1   thorpej 			break;
    406      1.1   thorpej 		sleep(1);
    407      1.1   thorpej 	}
    408      1.1   thorpej 	membar_sync();
    409      1.1   thorpej 	ATF_REQUIRE(LOAD(error_ptr) == -1);
    410      1.1   thorpej 
    411      1.1   thorpej 	/* Make sure invalid #wakes in rejected. */
    412      1.1   thorpej 	ATF_REQUIRE_ERRNO(EINVAL,
    413      1.1   thorpej 	    __futex(futex_ptr, FUTEX_WAKE | flags,
    414      1.1   thorpej 		    -1, NULL, NULL, 0, 0) == -1);
    415      1.1   thorpej 
    416      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: waking 1 waiter\n"));
    417      1.1   thorpej 	ATF_REQUIRE(__futex(futex_ptr, FUTEX_WAKE | flags,
    418      1.1   thorpej 			    1, NULL, NULL, 0, 0) == 1);
    419      1.1   thorpej 
    420      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: checking for successful wake (%d)\n",
    421      1.1   thorpej 	    LOAD(error_ptr)));
    422      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    423      1.1   thorpej 		membar_sync();
    424      1.1   thorpej 		if (LOAD(error_ptr) == 0)
    425      1.1   thorpej 			break;
    426      1.1   thorpej 		sleep(1);
    427      1.1   thorpej 	}
    428      1.1   thorpej 	membar_sync();
    429      1.1   thorpej 	ATF_REQUIRE(LOAD(error_ptr) == 0);
    430      1.1   thorpej 
    431      1.1   thorpej 	STORE(futex_ptr, 0);
    432      1.1   thorpej 	membar_sync();
    433      1.1   thorpej 
    434      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: waiting for LWP to advance (2)\n"));
    435      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    436      1.1   thorpej 		membar_sync();
    437      1.1   thorpej 		if (LOAD(futex_ptr) == 2)
    438      1.1   thorpej 			break;
    439      1.1   thorpej 		sleep(1);
    440      1.1   thorpej 	}
    441      1.1   thorpej 	membar_sync();
    442      1.1   thorpej 	ATF_REQUIRE(LOAD(futex_ptr) == 2);
    443      1.1   thorpej 
    444      1.1   thorpej 	STORE(futex_ptr, 3);
    445      1.1   thorpej 	membar_sync();
    446      1.1   thorpej 
    447      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: waiting for LWP to advance (4)\n"));
    448      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    449      1.1   thorpej 		membar_sync();
    450      1.1   thorpej 		if (LOAD(futex_ptr) == 4)
    451      1.1   thorpej 			break;
    452      1.1   thorpej 		sleep(1);
    453      1.1   thorpej 	}
    454      1.1   thorpej 	membar_sync();
    455      1.1   thorpej 	ATF_REQUIRE(LOAD(futex_ptr) == 4);
    456      1.1   thorpej 
    457      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: checking for expected EGAIN\n"));
    458      1.1   thorpej 	ATF_REQUIRE(LOAD(error_ptr) == EAGAIN);
    459      1.1   thorpej 
    460      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: reaping LWP %d\n", wlwp->lwpid));
    461      1.1   thorpej 	(*reap_func)(wlwp);
    462      1.1   thorpej }
    463      1.1   thorpej 
    464      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_basic_wait_wake_private);
    465      1.1   thorpej ATF_TC_HEAD(futex_basic_wait_wake_private, tc)
    466      1.1   thorpej {
    467      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    468      1.1   thorpej 	    "tests basic futex WAIT + WAKE operations (PRIVATE)");
    469      1.1   thorpej }
    470      1.1   thorpej ATF_TC_BODY(futex_basic_wait_wake_private, tc)
    471      1.1   thorpej {
    472      1.1   thorpej 	do_futex_wait_wake_test(&futex_word, NULL,
    473      1.1   thorpej 				NULL, NULL, NULL,
    474      1.1   thorpej 				FUTEX_PRIVATE_FLAG);
    475      1.1   thorpej }
    476      1.1   thorpej ATF_TC_CLEANUP(futex_basic_wait_wake_private, tc)
    477      1.1   thorpej {
    478      1.1   thorpej 	do_cleanup();
    479      1.1   thorpej }
    480      1.1   thorpej 
    481      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_basic_wait_wake_shared);
    482      1.1   thorpej ATF_TC_HEAD(futex_basic_wait_wake_shared, tc)
    483      1.1   thorpej {
    484      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    485      1.1   thorpej 	    "tests basic futex WAIT + WAKE operations (SHARED)");
    486      1.1   thorpej }
    487      1.1   thorpej ATF_TC_BODY(futex_basic_wait_wake_shared, tc)
    488      1.1   thorpej {
    489      1.1   thorpej 	do_futex_wait_wake_test(&futex_word, NULL,
    490      1.1   thorpej 				NULL, NULL, NULL,
    491      1.1   thorpej 				0);
    492      1.1   thorpej }
    493      1.1   thorpej ATF_TC_CLEANUP(futex_basic_wait_wake_shared, tc)
    494      1.1   thorpej {
    495      1.1   thorpej 	do_cleanup();
    496      1.1   thorpej }
    497      1.1   thorpej 
    498      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_anon_bs_private);
    499      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_anon_bs_private, tc)
    500      1.1   thorpej {
    501      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    502      1.1   thorpej 	    "tests futex WAIT + WAKE operations (MAP_ANON + PRIVATE)");
    503      1.1   thorpej }
    504      1.1   thorpej ATF_TC_BODY(futex_wait_wake_anon_bs_private, tc)
    505      1.1   thorpej {
    506      1.1   thorpej 	create_bs(MAP_ANON | MAP_PRIVATE);
    507      1.1   thorpej 	do_futex_wait_wake_test(&bs_addr[0], NULL,
    508      1.1   thorpej 				NULL, NULL, NULL,
    509      1.1   thorpej 				FUTEX_PRIVATE_FLAG);
    510      1.1   thorpej }
    511      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_anon_bs_private, tc)
    512      1.1   thorpej {
    513      1.1   thorpej 	do_cleanup();
    514      1.1   thorpej }
    515      1.1   thorpej 
    516      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_anon_bs_shared);
    517      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_anon_bs_shared, tc)
    518      1.1   thorpej {
    519      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    520      1.1   thorpej 	    "tests futex WAIT + WAKE operations (MAP_ANON + SHARED)");
    521      1.1   thorpej }
    522      1.1   thorpej ATF_TC_BODY(futex_wait_wake_anon_bs_shared, tc)
    523      1.1   thorpej {
    524      1.1   thorpej 	create_bs(MAP_ANON | MAP_PRIVATE);
    525      1.1   thorpej 	do_futex_wait_wake_test(&bs_addr[0], NULL,
    526      1.1   thorpej 				NULL, NULL, NULL,
    527      1.1   thorpej 				0);
    528      1.1   thorpej }
    529      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_anon_bs_shared, tc)
    530      1.1   thorpej {
    531      1.1   thorpej 	do_cleanup();
    532      1.1   thorpej }
    533      1.1   thorpej 
    534      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_file_bs_private);
    535      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_file_bs_private, tc)
    536      1.1   thorpej {
    537      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    538      1.1   thorpej 	    "tests futex WAIT + WAKE operations (MAP_FILE + PRIVATE)");
    539      1.1   thorpej }
    540      1.1   thorpej ATF_TC_BODY(futex_wait_wake_file_bs_private, tc)
    541      1.1   thorpej {
    542      1.1   thorpej 	/*
    543      1.1   thorpej 	 * This combination (non-COW mapped file + PRIVATE futex)
    544      1.1   thorpej 	 * doesn't really make sense, but we should make sure it
    545      1.1   thorpej 	 * works as expected.
    546      1.1   thorpej 	 */
    547      1.1   thorpej 	create_bs(MAP_FILE | MAP_SHARED);
    548      1.1   thorpej 	do_futex_wait_wake_test(&bs_addr[0], NULL,
    549      1.1   thorpej 				NULL, NULL, NULL,
    550      1.1   thorpej 				FUTEX_PRIVATE_FLAG);
    551      1.1   thorpej 	ATF_REQUIRE(! verify_zero_bs());
    552      1.1   thorpej }
    553      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_file_bs_private, tc)
    554      1.1   thorpej {
    555      1.1   thorpej 	do_cleanup();
    556      1.1   thorpej }
    557      1.1   thorpej 
    558      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_file_bs_cow_private);
    559      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_file_bs_cow_private, tc)
    560      1.1   thorpej {
    561      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    562      1.1   thorpej 	    "tests futex WAIT + WAKE operations (MAP_FILE COW + PRIVATE)");
    563      1.1   thorpej }
    564      1.1   thorpej ATF_TC_BODY(futex_wait_wake_file_bs_cow_private, tc)
    565      1.1   thorpej {
    566      1.1   thorpej 	create_bs(MAP_FILE | MAP_PRIVATE);
    567      1.1   thorpej 	do_futex_wait_wake_test(&bs_addr[0], NULL,
    568      1.1   thorpej 				NULL, NULL, NULL,
    569      1.1   thorpej 				FUTEX_PRIVATE_FLAG);
    570      1.1   thorpej 	ATF_REQUIRE(verify_zero_bs());
    571      1.1   thorpej }
    572      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_file_bs_cow_private, tc)
    573      1.1   thorpej {
    574      1.1   thorpej 	do_cleanup();
    575      1.1   thorpej }
    576      1.1   thorpej 
    577      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_file_bs_shared);
    578      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_file_bs_shared, tc)
    579      1.1   thorpej {
    580      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    581      1.1   thorpej 	    "tests futex WAIT + WAKE operations (MAP_FILE + SHARED)");
    582      1.1   thorpej }
    583      1.1   thorpej ATF_TC_BODY(futex_wait_wake_file_bs_shared, tc)
    584      1.1   thorpej {
    585      1.1   thorpej 	create_bs(MAP_FILE | MAP_SHARED);
    586      1.1   thorpej 	do_futex_wait_wake_test(&bs_addr[0], NULL,
    587      1.1   thorpej 				NULL, NULL, NULL,
    588      1.1   thorpej 				0);
    589      1.1   thorpej 	ATF_REQUIRE(! verify_zero_bs());
    590      1.1   thorpej }
    591      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_file_bs_shared, tc)
    592      1.1   thorpej {
    593      1.1   thorpej 	do_cleanup();
    594      1.1   thorpej }
    595      1.1   thorpej 
    596      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_file_bs_cow_shared);
    597      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_file_bs_cow_shared, tc)
    598      1.1   thorpej {
    599      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    600      1.1   thorpej 	    "tests futex WAIT + WAKE operations (MAP_FILE COW + SHARED)");
    601      1.1   thorpej }
    602      1.1   thorpej ATF_TC_BODY(futex_wait_wake_file_bs_cow_shared, tc)
    603      1.1   thorpej {
    604      1.1   thorpej 	/*
    605      1.1   thorpej 	 * This combination (COW mapped file + SHARED futex)
    606      1.1   thorpej 	 * doesn't really make sense, but we should make sure it
    607      1.1   thorpej 	 * works as expected.
    608      1.1   thorpej 	 */
    609      1.1   thorpej 	create_bs(MAP_FILE | MAP_PRIVATE);
    610      1.1   thorpej 	do_futex_wait_wake_test(&bs_addr[0], NULL,
    611      1.1   thorpej 				NULL, NULL, NULL,
    612      1.1   thorpej 				0);
    613      1.1   thorpej 	ATF_REQUIRE(verify_zero_bs());
    614      1.1   thorpej }
    615      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_file_bs_cow_shared, tc)
    616      1.1   thorpej {
    617      1.1   thorpej 	do_cleanup();
    618      1.1   thorpej }
    619      1.1   thorpej 
    620      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_anon_bs_shared_proc);
    621      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_anon_bs_shared_proc, tc)
    622      1.1   thorpej {
    623      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    624      1.1   thorpej 	    "tests multiproc futex WAIT + WAKE operations (MAP_ANON + SHARED)");
    625      1.1   thorpej }
    626      1.1   thorpej ATF_TC_BODY(futex_wait_wake_anon_bs_shared_proc, tc)
    627      1.1   thorpej {
    628      1.1   thorpej 	create_bs(MAP_ANON | MAP_SHARED);
    629      1.1   thorpej 	do_futex_wait_wake_test(&bs_addr[0], &bs_addr[1],
    630      1.1   thorpej 				create_proc_waiter,
    631      1.1   thorpej 				exit_proc_waiter,
    632      1.1   thorpej 				reap_proc_waiter,
    633      1.1   thorpej 				0);
    634      1.1   thorpej }
    635      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_anon_bs_shared_proc, tc)
    636      1.1   thorpej {
    637      1.1   thorpej 	do_cleanup();
    638      1.1   thorpej }
    639      1.1   thorpej 
    640      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_file_bs_shared_proc);
    641      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_file_bs_shared_proc, tc)
    642      1.1   thorpej {
    643      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    644      1.1   thorpej 	    "tests multiproc futex WAIT + WAKE operations (MAP_ANON + SHARED)");
    645      1.1   thorpej }
    646      1.1   thorpej ATF_TC_BODY(futex_wait_wake_file_bs_shared_proc, tc)
    647      1.1   thorpej {
    648      1.1   thorpej 	create_bs(MAP_FILE | MAP_SHARED);
    649      1.1   thorpej 	do_futex_wait_wake_test(&bs_addr[0], &bs_addr[1],
    650      1.1   thorpej 				create_proc_waiter,
    651      1.1   thorpej 				exit_proc_waiter,
    652      1.1   thorpej 				reap_proc_waiter,
    653      1.1   thorpej 				0);
    654      1.1   thorpej }
    655      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_file_bs_shared_proc, tc)
    656      1.1   thorpej {
    657      1.1   thorpej 	do_cleanup();
    658      1.1   thorpej }
    659      1.1   thorpej 
    660      1.1   thorpej /*****************************************************************************/
    661      1.1   thorpej 
    662      1.1   thorpej ATF_TC(futex_wait_pointless_bitset);
    663      1.1   thorpej ATF_TC_HEAD(futex_wait_pointless_bitset, tc)
    664      1.1   thorpej {
    665      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    666      1.1   thorpej 	    "tests basic futex WAIT + WAKE operations (SHARED)");
    667      1.1   thorpej }
    668      1.1   thorpej ATF_TC_BODY(futex_wait_pointless_bitset, tc)
    669      1.1   thorpej {
    670      1.1   thorpej 
    671      1.1   thorpej 	futex_word = 1;
    672      1.2  riastrad 	ATF_REQUIRE_ERRNO(EINVAL,
    673      1.2  riastrad 	    __futex(&futex_word, FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG,
    674      1.2  riastrad 		1, NULL, NULL, 0, 0) == -1);
    675      1.1   thorpej }
    676      1.1   thorpej 
    677      1.1   thorpej static void
    678      1.1   thorpej do_futex_wait_wake_bitset_test(int flags)
    679      1.1   thorpej {
    680      1.1   thorpej 	struct lwp_data *wlwp0 = &lwp_data[WAITER_LWP0];
    681      1.1   thorpej 	struct lwp_data *wlwp1 = &lwp_data[WAITER_LWP1];
    682      1.1   thorpej 	int i, tries;
    683      1.1   thorpej 
    684      1.1   thorpej 	for (i = WAITER_LWP0; i <= WAITER_LWP1; i++) {
    685      1.1   thorpej 		setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
    686      1.1   thorpej 		lwp_data[i].op_flags = flags;
    687      1.1   thorpej 		lwp_data[i].futex_error = -1;
    688      1.1   thorpej 		lwp_data[i].bitset = __BIT(i);
    689      1.1   thorpej 		lwp_data[i].wait_op = FUTEX_WAIT_BITSET;
    690      1.1   thorpej 		lwp_data[i].futex_ptr = &futex_word;
    691      1.1   thorpej 		lwp_data[i].block_val = 1;
    692      1.1   thorpej 	}
    693      1.1   thorpej 
    694      1.1   thorpej 	STORE(&futex_word, 1);
    695      1.1   thorpej 	membar_sync();
    696      1.1   thorpej 
    697      1.1   thorpej 	ATF_REQUIRE(_lwp_create(&wlwp0->context, 0, &wlwp0->lwpid) == 0);
    698      1.1   thorpej 	ATF_REQUIRE(_lwp_create(&wlwp1->context, 0, &wlwp1->lwpid) == 0);
    699      1.1   thorpej 
    700      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    701      1.1   thorpej 		membar_sync();
    702      1.1   thorpej 		if (nlwps_running == 2)
    703      1.1   thorpej 			break;
    704      1.1   thorpej 		sleep(1);
    705      1.1   thorpej 	}
    706      1.1   thorpej 	membar_sync();
    707      1.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 2, "waiters failed to start");
    708      1.1   thorpej 
    709      1.1   thorpej 	/* Ensure they're blocked. */
    710      1.1   thorpej 	ATF_REQUIRE(wlwp0->futex_error == -1);
    711      1.1   thorpej 	ATF_REQUIRE(wlwp1->futex_error == -1);
    712      1.1   thorpej 
    713      1.1   thorpej 	/* Make sure invalid #wakes in rejected. */
    714      1.1   thorpej 	ATF_REQUIRE_ERRNO(EINVAL,
    715      1.1   thorpej 	    __futex(&futex_word, FUTEX_WAKE_BITSET | flags,
    716      1.1   thorpej 		    -1, NULL, NULL, 0, 0) == -1);
    717      1.1   thorpej 
    718      1.1   thorpej 	/* This should result in no wakeups because no bits are set. */
    719      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_BITSET | flags,
    720      1.1   thorpej 			    INT_MAX, NULL, NULL, 0, 0) == 0);
    721      1.1   thorpej 
    722      1.1   thorpej 	/* This should result in no wakeups because the wrongs bits are set. */
    723      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_BITSET | flags,
    724      1.1   thorpej 			    INT_MAX, NULL, NULL, 0,
    725      1.1   thorpej 			    ~(wlwp0->bitset | wlwp1->bitset)) == 0);
    726      1.1   thorpej 
    727      1.1   thorpej 	/* Trust, but verify. */
    728      1.1   thorpej 	sleep(1);
    729      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    730      1.1   thorpej 		membar_sync();
    731      1.1   thorpej 		if (nlwps_running == 2)
    732      1.1   thorpej 			break;
    733      1.1   thorpej 		sleep(1);
    734      1.1   thorpej 	}
    735      1.1   thorpej 	membar_sync();
    736      1.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 2, "waiters exited unexpectedly");
    737      1.1   thorpej 
    738      1.1   thorpej 	/* Wake up the first LWP. */
    739      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_BITSET | flags,
    740      1.1   thorpej 			    INT_MAX, NULL, NULL, 0,
    741      1.1   thorpej 			    wlwp0->bitset) == 1);
    742      1.1   thorpej 	sleep(1);
    743      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    744      1.1   thorpej 		membar_sync();
    745      1.1   thorpej 		if (nlwps_running == 1)
    746      1.1   thorpej 			break;
    747      1.1   thorpej 		sleep(1);
    748      1.1   thorpej 	}
    749      1.1   thorpej 	membar_sync();
    750      1.1   thorpej 	ATF_REQUIRE(nlwps_running == 1);
    751      1.1   thorpej 	ATF_REQUIRE(wlwp0->futex_error == 0);
    752      1.1   thorpej 	ATF_REQUIRE(_lwp_wait(wlwp0->lwpid, NULL) == 0);
    753      1.1   thorpej 
    754      1.1   thorpej 	/* Wake up the second LWP. */
    755      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_BITSET | flags,
    756      1.1   thorpej 			    INT_MAX, NULL, NULL, 0,
    757      1.1   thorpej 			    wlwp1->bitset) == 1);
    758      1.1   thorpej 	sleep(1);
    759      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    760      1.1   thorpej 		membar_sync();
    761      1.1   thorpej 		if (nlwps_running == 0)
    762      1.1   thorpej 			break;
    763      1.1   thorpej 		sleep(1);
    764      1.1   thorpej 	}
    765      1.1   thorpej 	membar_sync();
    766      1.1   thorpej 	ATF_REQUIRE(nlwps_running == 0);
    767      1.1   thorpej 	ATF_REQUIRE(wlwp1->futex_error == 0);
    768      1.1   thorpej 	ATF_REQUIRE(_lwp_wait(wlwp1->lwpid, NULL) == 0);
    769      1.1   thorpej }
    770      1.1   thorpej 
    771      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_bitset);
    772      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_bitset, tc)
    773      1.1   thorpej {
    774      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    775      1.1   thorpej 	    "tests futex WAIT_BITSET + WAKE_BITSET operations");
    776      1.1   thorpej }
    777      1.1   thorpej ATF_TC_BODY(futex_wait_wake_bitset, tc)
    778      1.1   thorpej {
    779      1.1   thorpej 	do_futex_wait_wake_bitset_test(FUTEX_PRIVATE_FLAG);
    780      1.1   thorpej }
    781      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_bitset, tc)
    782      1.1   thorpej {
    783      1.1   thorpej 	do_cleanup();
    784      1.1   thorpej }
    785      1.1   thorpej 
    786      1.1   thorpej /*****************************************************************************/
    787      1.1   thorpej 
    788      1.1   thorpej static void
    789      1.1   thorpej do_futex_requeue_test(int flags, int op)
    790      1.1   thorpej {
    791      1.1   thorpej 	struct lwp_data *wlwp0 = &lwp_data[WAITER_LWP0];
    792      1.1   thorpej 	struct lwp_data *wlwp1 = &lwp_data[WAITER_LWP1];
    793      1.1   thorpej 	struct lwp_data *wlwp2 = &lwp_data[WAITER_LWP2];
    794      1.1   thorpej 	struct lwp_data *wlwp3 = &lwp_data[WAITER_LWP3];
    795      1.1   thorpej 	const int good_val3 = (op == FUTEX_CMP_REQUEUE) ?   1 : 0;
    796      1.1   thorpej 	const int bad_val3  = (op == FUTEX_CMP_REQUEUE) ? 666 : 0;
    797      1.1   thorpej 	int i, tries;
    798      1.1   thorpej 
    799      1.1   thorpej 	for (i = WAITER_LWP0; i <= WAITER_LWP3; i++) {
    800      1.1   thorpej 		setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
    801      1.1   thorpej 		lwp_data[i].op_flags = flags;
    802      1.1   thorpej 		lwp_data[i].futex_error = -1;
    803      1.1   thorpej 		lwp_data[i].futex_ptr = &futex_word;
    804      1.1   thorpej 		lwp_data[i].block_val = 1;
    805      1.1   thorpej 		lwp_data[i].bitset = 0;
    806      1.1   thorpej 		lwp_data[i].wait_op = FUTEX_WAIT;
    807      1.1   thorpej 	}
    808      1.1   thorpej 
    809      1.1   thorpej 	STORE(&futex_word, 1);
    810      1.1   thorpej 	STORE(&futex_word1, 1);
    811      1.1   thorpej 	membar_sync();
    812      1.1   thorpej 
    813      1.1   thorpej 	ATF_REQUIRE(_lwp_create(&wlwp0->context, 0, &wlwp0->lwpid) == 0);
    814      1.1   thorpej 	ATF_REQUIRE(_lwp_create(&wlwp1->context, 0, &wlwp1->lwpid) == 0);
    815      1.1   thorpej 	ATF_REQUIRE(_lwp_create(&wlwp2->context, 0, &wlwp2->lwpid) == 0);
    816      1.1   thorpej 	ATF_REQUIRE(_lwp_create(&wlwp3->context, 0, &wlwp3->lwpid) == 0);
    817      1.1   thorpej 
    818      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    819      1.1   thorpej 		membar_sync();
    820      1.1   thorpej 		if (nlwps_running == 4)
    821      1.1   thorpej 			break;
    822      1.1   thorpej 		sleep(1);
    823      1.1   thorpej 	}
    824      1.1   thorpej 	membar_sync();
    825      1.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 4, "waiters failed to start");
    826      1.1   thorpej 
    827      1.1   thorpej 	/* Ensure they're blocked. */
    828      1.1   thorpej 	ATF_REQUIRE(wlwp0->futex_error == -1);
    829      1.1   thorpej 	ATF_REQUIRE(wlwp1->futex_error == -1);
    830      1.1   thorpej 	ATF_REQUIRE(wlwp2->futex_error == -1);
    831      1.1   thorpej 	ATF_REQUIRE(wlwp3->futex_error == -1);
    832      1.1   thorpej 
    833      1.1   thorpej 	/* Make sure invalid #wakes and #requeues are rejected. */
    834      1.1   thorpej 	ATF_REQUIRE_ERRNO(EINVAL,
    835      1.1   thorpej 	    __futex(&futex_word, op | flags,
    836      1.1   thorpej 		    -1, NULL, &futex_word1, INT_MAX, bad_val3) == -1);
    837      1.1   thorpej 
    838      1.1   thorpej 	ATF_REQUIRE_ERRNO(EINVAL,
    839      1.1   thorpej 	    __futex(&futex_word, op | flags,
    840      1.1   thorpej 		    0, NULL, &futex_word1, -1, bad_val3) == -1);
    841      1.1   thorpej 
    842      1.1   thorpej 	/*
    843      1.1   thorpej 	 * FUTEX 0: 4 LWPs
    844      1.1   thorpej 	 * FUTEX 1: 0 LWPs
    845      1.1   thorpej 	 */
    846      1.1   thorpej 
    847      1.1   thorpej 	if (op == FUTEX_CMP_REQUEUE) {
    848      1.1   thorpej 		/* This should fail because the futex_word value is 1. */
    849      1.1   thorpej 		ATF_REQUIRE_ERRNO(EAGAIN,
    850      1.1   thorpej 		    __futex(&futex_word, op | flags,
    851      1.1   thorpej 			    0, NULL, &futex_word1, INT_MAX, bad_val3) == -1);
    852      1.1   thorpej 	}
    853      1.1   thorpej 
    854      1.1   thorpej 	/*
    855      1.1   thorpej 	 * FUTEX 0: 4 LWPs
    856      1.1   thorpej 	 * FUTEX 1: 0 LWPs
    857      1.1   thorpej 	 */
    858      1.1   thorpej 
    859      1.1   thorpej 	/* Move all waiters from 0 to 1. */
    860      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, op | flags,
    861  1.5.2.1   thorpej 			    0, NULL, &futex_word1, INT_MAX, good_val3) == 4);
    862      1.1   thorpej 
    863      1.1   thorpej 	/*
    864      1.1   thorpej 	 * FUTEX 0: 0 LWPs
    865      1.1   thorpej 	 * FUTEX 1: 4 LWPs
    866      1.1   thorpej 	 */
    867      1.1   thorpej 
    868      1.1   thorpej 	if (op == FUTEX_CMP_REQUEUE) {
    869      1.1   thorpej 		/* This should fail because the futex_word1 value is 1. */
    870      1.1   thorpej 		ATF_REQUIRE_ERRNO(EAGAIN,
    871      1.1   thorpej 		    __futex(&futex_word1, op | flags,
    872      1.1   thorpej 			    1, NULL, &futex_word, 1, bad_val3) == -1);
    873      1.1   thorpej 	}
    874      1.1   thorpej 
    875      1.1   thorpej 	/*
    876      1.1   thorpej 	 * FUTEX 0: 0 LWPs
    877      1.1   thorpej 	 * FUTEX 1: 4 LWPs
    878      1.1   thorpej 	 */
    879      1.1   thorpej 
    880      1.1   thorpej 	/* Wake one waiter on 1, move one waiter to 0. */
    881      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word1, op | flags,
    882  1.5.2.1   thorpej 			    1, NULL, &futex_word, 1, good_val3) == 2);
    883      1.1   thorpej 
    884      1.1   thorpej 	/*
    885      1.1   thorpej 	 * FUTEX 0: 1 LWP
    886      1.1   thorpej 	 * FUTEX 1: 2 LWPs
    887      1.1   thorpej 	 */
    888      1.1   thorpej 
    889      1.1   thorpej 	/* Wake all waiters on 0 (should be 1). */
    890      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE | flags,
    891      1.1   thorpej 			    INT_MAX, NULL, NULL, 0, 0) == 1);
    892      1.1   thorpej 
    893      1.1   thorpej 	/* Wake all waiters on 1 (should be 2). */
    894      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word1, FUTEX_WAKE | flags,
    895      1.1   thorpej 			    INT_MAX, NULL, NULL, 0, 0) == 2);
    896      1.1   thorpej 
    897      1.1   thorpej 	/* Trust, but verify. */
    898      1.1   thorpej 	sleep(1);
    899      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    900      1.1   thorpej 		membar_sync();
    901      1.1   thorpej 		if (nlwps_running == 0)
    902      1.1   thorpej 			break;
    903      1.1   thorpej 		sleep(1);
    904      1.1   thorpej 	}
    905      1.1   thorpej 	membar_sync();
    906      1.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "waiters failed to exit");
    907      1.1   thorpej 
    908      1.1   thorpej 	ATF_REQUIRE(_lwp_wait(wlwp0->lwpid, NULL) == 0);
    909      1.1   thorpej 	ATF_REQUIRE(_lwp_wait(wlwp1->lwpid, NULL) == 0);
    910      1.1   thorpej 	ATF_REQUIRE(_lwp_wait(wlwp2->lwpid, NULL) == 0);
    911      1.1   thorpej 	ATF_REQUIRE(_lwp_wait(wlwp3->lwpid, NULL) == 0);
    912      1.1   thorpej }
    913      1.1   thorpej 
    914      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_requeue);
    915      1.1   thorpej ATF_TC_HEAD(futex_requeue, tc)
    916      1.1   thorpej {
    917      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    918      1.1   thorpej 	    "tests futex REQUEUE operations");
    919      1.1   thorpej }
    920      1.1   thorpej ATF_TC_BODY(futex_requeue, tc)
    921      1.1   thorpej {
    922      1.1   thorpej 	do_futex_requeue_test(FUTEX_PRIVATE_FLAG, FUTEX_REQUEUE);
    923      1.1   thorpej }
    924      1.1   thorpej ATF_TC_CLEANUP(futex_requeue, tc)
    925      1.1   thorpej {
    926      1.1   thorpej 	do_cleanup();
    927      1.1   thorpej }
    928      1.1   thorpej 
    929      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_cmp_requeue);
    930      1.1   thorpej ATF_TC_HEAD(futex_cmp_requeue, tc)
    931      1.1   thorpej {
    932      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    933      1.1   thorpej 	    "tests futex CMP_REQUEUE operations");
    934      1.1   thorpej }
    935      1.1   thorpej ATF_TC_BODY(futex_cmp_requeue, tc)
    936      1.1   thorpej {
    937      1.1   thorpej 	do_futex_requeue_test(FUTEX_PRIVATE_FLAG, FUTEX_CMP_REQUEUE);
    938      1.1   thorpej }
    939      1.1   thorpej ATF_TC_CLEANUP(futex_cmp_requeue, tc)
    940      1.1   thorpej {
    941      1.1   thorpej 	do_cleanup();
    942      1.1   thorpej }
    943      1.1   thorpej 
    944      1.1   thorpej /*****************************************************************************/
    945      1.1   thorpej 
    946      1.1   thorpej static void
    947      1.1   thorpej do_futex_wake_op_op_test(int flags)
    948      1.1   thorpej {
    949      1.1   thorpej 	int op;
    950      1.1   thorpej 
    951      1.1   thorpej 	futex_word = 0;
    952      1.1   thorpej 	futex_word1 = 0;
    953      1.1   thorpej 
    954      1.1   thorpej 	/*
    955      1.1   thorpej 	 * The op= operations should work even if there are no waiters.
    956      1.1   thorpej 	 */
    957      1.1   thorpej 
    958      1.1   thorpej 	/*
    959      1.1   thorpej 	 * Because these operations use both futex addresses, exercise
    960      1.1   thorpej 	 * rejecting unaligned futex addresses here.
    961      1.1   thorpej 	 */
    962      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_EQ, 0);
    963      1.1   thorpej 	ATF_REQUIRE_ERRNO(EINVAL,
    964      1.1   thorpej 	    __futex((int *)1, FUTEX_WAKE_OP | flags,
    965      1.1   thorpej 		    0, NULL, &futex_word1, 0, op) == -1);
    966      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 0);
    967      1.1   thorpej 
    968      1.1   thorpej 	ATF_REQUIRE_ERRNO(EINVAL,
    969      1.1   thorpej 	    __futex(&futex_word, FUTEX_WAKE_OP | flags,
    970      1.1   thorpej 		    0, NULL, (int *)1, 0, op) == -1);
    971      1.1   thorpej 	ATF_REQUIRE(futex_word == 0);
    972      1.1   thorpej 
    973      1.1   thorpej 	/* Check unmapped uaddr2 handling, too. */
    974      1.1   thorpej 	ATF_REQUIRE_ERRNO(EFAULT,
    975      1.1   thorpej 	    __futex(&futex_word, FUTEX_WAKE_OP | flags,
    976      1.1   thorpej 		    0, NULL, NULL, 0, op) == -1);
    977      1.1   thorpej 	ATF_REQUIRE(futex_word == 0);
    978      1.1   thorpej 
    979      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_EQ, 0);
    980      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
    981      1.1   thorpej 			    0, NULL, &futex_word1, 0, op) == 0);
    982      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 1);
    983      1.1   thorpej 
    984      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_ADD, 1, FUTEX_OP_CMP_EQ, 0);
    985      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
    986      1.1   thorpej 			    0, NULL, &futex_word1, 0, op) == 0);
    987      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
    988      1.1   thorpej 
    989      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_OR, 2, FUTEX_OP_CMP_EQ, 0);
    990      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
    991      1.1   thorpej 			    0, NULL, &futex_word1, 0, op) == 0);
    992      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
    993      1.1   thorpej 
    994      1.1   thorpej 	/* This should fail because of invalid shift value 32. */
    995      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_OR | FUTEX_OP_OPARG_SHIFT, 32,
    996      1.1   thorpej 		      FUTEX_OP_CMP_EQ, 0);
    997      1.1   thorpej 	ATF_REQUIRE_ERRNO(EINVAL,
    998      1.1   thorpej 	    __futex(&futex_word, FUTEX_WAKE_OP | flags,
    999      1.1   thorpej 		    0, NULL, &futex_word1, 0, op) == -1);
   1000      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
   1001      1.1   thorpej 
   1002      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_OR | FUTEX_OP_OPARG_SHIFT, 31,
   1003      1.1   thorpej 		      FUTEX_OP_CMP_EQ, 0);
   1004      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1005      1.1   thorpej 			    0, NULL, &futex_word1, 0, op) == 0);
   1006      1.1   thorpej 	ATF_REQUIRE(futex_word1 == (int)0x80000002);
   1007      1.1   thorpej 
   1008      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_ANDN | FUTEX_OP_OPARG_SHIFT, 31,
   1009      1.1   thorpej 		      FUTEX_OP_CMP_EQ, 0);
   1010      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1011      1.1   thorpej 			    0, NULL, &futex_word1, 0, op) == 0);
   1012      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
   1013      1.1   thorpej 
   1014      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_XOR, 2, FUTEX_OP_CMP_EQ, 0);
   1015      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1016      1.1   thorpej 			    0, NULL, &futex_word1, 0, op) == 0);
   1017      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 0);
   1018      1.1   thorpej }
   1019      1.1   thorpej 
   1020      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wake_op_op);
   1021      1.1   thorpej ATF_TC_HEAD(futex_wake_op_op, tc)
   1022      1.1   thorpej {
   1023      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   1024      1.1   thorpej 	    "tests futex WAKE_OP OP operations");
   1025      1.1   thorpej }
   1026      1.1   thorpej ATF_TC_BODY(futex_wake_op_op, tc)
   1027      1.1   thorpej {
   1028      1.1   thorpej 	do_futex_wake_op_op_test(FUTEX_PRIVATE_FLAG);
   1029      1.1   thorpej }
   1030      1.1   thorpej ATF_TC_CLEANUP(futex_wake_op_op, tc)
   1031      1.1   thorpej {
   1032      1.1   thorpej 	do_cleanup();
   1033      1.1   thorpej }
   1034      1.1   thorpej 
   1035      1.1   thorpej static void
   1036      1.1   thorpej create_wake_op_test_lwps(int flags)
   1037      1.1   thorpej {
   1038      1.1   thorpej 	int i;
   1039      1.1   thorpej 
   1040      1.1   thorpej 	futex_word1 = 0;
   1041      1.1   thorpej 	membar_sync();
   1042      1.1   thorpej 
   1043      1.1   thorpej 	for (i = WAITER_LWP0; i <= WAITER_LWP5; i++) {
   1044      1.1   thorpej 		setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
   1045      1.1   thorpej 		lwp_data[i].op_flags = flags;
   1046      1.1   thorpej 		lwp_data[i].futex_error = -1;
   1047      1.1   thorpej 		lwp_data[i].futex_ptr = &futex_word1;
   1048      1.1   thorpej 		lwp_data[i].block_val = 0;
   1049      1.1   thorpej 		lwp_data[i].bitset = 0;
   1050      1.1   thorpej 		lwp_data[i].wait_op = FUTEX_WAIT;
   1051      1.1   thorpej 		ATF_REQUIRE(_lwp_create(&lwp_data[i].context, 0,
   1052      1.1   thorpej 					&lwp_data[i].lwpid) == 0);
   1053      1.1   thorpej 	}
   1054      1.1   thorpej 
   1055      1.1   thorpej 	for (i = 0; i < 5; i++) {
   1056      1.1   thorpej 		membar_sync();
   1057      1.1   thorpej 		if (nlwps_running == 6)
   1058      1.1   thorpej 			break;
   1059      1.1   thorpej 		sleep(1);
   1060      1.1   thorpej 	}
   1061      1.1   thorpej 	membar_sync();
   1062      1.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 6, "waiters failed to start");
   1063      1.1   thorpej 
   1064      1.1   thorpej 	/* Ensure they're blocked. */
   1065      1.1   thorpej 	for (i = WAITER_LWP0; i <= WAITER_LWP5; i++) {
   1066      1.1   thorpej 		ATF_REQUIRE(lwp_data[i].futex_error == -1);
   1067      1.1   thorpej 	}
   1068      1.1   thorpej }
   1069      1.1   thorpej 
   1070      1.1   thorpej static void
   1071      1.1   thorpej reap_wake_op_test_lwps(void)
   1072      1.1   thorpej {
   1073      1.1   thorpej 	int i;
   1074      1.1   thorpej 
   1075      1.1   thorpej 	for (i = WAITER_LWP0; i <= WAITER_LWP5; i++) {
   1076      1.1   thorpej 		ATF_REQUIRE(_lwp_wait(lwp_data[i].lwpid, NULL) == 0);
   1077      1.1   thorpej 	}
   1078      1.1   thorpej }
   1079      1.1   thorpej 
   1080      1.1   thorpej static void
   1081      1.1   thorpej do_futex_wake_op_cmp_test(int flags)
   1082      1.1   thorpej {
   1083      1.1   thorpej 	int tries, op;
   1084      1.1   thorpej 
   1085      1.1   thorpej 	futex_word = 0;
   1086      1.1   thorpej 	membar_sync();
   1087      1.1   thorpej 
   1088      1.1   thorpej 	/*
   1089      1.1   thorpej 	 * Verify and negative and positive for each individual
   1090      1.1   thorpej 	 * compare.
   1091      1.1   thorpej 	 */
   1092      1.1   thorpej 
   1093      1.1   thorpej 	create_wake_op_test_lwps(flags);
   1094      1.1   thorpej 
   1095      1.1   thorpej 	/* #LWPs = 6 */
   1096      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 1);
   1097      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1098      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 0);
   1099      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 0);
   1100      1.1   thorpej 
   1101      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_EQ, 0);
   1102      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1103      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 1);
   1104      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 1);
   1105      1.1   thorpej 
   1106      1.1   thorpej 	/* #LWPs = 5 */
   1107      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_NE, 1);
   1108      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1109      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 0);
   1110      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 1);
   1111      1.1   thorpej 
   1112      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_NE, 2);
   1113      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1114      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 1);
   1115      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
   1116      1.1   thorpej 
   1117      1.1   thorpej 	/* #LWPs = 4 */
   1118      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_LT, 2);
   1119      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1120      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 0);
   1121      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
   1122      1.1   thorpej 
   1123      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_LT, 3);
   1124      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1125      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 1);
   1126      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
   1127      1.1   thorpej 
   1128      1.1   thorpej 	/* #LWPs = 3 */
   1129      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_LE, 1);
   1130      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1131      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 0);
   1132      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 1);
   1133      1.1   thorpej 
   1134      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_LE, 1);
   1135      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1136      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 1);
   1137      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 1);
   1138      1.1   thorpej 
   1139      1.1   thorpej 	/* #LWPs = 2 */
   1140      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 3, FUTEX_OP_CMP_GT, 3);
   1141      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1142      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 0);
   1143      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 3);
   1144      1.1   thorpej 
   1145      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_GT, 2);
   1146      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1147      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 1);
   1148      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
   1149      1.1   thorpej 
   1150      1.1   thorpej 	/* #LWPs = 1 */
   1151      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 3, FUTEX_OP_CMP_GE, 4);
   1152      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1153      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 0);
   1154      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 3);
   1155      1.1   thorpej 
   1156      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_GE, 3);
   1157      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1158      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 1);
   1159      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
   1160      1.1   thorpej 
   1161      1.1   thorpej 	/* #LWPs = 0 */
   1162      1.1   thorpej 
   1163      1.1   thorpej 	/* Trust, but verify. */
   1164      1.1   thorpej 	sleep(1);
   1165      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
   1166      1.1   thorpej 		membar_sync();
   1167      1.1   thorpej 		if (nlwps_running == 0)
   1168      1.1   thorpej 			break;
   1169      1.1   thorpej 		sleep(1);
   1170      1.1   thorpej 	}
   1171      1.1   thorpej 	membar_sync();
   1172      1.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "waiters failed to exit");
   1173      1.1   thorpej 
   1174      1.1   thorpej 	reap_wake_op_test_lwps();
   1175      1.1   thorpej 
   1176      1.1   thorpej 	/*
   1177      1.1   thorpej 	 * Verify wakes on uaddr work even if the uaddr2 comparison
   1178      1.1   thorpej 	 * fails.
   1179      1.1   thorpej 	 */
   1180      1.1   thorpej 
   1181      1.1   thorpej 	create_wake_op_test_lwps(flags);
   1182      1.1   thorpej 
   1183      1.1   thorpej 	/* #LWPs = 6 */
   1184      1.1   thorpej 	ATF_REQUIRE(futex_word == 0);
   1185      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 666);
   1186      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word1, FUTEX_WAKE_OP | flags,
   1187      1.1   thorpej 			    INT_MAX, NULL, &futex_word, 0, op) == 6);
   1188      1.1   thorpej 	ATF_REQUIRE(futex_word == 0);
   1189      1.1   thorpej 
   1190      1.1   thorpej 	/* #LWPs = 0 */
   1191      1.1   thorpej 
   1192      1.1   thorpej 	/* Trust, but verify. */
   1193      1.1   thorpej 	sleep(1);
   1194      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
   1195      1.1   thorpej 		membar_sync();
   1196      1.1   thorpej 		if (nlwps_running == 0)
   1197      1.1   thorpej 			break;
   1198      1.1   thorpej 		sleep(1);
   1199      1.1   thorpej 	}
   1200      1.1   thorpej 	membar_sync();
   1201      1.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "waiters failed to exit");
   1202      1.1   thorpej 
   1203      1.1   thorpej 	reap_wake_op_test_lwps();
   1204      1.1   thorpej }
   1205      1.1   thorpej 
   1206      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wake_op_cmp);
   1207      1.1   thorpej ATF_TC_HEAD(futex_wake_op_cmp, tc)
   1208      1.1   thorpej {
   1209      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   1210      1.1   thorpej 	    "tests futex WAKE_OP CMP operations");
   1211      1.1   thorpej }
   1212      1.1   thorpej ATF_TC_BODY(futex_wake_op_cmp, tc)
   1213      1.1   thorpej {
   1214      1.1   thorpej 	do_futex_wake_op_cmp_test(FUTEX_PRIVATE_FLAG);
   1215      1.1   thorpej }
   1216      1.1   thorpej ATF_TC_CLEANUP(futex_wake_op_cmp, tc)
   1217      1.1   thorpej {
   1218      1.1   thorpej 	do_cleanup();
   1219      1.1   thorpej }
   1220      1.1   thorpej 
   1221      1.1   thorpej /*****************************************************************************/
   1222      1.1   thorpej 
   1223      1.1   thorpej static void
   1224      1.1   thorpej do_futex_wait_timeout(bool relative, clockid_t clock)
   1225      1.1   thorpej {
   1226      1.1   thorpej 	struct timespec ts;
   1227      1.1   thorpej 	struct timespec deadline;
   1228      1.1   thorpej 	int op = relative ? FUTEX_WAIT : FUTEX_WAIT_BITSET;
   1229      1.1   thorpej 
   1230      1.1   thorpej 	if (clock == CLOCK_REALTIME)
   1231      1.1   thorpej 		op |= FUTEX_CLOCK_REALTIME;
   1232      1.1   thorpej 
   1233      1.1   thorpej 	ATF_REQUIRE(clock_gettime(clock, &deadline) == 0);
   1234      1.1   thorpej 	deadline.tv_sec += 2;
   1235      1.1   thorpej 	if (relative) {
   1236      1.1   thorpej 		ts.tv_sec = 2;
   1237      1.1   thorpej 		ts.tv_nsec = 0;
   1238      1.1   thorpej 	} else {
   1239      1.1   thorpej 		ts = deadline;
   1240      1.1   thorpej 	}
   1241      1.1   thorpej 
   1242      1.1   thorpej 	futex_word = 1;
   1243      1.1   thorpej 	ATF_REQUIRE_ERRNO(ETIMEDOUT,
   1244      1.1   thorpej 	    __futex(&futex_word, op | FUTEX_PRIVATE_FLAG,
   1245      1.1   thorpej 		    1, &ts, NULL, 0, FUTEX_BITSET_MATCH_ANY) == -1);
   1246      1.1   thorpej 
   1247      1.1   thorpej 	/* Can't reliably check CLOCK_REALTIME in the presence of NTP. */
   1248      1.1   thorpej 	if (clock != CLOCK_REALTIME) {
   1249      1.1   thorpej 		ATF_REQUIRE(clock_gettime(clock, &ts) == 0);
   1250      1.1   thorpej 		ATF_REQUIRE(ts.tv_sec >= deadline.tv_sec);
   1251      1.1   thorpej 		ATF_REQUIRE(ts.tv_sec > deadline.tv_sec ||
   1252      1.1   thorpej 			    ts.tv_nsec >= deadline.tv_nsec);
   1253      1.1   thorpej 	}
   1254      1.1   thorpej }
   1255      1.1   thorpej 
   1256      1.1   thorpej ATF_TC(futex_wait_timeout_relative);
   1257      1.1   thorpej ATF_TC_HEAD(futex_wait_timeout_relative, tc)
   1258      1.1   thorpej {
   1259      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   1260      1.1   thorpej 	    "tests futex WAIT with relative timeout");
   1261      1.1   thorpej }
   1262      1.1   thorpej ATF_TC_BODY(futex_wait_timeout_relative, tc)
   1263      1.1   thorpej {
   1264      1.1   thorpej 	do_futex_wait_timeout(true, CLOCK_MONOTONIC);
   1265      1.1   thorpej }
   1266      1.1   thorpej 
   1267      1.1   thorpej ATF_TC(futex_wait_timeout_relative_rt);
   1268      1.1   thorpej ATF_TC_HEAD(futex_wait_timeout_relative_rt, tc)
   1269      1.1   thorpej {
   1270      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   1271      1.1   thorpej 	    "tests futex WAIT with relative timeout (REALTIME)");
   1272      1.1   thorpej }
   1273      1.1   thorpej ATF_TC_BODY(futex_wait_timeout_relative_rt, tc)
   1274      1.1   thorpej {
   1275      1.1   thorpej 	do_futex_wait_timeout(true, CLOCK_REALTIME);
   1276      1.1   thorpej }
   1277      1.1   thorpej 
   1278      1.1   thorpej ATF_TC(futex_wait_timeout_deadline);
   1279      1.1   thorpej ATF_TC_HEAD(futex_wait_timeout_deadline, tc)
   1280      1.1   thorpej {
   1281      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   1282      1.1   thorpej 	    "tests futex WAIT with absolute deadline");
   1283      1.1   thorpej }
   1284      1.1   thorpej ATF_TC_BODY(futex_wait_timeout_deadline, tc)
   1285      1.1   thorpej {
   1286      1.1   thorpej 	do_futex_wait_timeout(false, CLOCK_MONOTONIC);
   1287      1.1   thorpej }
   1288      1.1   thorpej 
   1289      1.1   thorpej ATF_TC(futex_wait_timeout_deadline_rt);
   1290      1.1   thorpej ATF_TC_HEAD(futex_wait_timeout_deadline_rt, tc)
   1291      1.1   thorpej {
   1292      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   1293      1.1   thorpej 	    "tests futex WAIT with absolute deadline (REALTIME)");
   1294      1.1   thorpej }
   1295      1.1   thorpej ATF_TC_BODY(futex_wait_timeout_deadline_rt, tc)
   1296      1.1   thorpej {
   1297      1.1   thorpej 	do_futex_wait_timeout(false, CLOCK_REALTIME);
   1298      1.1   thorpej }
   1299      1.1   thorpej 
   1300      1.1   thorpej /*****************************************************************************/
   1301      1.1   thorpej 
   1302      1.3   thorpej static void
   1303      1.3   thorpej sig_noop(int sig __unused)
   1304      1.3   thorpej {
   1305      1.3   thorpej }
   1306      1.3   thorpej 
   1307      1.3   thorpej static void (*old_act)(int) = SIG_DFL;
   1308      1.3   thorpej 
   1309      1.3   thorpej static void
   1310      1.3   thorpej do_futex_wait_evil_unmapped(int map_flags)
   1311      1.3   thorpej {
   1312      1.3   thorpej 	int i;
   1313      1.3   thorpej 
   1314      1.3   thorpej 	create_bs(map_flags);
   1315      1.3   thorpej 
   1316      1.3   thorpej 	old_act = signal(SIGUSR1, sig_noop);
   1317      1.3   thorpej 	ATF_REQUIRE(old_act != SIG_ERR);
   1318      1.3   thorpej 
   1319      1.3   thorpej 	setup_lwp_context(&lwp_data[0], simple_test_waiter_lwp);
   1320      1.3   thorpej 	lwp_data[0].op_flags = 0;
   1321      1.3   thorpej 	lwp_data[0].futex_error = -1;
   1322      1.3   thorpej 	lwp_data[0].futex_ptr = &bs_addr[0];
   1323      1.3   thorpej 	lwp_data[0].block_val = 0;
   1324      1.3   thorpej 	lwp_data[0].bitset = 0;
   1325      1.3   thorpej 	lwp_data[0].wait_op = FUTEX_WAIT;
   1326      1.3   thorpej 	ATF_REQUIRE(_lwp_create(&lwp_data[0].context, 0,
   1327      1.3   thorpej 				&lwp_data[0].lwpid) == 0);
   1328      1.3   thorpej 
   1329      1.3   thorpej 	for (i = 0; i < 5; i++) {
   1330      1.3   thorpej 		membar_sync();
   1331      1.3   thorpej 		if (nlwps_running == 1)
   1332      1.3   thorpej 			break;
   1333      1.3   thorpej 		sleep(1);
   1334      1.3   thorpej 	}
   1335      1.3   thorpej 	membar_sync();
   1336      1.3   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 1, "waiters failed to start");
   1337      1.3   thorpej 
   1338      1.3   thorpej 	/* Ensure it's blocked. */
   1339      1.3   thorpej 	ATF_REQUIRE(lwp_data[0].futex_error == -1);
   1340      1.3   thorpej 
   1341      1.3   thorpej 	/* Rudely unmap the backing store. */
   1342      1.3   thorpej 	cleanup_bs();
   1343      1.3   thorpej 
   1344      1.3   thorpej 	/* Signal the waiter so that it leaves the futex. */
   1345      1.3   thorpej 	ATF_REQUIRE(_lwp_kill(lwp_data[0].threadid, SIGUSR1) == 0);
   1346      1.3   thorpej 
   1347      1.3   thorpej 	/* Yay! No panic! */
   1348      1.3   thorpej 
   1349      1.3   thorpej 	reap_lwp_waiter(&lwp_data[0]);
   1350      1.3   thorpej }
   1351      1.3   thorpej 
   1352      1.3   thorpej ATF_TC_WITH_CLEANUP(futex_wait_evil_unmapped_anon);
   1353      1.3   thorpej ATF_TC_HEAD(futex_wait_evil_unmapped_anon, tc)
   1354      1.3   thorpej {
   1355      1.3   thorpej 	atf_tc_set_md_var(tc, "descr",
   1356      1.3   thorpej 	    "tests futex WAIT while futex is unmapped - anon memory");
   1357      1.3   thorpej }
   1358      1.3   thorpej ATF_TC_BODY(futex_wait_evil_unmapped_anon, tc)
   1359      1.3   thorpej {
   1360      1.3   thorpej 	do_futex_wait_evil_unmapped(MAP_ANON);
   1361      1.3   thorpej }
   1362      1.3   thorpej ATF_TC_CLEANUP(futex_wait_evil_unmapped_anon, tc)
   1363      1.3   thorpej {
   1364      1.3   thorpej 	signal(SIGUSR1, old_act);
   1365      1.3   thorpej 	do_cleanup();
   1366      1.3   thorpej }
   1367      1.3   thorpej 
   1368      1.3   thorpej /*****************************************************************************/
   1369      1.3   thorpej 
   1370      1.4   thorpej static void
   1371      1.4   thorpej do_test_wake_highest_pri(void)
   1372      1.4   thorpej {
   1373      1.4   thorpej 	lwpid_t waiter;
   1374      1.4   thorpej 	int tries;
   1375      1.4   thorpej 
   1376  1.5.2.1   thorpej 	setup_rt_params();
   1377      1.4   thorpej 
   1378      1.4   thorpej 	futex_word = 0;
   1379      1.4   thorpej 	membar_sync();
   1380      1.4   thorpej 
   1381  1.5.2.1   thorpej 	setup_lwp_context(&lwp_data[0], rt_simple_test_waiter_lwp);
   1382  1.5.2.1   thorpej 	lwp_data[0].rt_prio = pri_min;
   1383      1.4   thorpej 	lwp_data[0].op_flags = FUTEX_PRIVATE_FLAG;
   1384      1.4   thorpej 	lwp_data[0].futex_error = -1;
   1385      1.4   thorpej 	lwp_data[0].futex_ptr = &futex_word;
   1386      1.4   thorpej 	lwp_data[0].block_val = 0;
   1387      1.4   thorpej 	lwp_data[0].bitset = 0;
   1388      1.4   thorpej 	lwp_data[0].wait_op = FUTEX_WAIT;
   1389      1.4   thorpej 	ATF_REQUIRE(_lwp_create(&lwp_data[0].context, 0,
   1390      1.4   thorpej 				&lwp_data[0].lwpid) == 0);
   1391      1.4   thorpej 
   1392      1.4   thorpej 	for (tries = 0; tries < 5; tries++) {
   1393      1.4   thorpej 		membar_sync();
   1394      1.4   thorpej 		if (nlwps_running == 1)
   1395      1.4   thorpej 			break;
   1396      1.4   thorpej 		sleep(1);
   1397      1.4   thorpej 	}
   1398      1.4   thorpej 	membar_sync();
   1399      1.4   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 1, "lowpri waiter failed to start");
   1400      1.4   thorpej 
   1401      1.4   thorpej 	/* Ensure it's blocked. */
   1402      1.4   thorpej 	ATF_REQUIRE(lwp_data[0].futex_error == -1);
   1403      1.4   thorpej 
   1404  1.5.2.1   thorpej 	setup_lwp_context(&lwp_data[1], rt_simple_test_waiter_lwp);
   1405  1.5.2.1   thorpej 	lwp_data[1].rt_prio = pri_max;
   1406      1.4   thorpej 	lwp_data[1].op_flags = FUTEX_PRIVATE_FLAG;
   1407      1.4   thorpej 	lwp_data[1].futex_error = -1;
   1408      1.4   thorpej 	lwp_data[1].futex_ptr = &futex_word;
   1409      1.4   thorpej 	lwp_data[1].block_val = 0;
   1410      1.4   thorpej 	lwp_data[1].bitset = 0;
   1411      1.4   thorpej 	lwp_data[1].wait_op = FUTEX_WAIT;
   1412      1.5   thorpej 	ATF_REQUIRE(_lwp_create(&lwp_data[1].context, 0,
   1413      1.5   thorpej 				&lwp_data[1].lwpid) == 0);
   1414      1.4   thorpej 
   1415      1.4   thorpej 	for (tries = 0; tries < 5; tries++) {
   1416      1.4   thorpej 		membar_sync();
   1417      1.4   thorpej 		if (nlwps_running == 2)
   1418      1.4   thorpej 			break;
   1419      1.4   thorpej 		sleep(1);
   1420      1.4   thorpej 	}
   1421      1.4   thorpej 	membar_sync();
   1422      1.4   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 2, "highpri waiter failed to start");
   1423      1.4   thorpej 
   1424      1.4   thorpej 	/* Ensure it's blocked. */
   1425      1.4   thorpej 	ATF_REQUIRE(lwp_data[1].futex_error == -1);
   1426      1.4   thorpej 
   1427      1.4   thorpej 	/* Wake the first LWP.  We should get the highpri thread. */
   1428      1.4   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE | FUTEX_PRIVATE_FLAG,
   1429      1.4   thorpej 			    1, NULL, NULL, 0, 0) == 1);
   1430      1.4   thorpej 	sleep(1);
   1431      1.4   thorpej 	for (tries = 0; tries < 5; tries++) {
   1432      1.4   thorpej 		membar_sync();
   1433      1.4   thorpej 		if (nlwps_running == 1)
   1434      1.4   thorpej 			break;
   1435      1.4   thorpej 		sleep(1);
   1436      1.4   thorpej 	}
   1437      1.4   thorpej 	membar_sync();
   1438      1.4   thorpej 	ATF_REQUIRE(nlwps_running == 1);
   1439      1.4   thorpej 	ATF_REQUIRE(_lwp_wait(0, &waiter) == 0);
   1440      1.4   thorpej 	ATF_REQUIRE(waiter == lwp_data[1].threadid);
   1441      1.4   thorpej 
   1442      1.4   thorpej 	/* Wake the second LWP.  We should get the lowpri thread. */
   1443      1.4   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE | FUTEX_PRIVATE_FLAG,
   1444      1.4   thorpej 			    1, NULL, NULL, 0, 0) == 1);
   1445      1.4   thorpej 	sleep(1);
   1446      1.4   thorpej 	for (tries = 0; tries < 5; tries++) {
   1447      1.4   thorpej 		membar_sync();
   1448      1.4   thorpej 		if (nlwps_running == 0)
   1449      1.4   thorpej 			break;
   1450      1.4   thorpej 		sleep(1);
   1451      1.4   thorpej 	}
   1452      1.4   thorpej 	membar_sync();
   1453      1.4   thorpej 	ATF_REQUIRE(nlwps_running == 0);
   1454      1.4   thorpej 	ATF_REQUIRE(_lwp_wait(0, &waiter) == 0);
   1455      1.4   thorpej 	ATF_REQUIRE(waiter == lwp_data[0].threadid);
   1456      1.4   thorpej }
   1457      1.4   thorpej 
   1458      1.4   thorpej ATF_TC_WITH_CLEANUP(futex_wake_highest_pri);
   1459      1.4   thorpej ATF_TC_HEAD(futex_wake_highest_pri, tc)
   1460      1.4   thorpej {
   1461      1.4   thorpej 	atf_tc_set_md_var(tc, "descr",
   1462      1.4   thorpej 	    "tests that futex WAKE wakes the highest priority waiter");
   1463      1.4   thorpej 	atf_tc_set_md_var(tc, "require.user", "root");
   1464      1.4   thorpej }
   1465      1.4   thorpej ATF_TC_BODY(futex_wake_highest_pri, tc)
   1466      1.4   thorpej {
   1467      1.4   thorpej 	do_test_wake_highest_pri();
   1468      1.4   thorpej }
   1469      1.4   thorpej ATF_TC_CLEANUP(futex_wake_highest_pri, tc)
   1470      1.4   thorpej {
   1471      1.4   thorpej 	do_cleanup();
   1472      1.4   thorpej }
   1473      1.4   thorpej 
   1474      1.4   thorpej /*****************************************************************************/
   1475      1.4   thorpej 
   1476  1.5.2.1   thorpej static void
   1477  1.5.2.1   thorpej do_test_rw_handoff_read(void)
   1478  1.5.2.1   thorpej {
   1479  1.5.2.1   thorpej 	int i, tries;
   1480  1.5.2.1   thorpej 	int rv;
   1481  1.5.2.1   thorpej 
   1482  1.5.2.1   thorpej 	futex_word = FUTEX_WAITERS;
   1483  1.5.2.1   thorpej 	membar_sync();
   1484  1.5.2.1   thorpej 
   1485  1.5.2.1   thorpej 	for (i = 0; i < 3; i++) {
   1486  1.5.2.1   thorpej 		setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
   1487  1.5.2.1   thorpej 		lwp_data[i].op_flags = FUTEX_PRIVATE_FLAG;
   1488  1.5.2.1   thorpej 		lwp_data[i].futex_error = -1;
   1489  1.5.2.1   thorpej 		lwp_data[i].futex_ptr = &futex_word;
   1490  1.5.2.1   thorpej 		lwp_data[i].block_val = futex_word;
   1491  1.5.2.1   thorpej 		lwp_data[i].bitset = FUTEX_RW_READER;
   1492  1.5.2.1   thorpej 		lwp_data[i].wait_op = FUTEX_NETBSD_RW_WAIT;
   1493  1.5.2.1   thorpej 		ATF_REQUIRE(_lwp_create(&lwp_data[i].context, 0,
   1494  1.5.2.1   thorpej 					&lwp_data[i].lwpid) == 0);
   1495  1.5.2.1   thorpej 	}
   1496  1.5.2.1   thorpej 
   1497  1.5.2.1   thorpej 	for (tries = 0; tries < 5; tries++) {
   1498  1.5.2.1   thorpej 		membar_sync();
   1499  1.5.2.1   thorpej 		if (nlwps_running == 3)
   1500  1.5.2.1   thorpej 			break;
   1501  1.5.2.1   thorpej 		sleep(1);
   1502  1.5.2.1   thorpej 	}
   1503  1.5.2.1   thorpej 	membar_sync();
   1504  1.5.2.1   thorpej 
   1505  1.5.2.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 3, "read-waiters failed to start");
   1506  1.5.2.1   thorpej 
   1507  1.5.2.1   thorpej 	/* Ensure they're all blocked. */
   1508  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[0].futex_error == -1);
   1509  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[1].futex_error == -1);
   1510  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[2].futex_error == -1);
   1511  1.5.2.1   thorpej 
   1512  1.5.2.1   thorpej 	/* Ensure a regular wake errors out. */
   1513  1.5.2.1   thorpej 	rv = __futex(&futex_word,
   1514  1.5.2.1   thorpej 		     FUTEX_WAKE | FUTEX_PRIVATE_FLAG, INT_MAX, NULL,
   1515  1.5.2.1   thorpej 		     NULL, 0, 0);
   1516  1.5.2.1   thorpej 	ATF_REQUIRE(rv == -1 && errno == EINVAL);
   1517  1.5.2.1   thorpej 
   1518  1.5.2.1   thorpej 	/*
   1519  1.5.2.1   thorpej 	 * Issue a hand-off.  It should wake all 3 readers and update
   1520  1.5.2.1   thorpej 	 * the futex word.
   1521  1.5.2.1   thorpej 	 */
   1522  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   1523  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   1524  1.5.2.1   thorpej 			    FUTEX_WAITERS, NULL, NULL, 0, 0) == 3);
   1525  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word == 3);
   1526  1.5.2.1   thorpej 
   1527  1.5.2.1   thorpej 	for (tries = 0; tries < 5; tries++) {
   1528  1.5.2.1   thorpej 		membar_sync();
   1529  1.5.2.1   thorpej 		if (nlwps_running == 0)
   1530  1.5.2.1   thorpej 			break;
   1531  1.5.2.1   thorpej 		sleep(1);
   1532  1.5.2.1   thorpej 	}
   1533  1.5.2.1   thorpej 	membar_sync();
   1534  1.5.2.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "read-waiters failed to exit");
   1535  1.5.2.1   thorpej 
   1536  1.5.2.1   thorpej 	/* Ensure they all exited error-free. */
   1537  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[0].futex_error == 0);
   1538  1.5.2.1   thorpej 	reap_lwp_waiter(&lwp_data[0]);
   1539  1.5.2.1   thorpej 
   1540  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[1].futex_error == 0);
   1541  1.5.2.1   thorpej 	reap_lwp_waiter(&lwp_data[1]);
   1542  1.5.2.1   thorpej 
   1543  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[2].futex_error == 0);
   1544  1.5.2.1   thorpej 	reap_lwp_waiter(&lwp_data[2]);
   1545  1.5.2.1   thorpej }
   1546  1.5.2.1   thorpej 
   1547  1.5.2.1   thorpej ATF_TC_WITH_CLEANUP(futex_rw_handoff_read);
   1548  1.5.2.1   thorpej ATF_TC_HEAD(futex_rw_handoff_read, tc)
   1549  1.5.2.1   thorpej {
   1550  1.5.2.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   1551  1.5.2.1   thorpej 	    "tests rwlock direct hand-off to readers");
   1552  1.5.2.1   thorpej }
   1553  1.5.2.1   thorpej ATF_TC_BODY(futex_rw_handoff_read, tc)
   1554  1.5.2.1   thorpej {
   1555  1.5.2.1   thorpej 	atf_tc_skip("futex_rw_handoff is currently broken");
   1556  1.5.2.1   thorpej 	do_test_rw_handoff_read();
   1557  1.5.2.1   thorpej }
   1558  1.5.2.1   thorpej ATF_TC_CLEANUP(futex_rw_handoff_read, tc)
   1559  1.5.2.1   thorpej {
   1560  1.5.2.1   thorpej 	do_cleanup();
   1561  1.5.2.1   thorpej }
   1562  1.5.2.1   thorpej 
   1563  1.5.2.1   thorpej /*****************************************************************************/
   1564  1.5.2.1   thorpej 
   1565  1.5.2.1   thorpej static void
   1566  1.5.2.1   thorpej do_test_rw_handoff_write(void)
   1567  1.5.2.1   thorpej {
   1568  1.5.2.1   thorpej 	unsigned int i, tries;
   1569  1.5.2.1   thorpej 	lwpid_t lid;
   1570  1.5.2.1   thorpej 
   1571  1.5.2.1   thorpej 	/*
   1572  1.5.2.1   thorpej 	 * The kernel should not care about the WRITE_WANTED bit, and
   1573  1.5.2.1   thorpej 	 * should use the contents of the sleepqs as the truth.
   1574  1.5.2.1   thorpej 	 */
   1575  1.5.2.1   thorpej 	futex_word = FUTEX_WAITERS;
   1576  1.5.2.1   thorpej 	membar_sync();
   1577  1.5.2.1   thorpej 
   1578  1.5.2.1   thorpej 	for (i = 0; i < 3; i++) {
   1579  1.5.2.1   thorpej 		setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
   1580  1.5.2.1   thorpej 		lwp_data[i].op_flags = FUTEX_PRIVATE_FLAG;
   1581  1.5.2.1   thorpej 		lwp_data[i].futex_error = -1;
   1582  1.5.2.1   thorpej 		lwp_data[i].futex_ptr = &futex_word;
   1583  1.5.2.1   thorpej 		lwp_data[i].block_val = futex_word;
   1584  1.5.2.1   thorpej 		lwp_data[i].bitset = FUTEX_RW_WRITER;
   1585  1.5.2.1   thorpej 		lwp_data[i].wait_op = FUTEX_NETBSD_RW_WAIT;
   1586  1.5.2.1   thorpej 		ATF_REQUIRE(_lwp_create(&lwp_data[i].context, 0,
   1587  1.5.2.1   thorpej 					&lwp_data[i].lwpid) == 0);
   1588  1.5.2.1   thorpej 
   1589  1.5.2.1   thorpej 		/*
   1590  1.5.2.1   thorpej 		 * Wait for each one to start in-turn, because we want
   1591  1.5.2.1   thorpej 		 * to know the order in which the LWPs block on the futex.
   1592  1.5.2.1   thorpej 		 */
   1593  1.5.2.1   thorpej 		for (tries = 0; tries < 5; tries++) {
   1594  1.5.2.1   thorpej 			membar_sync();
   1595  1.5.2.1   thorpej 			if (nlwps_running == i + 1)
   1596  1.5.2.1   thorpej 				break;
   1597  1.5.2.1   thorpej 			sleep(1);
   1598  1.5.2.1   thorpej 		}
   1599  1.5.2.1   thorpej 		membar_sync();
   1600  1.5.2.1   thorpej 	}
   1601  1.5.2.1   thorpej 
   1602  1.5.2.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 3, "write-waiters failed to start");
   1603  1.5.2.1   thorpej 
   1604  1.5.2.1   thorpej 	/* Ensure they're all blocked. */
   1605  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[0].futex_error == -1);
   1606  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[1].futex_error == -1);
   1607  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[2].futex_error == -1);
   1608  1.5.2.1   thorpej 
   1609  1.5.2.1   thorpej 	/*
   1610  1.5.2.1   thorpej 	 * Issue a hand-off for each waiter.  This should awaken one
   1611  1.5.2.1   thorpej 	 * at a time and update the futex word.
   1612  1.5.2.1   thorpej 	 */
   1613  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   1614  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   1615  1.5.2.1   thorpej 			    FUTEX_WAITERS, NULL, NULL, 0, 0) == 1);
   1616  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_LOCKED);
   1617  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_WANTED);
   1618  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_WAITERS);
   1619  1.5.2.1   thorpej 	lid = futex_word & FUTEX_TID_MASK;
   1620  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[0].lwpid);
   1621  1.5.2.1   thorpej 
   1622  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   1623  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   1624  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 1);
   1625  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_LOCKED);
   1626  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_WANTED);
   1627  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_WAITERS);
   1628  1.5.2.1   thorpej 	lid = futex_word & FUTEX_TID_MASK;
   1629  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[1].lwpid);
   1630  1.5.2.1   thorpej 
   1631  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   1632  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   1633  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 1);
   1634  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_LOCKED);
   1635  1.5.2.1   thorpej 	ATF_REQUIRE((futex_word & FUTEX_RW_WRITE_WANTED) == 0);
   1636  1.5.2.1   thorpej 	ATF_REQUIRE((futex_word & FUTEX_WAITERS) == 0);
   1637  1.5.2.1   thorpej 	lid = futex_word & FUTEX_TID_MASK;
   1638  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[2].lwpid);
   1639  1.5.2.1   thorpej 
   1640  1.5.2.1   thorpej 	/*
   1641  1.5.2.1   thorpej 	 * Issue one final hand-off; it should result in a fully
   1642  1.5.2.1   thorpej 	 * released lock word.
   1643  1.5.2.1   thorpej 	 */
   1644  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   1645  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   1646  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 0);
   1647  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word == 0);
   1648  1.5.2.1   thorpej 
   1649  1.5.2.1   thorpej 	for (tries = 0; tries < 5; tries++) {
   1650  1.5.2.1   thorpej 		membar_sync();
   1651  1.5.2.1   thorpej 		if (nlwps_running == 0)
   1652  1.5.2.1   thorpej 			break;
   1653  1.5.2.1   thorpej 		sleep(1);
   1654  1.5.2.1   thorpej 	}
   1655  1.5.2.1   thorpej 	membar_sync();
   1656  1.5.2.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "read-waiters failed to exit");
   1657  1.5.2.1   thorpej 
   1658  1.5.2.1   thorpej 	/* Ensure they all exited error-free. */
   1659  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[0].futex_error == 0);
   1660  1.5.2.1   thorpej 	reap_lwp_waiter(&lwp_data[0]);
   1661  1.5.2.1   thorpej 
   1662  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[1].futex_error == 0);
   1663  1.5.2.1   thorpej 	reap_lwp_waiter(&lwp_data[1]);
   1664  1.5.2.1   thorpej 
   1665  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[2].futex_error == 0);
   1666  1.5.2.1   thorpej 	reap_lwp_waiter(&lwp_data[2]);
   1667  1.5.2.1   thorpej }
   1668  1.5.2.1   thorpej 
   1669  1.5.2.1   thorpej ATF_TC_WITH_CLEANUP(futex_rw_handoff_write);
   1670  1.5.2.1   thorpej ATF_TC_HEAD(futex_rw_handoff_write, tc)
   1671  1.5.2.1   thorpej {
   1672  1.5.2.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   1673  1.5.2.1   thorpej 	    "tests rwlock direct hand-off to writers");
   1674  1.5.2.1   thorpej }
   1675  1.5.2.1   thorpej ATF_TC_BODY(futex_rw_handoff_write, tc)
   1676  1.5.2.1   thorpej {
   1677  1.5.2.1   thorpej 	atf_tc_skip("futex_rw_handoff is currently broken");
   1678  1.5.2.1   thorpej 	do_test_rw_handoff_write();
   1679  1.5.2.1   thorpej }
   1680  1.5.2.1   thorpej ATF_TC_CLEANUP(futex_rw_handoff_write, tc)
   1681  1.5.2.1   thorpej {
   1682  1.5.2.1   thorpej 	do_cleanup();
   1683  1.5.2.1   thorpej }
   1684  1.5.2.1   thorpej 
   1685  1.5.2.1   thorpej /*****************************************************************************/
   1686  1.5.2.1   thorpej 
   1687  1.5.2.1   thorpej static void
   1688  1.5.2.1   thorpej do_test_rw_handoff_write_preferred(void)
   1689  1.5.2.1   thorpej {
   1690  1.5.2.1   thorpej 	unsigned int i, tries;
   1691  1.5.2.1   thorpej 	lwpid_t lid;
   1692  1.5.2.1   thorpej 
   1693  1.5.2.1   thorpej 	/*
   1694  1.5.2.1   thorpej 	 * The kernel should not care about the WRITE_WANTED bit, and
   1695  1.5.2.1   thorpej 	 * should use the contents of the sleepqs as the truth.
   1696  1.5.2.1   thorpej 	 */
   1697  1.5.2.1   thorpej 	futex_word = FUTEX_WAITERS;
   1698  1.5.2.1   thorpej 	membar_sync();
   1699  1.5.2.1   thorpej 
   1700  1.5.2.1   thorpej 	for (i = 0; i < 2; i++) {
   1701  1.5.2.1   thorpej 		setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
   1702  1.5.2.1   thorpej 		lwp_data[i].op_flags = FUTEX_PRIVATE_FLAG;
   1703  1.5.2.1   thorpej 		lwp_data[i].futex_error = -1;
   1704  1.5.2.1   thorpej 		lwp_data[i].futex_ptr = &futex_word;
   1705  1.5.2.1   thorpej 		lwp_data[i].block_val = futex_word;
   1706  1.5.2.1   thorpej 		lwp_data[i].bitset = FUTEX_RW_READER;
   1707  1.5.2.1   thorpej 		lwp_data[i].wait_op = FUTEX_NETBSD_RW_WAIT;
   1708  1.5.2.1   thorpej 		ATF_REQUIRE(_lwp_create(&lwp_data[i].context, 0,
   1709  1.5.2.1   thorpej 					&lwp_data[i].lwpid) == 0);
   1710  1.5.2.1   thorpej 
   1711  1.5.2.1   thorpej 		/*
   1712  1.5.2.1   thorpej 		 * Wait for each one to start in-turn, because we want
   1713  1.5.2.1   thorpej 		 * to know the order in which the LWPs block on the futex.
   1714  1.5.2.1   thorpej 		 */
   1715  1.5.2.1   thorpej 		for (tries = 0; tries < 5; tries++) {
   1716  1.5.2.1   thorpej 			membar_sync();
   1717  1.5.2.1   thorpej 			if (nlwps_running == i + 1)
   1718  1.5.2.1   thorpej 				break;
   1719  1.5.2.1   thorpej 			sleep(1);
   1720  1.5.2.1   thorpej 		}
   1721  1.5.2.1   thorpej 		membar_sync();
   1722  1.5.2.1   thorpej 	}
   1723  1.5.2.1   thorpej 
   1724  1.5.2.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 2, "read-waiters failed to start");
   1725  1.5.2.1   thorpej 
   1726  1.5.2.1   thorpej 	setup_lwp_context(&lwp_data[2], simple_test_waiter_lwp);
   1727  1.5.2.1   thorpej 	lwp_data[2].op_flags = FUTEX_PRIVATE_FLAG;
   1728  1.5.2.1   thorpej 	lwp_data[2].futex_error = -1;
   1729  1.5.2.1   thorpej 	lwp_data[2].futex_ptr = &futex_word;
   1730  1.5.2.1   thorpej 	lwp_data[2].block_val = futex_word;
   1731  1.5.2.1   thorpej 	lwp_data[2].bitset = FUTEX_RW_WRITER;
   1732  1.5.2.1   thorpej 	lwp_data[2].wait_op = FUTEX_NETBSD_RW_WAIT;
   1733  1.5.2.1   thorpej 	ATF_REQUIRE(_lwp_create(&lwp_data[2].context, 0,
   1734  1.5.2.1   thorpej 				&lwp_data[2].lwpid) == 0);
   1735  1.5.2.1   thorpej 
   1736  1.5.2.1   thorpej 	for (tries = 0; tries < 5; tries++) {
   1737  1.5.2.1   thorpej 		membar_sync();
   1738  1.5.2.1   thorpej 		if (nlwps_running == 3)
   1739  1.5.2.1   thorpej 			break;
   1740  1.5.2.1   thorpej 		sleep(1);
   1741  1.5.2.1   thorpej 	}
   1742  1.5.2.1   thorpej 	membar_sync();
   1743  1.5.2.1   thorpej 
   1744  1.5.2.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 3, "write-waiter failed to start");
   1745  1.5.2.1   thorpej 
   1746  1.5.2.1   thorpej 	/* Ensure they're all blocked. */
   1747  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[0].futex_error == -1);
   1748  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[1].futex_error == -1);
   1749  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[2].futex_error == -1);
   1750  1.5.2.1   thorpej 
   1751  1.5.2.1   thorpej 	/*
   1752  1.5.2.1   thorpej 	 * Issue a hand-off.  It should select the writer despite
   1753  1.5.2.1   thorpej 	 * the fact that it is the most recent waiter.
   1754  1.5.2.1   thorpej 	 */
   1755  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   1756  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   1757  1.5.2.1   thorpej 			    FUTEX_WAITERS, NULL, NULL, 0, 0) == 1);
   1758  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_LOCKED);
   1759  1.5.2.1   thorpej 	ATF_REQUIRE((futex_word & FUTEX_RW_WRITE_WANTED) == 0);
   1760  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_WAITERS);
   1761  1.5.2.1   thorpej 	lid = futex_word & FUTEX_TID_MASK;
   1762  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[2].lwpid);
   1763  1.5.2.1   thorpej 
   1764  1.5.2.1   thorpej 	/*
   1765  1.5.2.1   thorpej 	 * Issue another hand-off.  It should awaken both waiting
   1766  1.5.2.1   thorpej 	 * readers.
   1767  1.5.2.1   thorpej 	 */
   1768  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   1769  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   1770  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 2);
   1771  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word == 2);
   1772  1.5.2.1   thorpej 
   1773  1.5.2.1   thorpej 	/*
   1774  1.5.2.1   thorpej 	 * Issue one final hand-off; it should result in a fully
   1775  1.5.2.1   thorpej 	 * released lock word.  Note that we don't have any
   1776  1.5.2.1   thorpej 	 * outstaning waiters waiting, and therefore there will
   1777  1.5.2.1   thorpej 	 * not be a kernel futex; this exercises a specific code
   1778  1.5.2.1   thorpej 	 * path in the kernel designed to handle this.
   1779  1.5.2.1   thorpej 	 */
   1780  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   1781  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   1782  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 0);
   1783  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word == 0);
   1784  1.5.2.1   thorpej 
   1785  1.5.2.1   thorpej 	for (tries = 0; tries < 5; tries++) {
   1786  1.5.2.1   thorpej 		membar_sync();
   1787  1.5.2.1   thorpej 		if (nlwps_running == 0)
   1788  1.5.2.1   thorpej 			break;
   1789  1.5.2.1   thorpej 		sleep(1);
   1790  1.5.2.1   thorpej 	}
   1791  1.5.2.1   thorpej 	membar_sync();
   1792  1.5.2.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "read-waiters failed to exit");
   1793  1.5.2.1   thorpej 
   1794  1.5.2.1   thorpej 	/* Ensure they all exited error-free. */
   1795  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[0].futex_error == 0);
   1796  1.5.2.1   thorpej 	reap_lwp_waiter(&lwp_data[0]);
   1797  1.5.2.1   thorpej 
   1798  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[1].futex_error == 0);
   1799  1.5.2.1   thorpej 	reap_lwp_waiter(&lwp_data[1]);
   1800  1.5.2.1   thorpej 
   1801  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[2].futex_error == 0);
   1802  1.5.2.1   thorpej 	reap_lwp_waiter(&lwp_data[2]);
   1803  1.5.2.1   thorpej }
   1804  1.5.2.1   thorpej 
   1805  1.5.2.1   thorpej ATF_TC_WITH_CLEANUP(futex_rw_handoff_write_preferred);
   1806  1.5.2.1   thorpej ATF_TC_HEAD(futex_rw_handoff_write_preferred, tc)
   1807  1.5.2.1   thorpej {
   1808  1.5.2.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   1809  1.5.2.1   thorpej 	    "tests that rwlock direct hand-off prefers writers");
   1810  1.5.2.1   thorpej }
   1811  1.5.2.1   thorpej ATF_TC_BODY(futex_rw_handoff_write_preferred, tc)
   1812  1.5.2.1   thorpej {
   1813  1.5.2.1   thorpej 	atf_tc_skip("futex_rw_handoff is currently broken");
   1814  1.5.2.1   thorpej 	do_test_rw_handoff_write_preferred();
   1815  1.5.2.1   thorpej }
   1816  1.5.2.1   thorpej ATF_TC_CLEANUP(futex_rw_handoff_write_preferred, tc)
   1817  1.5.2.1   thorpej {
   1818  1.5.2.1   thorpej 	do_cleanup();
   1819  1.5.2.1   thorpej }
   1820  1.5.2.1   thorpej 
   1821  1.5.2.1   thorpej /*****************************************************************************/
   1822  1.5.2.1   thorpej 
   1823  1.5.2.1   thorpej static void
   1824  1.5.2.1   thorpej do_test_rw_handoff_write_locked_rt_reader_preferred(void)
   1825  1.5.2.1   thorpej {
   1826  1.5.2.1   thorpej 	unsigned int i, tries;
   1827  1.5.2.1   thorpej 	lwpid_t lid;
   1828  1.5.2.1   thorpej 
   1829  1.5.2.1   thorpej 	setup_rt_params();
   1830  1.5.2.1   thorpej 
   1831  1.5.2.1   thorpej 	/*
   1832  1.5.2.1   thorpej 	 * We need to show the rwlock as write-locked to ensure
   1833  1.5.2.1   thorpej 	 * the rt read-waiter blocks.
   1834  1.5.2.1   thorpej 	 */
   1835  1.5.2.1   thorpej 	futex_word =
   1836  1.5.2.1   thorpej 	    FUTEX_WAITERS | FUTEX_RW_WRITE_WANTED | FUTEX_RW_WRITE_LOCKED;
   1837  1.5.2.1   thorpej 	membar_sync();
   1838  1.5.2.1   thorpej 
   1839  1.5.2.1   thorpej 	/*
   1840  1.5.2.1   thorpej 	 * Create LWPs in the following order:
   1841  1.5.2.1   thorpej 	 *
   1842  1.5.2.1   thorpej 	 *	0 - non-RT reader
   1843  1.5.2.1   thorpej 	 *	1 - RT reader
   1844  1.5.2.1   thorpej 	 *	2 - non-RT writer
   1845  1.5.2.1   thorpej 	 *
   1846  1.5.2.1   thorpej 	 * We expect them to be awakened in this order:
   1847  1.5.2.1   thorpej 	 *
   1848  1.5.2.1   thorpej 	 *	1 -> 2 -> 0
   1849  1.5.2.1   thorpej 	 */
   1850  1.5.2.1   thorpej 	for (i = 0; i < 3; i++) {
   1851  1.5.2.1   thorpej 		if (i == 1) {
   1852  1.5.2.1   thorpej 			setup_lwp_context(&lwp_data[i],
   1853  1.5.2.1   thorpej 			    rt_simple_test_waiter_lwp);
   1854  1.5.2.1   thorpej 			lwp_data[i].rt_prio = pri_min;
   1855  1.5.2.1   thorpej 		} else {
   1856  1.5.2.1   thorpej 			setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
   1857  1.5.2.1   thorpej 		}
   1858  1.5.2.1   thorpej 		lwp_data[i].op_flags = FUTEX_PRIVATE_FLAG;
   1859  1.5.2.1   thorpej 		lwp_data[i].futex_error = -1;
   1860  1.5.2.1   thorpej 		lwp_data[i].futex_ptr = &futex_word;
   1861  1.5.2.1   thorpej 		lwp_data[i].block_val = futex_word;
   1862  1.5.2.1   thorpej 		lwp_data[i].bitset = i == 2 ? FUTEX_RW_WRITER : FUTEX_RW_READER;
   1863  1.5.2.1   thorpej 		lwp_data[i].wait_op = FUTEX_NETBSD_RW_WAIT;
   1864  1.5.2.1   thorpej 		ATF_REQUIRE(_lwp_create(&lwp_data[i].context, 0,
   1865  1.5.2.1   thorpej 					&lwp_data[i].lwpid) == 0);
   1866  1.5.2.1   thorpej 
   1867  1.5.2.1   thorpej 		/*
   1868  1.5.2.1   thorpej 		 * Wait for each one to start in-turn, because we want
   1869  1.5.2.1   thorpej 		 * to know the order in which the LWPs block on the futex.
   1870  1.5.2.1   thorpej 		 */
   1871  1.5.2.1   thorpej 		for (tries = 0; tries < 5; tries++) {
   1872  1.5.2.1   thorpej 			membar_sync();
   1873  1.5.2.1   thorpej 			if (nlwps_running == i + 1)
   1874  1.5.2.1   thorpej 				break;
   1875  1.5.2.1   thorpej 			sleep(1);
   1876  1.5.2.1   thorpej 		}
   1877  1.5.2.1   thorpej 		membar_sync();
   1878  1.5.2.1   thorpej 	}
   1879  1.5.2.1   thorpej 
   1880  1.5.2.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 3, "waiters failed to start");
   1881  1.5.2.1   thorpej 
   1882  1.5.2.1   thorpej 	/* Ensure they're all blocked. */
   1883  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[0].futex_error == -1);
   1884  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[1].futex_error == -1);
   1885  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[2].futex_error == -1);
   1886  1.5.2.1   thorpej 
   1887  1.5.2.1   thorpej 	/*
   1888  1.5.2.1   thorpej 	 * Issue a hand-off.  It should select the RT reader, and should
   1889  1.5.2.1   thorpej 	 * indicate that there are still waiters, including a write-waiter.
   1890  1.5.2.1   thorpej 	 */
   1891  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   1892  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   1893  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 1);
   1894  1.5.2.1   thorpej 	ATF_REQUIRE((futex_word & FUTEX_RW_WRITE_LOCKED) == 0);
   1895  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_WANTED);
   1896  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_WAITERS);
   1897  1.5.2.1   thorpej 	lid = futex_word & FUTEX_TID_MASK;
   1898  1.5.2.1   thorpej 	ATF_REQUIRE(lid == 1);
   1899  1.5.2.1   thorpej 	ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
   1900  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[1].lwpid);
   1901  1.5.2.1   thorpej 
   1902  1.5.2.1   thorpej 	/*
   1903  1.5.2.1   thorpej 	 * Issue another hand-off.  It should awaken the writer and
   1904  1.5.2.1   thorpej 	 * indicate only readers waiting.
   1905  1.5.2.1   thorpej 	 */
   1906  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   1907  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   1908  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 1);
   1909  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_LOCKED);
   1910  1.5.2.1   thorpej 	ATF_REQUIRE((futex_word & FUTEX_RW_WRITE_WANTED) == 0);
   1911  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_WAITERS);
   1912  1.5.2.1   thorpej 	lid = futex_word & FUTEX_TID_MASK;
   1913  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[2].lwpid);
   1914  1.5.2.1   thorpej 	ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
   1915  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[2].lwpid);
   1916  1.5.2.1   thorpej 
   1917  1.5.2.1   thorpej 	/*
   1918  1.5.2.1   thorpej 	 * Issue another hand-off.  It would awaken the non-rt
   1919  1.5.2.1   thorpej 	 * reader and indicate no waiters waiting.
   1920  1.5.2.1   thorpej 	 */
   1921  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   1922  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   1923  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 1);
   1924  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word == 1);
   1925  1.5.2.1   thorpej 	ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
   1926  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[0].lwpid);
   1927  1.5.2.1   thorpej 
   1928  1.5.2.1   thorpej 	/*
   1929  1.5.2.1   thorpej 	 * Issue one final hand-off; it should result in a fully
   1930  1.5.2.1   thorpej 	 * released lock word.  Note that we don't have any
   1931  1.5.2.1   thorpej 	 * outstaning waiters waiting, and therefore there will
   1932  1.5.2.1   thorpej 	 * not be a kernel futex; this exercises a specific code
   1933  1.5.2.1   thorpej 	 * path in the kernel designed to handle this.
   1934  1.5.2.1   thorpej 	 */
   1935  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   1936  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   1937  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 0);
   1938  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word == 0);
   1939  1.5.2.1   thorpej 
   1940  1.5.2.1   thorpej 	for (tries = 0; tries < 5; tries++) {
   1941  1.5.2.1   thorpej 		membar_sync();
   1942  1.5.2.1   thorpej 		if (nlwps_running == 0)
   1943  1.5.2.1   thorpej 			break;
   1944  1.5.2.1   thorpej 		sleep(1);
   1945  1.5.2.1   thorpej 	}
   1946  1.5.2.1   thorpej 	membar_sync();
   1947  1.5.2.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "threads failed to exit");
   1948  1.5.2.1   thorpej 
   1949  1.5.2.1   thorpej 	/* Ensure they all exited error-free. */
   1950  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[0].futex_error == 0);
   1951  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[1].futex_error == 0);
   1952  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[2].futex_error == 0);
   1953  1.5.2.1   thorpej }
   1954  1.5.2.1   thorpej 
   1955  1.5.2.1   thorpej ATF_TC_WITH_CLEANUP(futex_rw_handoff_write_locked_rt_reader_preferred);
   1956  1.5.2.1   thorpej ATF_TC_HEAD(futex_rw_handoff_write_locked_rt_reader_preferred, tc)
   1957  1.5.2.1   thorpej {
   1958  1.5.2.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   1959  1.5.2.1   thorpej 	    "tests that write-locked rwlock direct hand-off "
   1960  1.5.2.1   thorpej 	    "prefers rt readers over non-rt writers");
   1961  1.5.2.1   thorpej 	atf_tc_set_md_var(tc, "require.user", "root");
   1962  1.5.2.1   thorpej }
   1963  1.5.2.1   thorpej ATF_TC_BODY(futex_rw_handoff_write_locked_rt_reader_preferred, tc)
   1964  1.5.2.1   thorpej {
   1965  1.5.2.1   thorpej 	atf_tc_skip("futex_rw_handoff is currently broken");
   1966  1.5.2.1   thorpej 	do_test_rw_handoff_write_locked_rt_reader_preferred();
   1967  1.5.2.1   thorpej }
   1968  1.5.2.1   thorpej ATF_TC_CLEANUP(futex_rw_handoff_write_locked_rt_reader_preferred, tc)
   1969  1.5.2.1   thorpej {
   1970  1.5.2.1   thorpej 	do_cleanup();
   1971  1.5.2.1   thorpej }
   1972  1.5.2.1   thorpej 
   1973  1.5.2.1   thorpej /*****************************************************************************/
   1974  1.5.2.1   thorpej 
   1975  1.5.2.1   thorpej static void
   1976  1.5.2.1   thorpej do_test_rw_wait_write_wanted_rt_reader_preferred(void)
   1977  1.5.2.1   thorpej {
   1978  1.5.2.1   thorpej 	unsigned int i, tries;
   1979  1.5.2.1   thorpej 	lwpid_t lid;
   1980  1.5.2.1   thorpej 
   1981  1.5.2.1   thorpej 	setup_rt_params();
   1982  1.5.2.1   thorpej 
   1983  1.5.2.1   thorpej 	/*
   1984  1.5.2.1   thorpej 	 * The kernel should not care about the WRITE_WANTED bit, and
   1985  1.5.2.1   thorpej 	 * should use the contents of the sleepqs as the truth.
   1986  1.5.2.1   thorpej 	 */
   1987  1.5.2.1   thorpej 	futex_word = FUTEX_WAITERS;
   1988  1.5.2.1   thorpej 	membar_sync();
   1989  1.5.2.1   thorpej 
   1990  1.5.2.1   thorpej 	/*
   1991  1.5.2.1   thorpej 	 * Create LWPs in the following order:
   1992  1.5.2.1   thorpej 	 *
   1993  1.5.2.1   thorpej 	 *	0 - non-RT writer
   1994  1.5.2.1   thorpej 	 *	1 - non-RT reader
   1995  1.5.2.1   thorpej 	 *	2 - RT reader
   1996  1.5.2.1   thorpej 	 *
   1997  1.5.2.1   thorpej 	 * We expect:
   1998  1.5.2.1   thorpej 	 *
   1999  1.5.2.1   thorpej 	 * ==> non-RT reader blocks because WRITE_WANTED.
   2000  1.5.2.1   thorpej 	 * ==> RT reader does not block and acquires the read-lock.
   2001  1.5.2.1   thorpej 	 *
   2002  1.5.2.1   thorpej 	 * We then expect hand-offs to awaken the remaining waiters
   2003  1.5.2.1   thorpej 	 * in this order:
   2004  1.5.2.1   thorpej 	 *
   2005  1.5.2.1   thorpej 	 *	0 -> 1
   2006  1.5.2.1   thorpej 	 */
   2007  1.5.2.1   thorpej 	for (i = 0; i < 3; i++) {
   2008  1.5.2.1   thorpej 		if (i == 2) {
   2009  1.5.2.1   thorpej 			setup_lwp_context(&lwp_data[i],
   2010  1.5.2.1   thorpej 			    rt_simple_test_waiter_lwp);
   2011  1.5.2.1   thorpej 			lwp_data[i].rt_prio = pri_min;
   2012  1.5.2.1   thorpej 		} else {
   2013  1.5.2.1   thorpej 			setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
   2014  1.5.2.1   thorpej 		}
   2015  1.5.2.1   thorpej 		lwp_data[i].op_flags = FUTEX_PRIVATE_FLAG;
   2016  1.5.2.1   thorpej 		lwp_data[i].futex_error = -1;
   2017  1.5.2.1   thorpej 		lwp_data[i].futex_ptr = &futex_word;
   2018  1.5.2.1   thorpej 		lwp_data[i].block_val = futex_word;
   2019  1.5.2.1   thorpej 		lwp_data[i].bitset = i == 0 ? FUTEX_RW_WRITER : FUTEX_RW_READER;
   2020  1.5.2.1   thorpej 		lwp_data[i].wait_op = FUTEX_NETBSD_RW_WAIT;
   2021  1.5.2.1   thorpej 		ATF_REQUIRE(_lwp_create(&lwp_data[i].context, 0,
   2022  1.5.2.1   thorpej 					&lwp_data[i].lwpid) == 0);
   2023  1.5.2.1   thorpej 
   2024  1.5.2.1   thorpej 		/*
   2025  1.5.2.1   thorpej 		 * Wait for the first 2 to start in-turn, because we want
   2026  1.5.2.1   thorpej 		 * to know the order in which the LWPs block on the futex.
   2027  1.5.2.1   thorpej 		 */
   2028  1.5.2.1   thorpej 		for (tries = 0; i < 2 && tries < 5; tries++) {
   2029  1.5.2.1   thorpej 			membar_sync();
   2030  1.5.2.1   thorpej 			if (nlwps_running == i + 1)
   2031  1.5.2.1   thorpej 				break;
   2032  1.5.2.1   thorpej 			sleep(1);
   2033  1.5.2.1   thorpej 		}
   2034  1.5.2.1   thorpej 		membar_sync();
   2035  1.5.2.1   thorpej 	}
   2036  1.5.2.1   thorpej 
   2037  1.5.2.1   thorpej 	sleep(2);
   2038  1.5.2.1   thorpej 
   2039  1.5.2.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 2, "waiters failed to start");
   2040  1.5.2.1   thorpej 
   2041  1.5.2.1   thorpej 	/* Ensure the first two are blocked and the 3rd one succeeded. */
   2042  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[0].futex_error == -1);
   2043  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[1].futex_error == -1);
   2044  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[2].futex_error == 0);
   2045  1.5.2.1   thorpej 
   2046  1.5.2.1   thorpej 	/*
   2047  1.5.2.1   thorpej 	 * Verify the locked-ness and waiter-status of the rwlock.
   2048  1.5.2.1   thorpej 	 * Also verify it was the expected LWP that made it through
   2049  1.5.2.1   thorpej 	 * the gate.
   2050  1.5.2.1   thorpej 	 */
   2051  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word == (FUTEX_WAITERS | FUTEX_RW_WRITE_WANTED | 1));
   2052  1.5.2.1   thorpej 	ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
   2053  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[2].lwpid);
   2054  1.5.2.1   thorpej 
   2055  1.5.2.1   thorpej 	/*
   2056  1.5.2.1   thorpej 	 * Issue a hand-off.  It should awaken the writer and indicate only
   2057  1.5.2.1   thorpej 	 * readers waiting.
   2058  1.5.2.1   thorpej 	 */
   2059  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   2060  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   2061  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 1);
   2062  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_LOCKED);
   2063  1.5.2.1   thorpej 	ATF_REQUIRE((futex_word & FUTEX_RW_WRITE_WANTED) == 0);
   2064  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_WAITERS);
   2065  1.5.2.1   thorpej 	lid = futex_word & FUTEX_TID_MASK;
   2066  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[0].lwpid);
   2067  1.5.2.1   thorpej 	ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
   2068  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[0].lwpid);
   2069  1.5.2.1   thorpej 
   2070  1.5.2.1   thorpej 	/*
   2071  1.5.2.1   thorpej 	 * Issue another hand-off.  It would awaken the non-rt
   2072  1.5.2.1   thorpej 	 * reader and indicate no waiters waiting.
   2073  1.5.2.1   thorpej 	 */
   2074  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   2075  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   2076  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 1);
   2077  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word == 1);
   2078  1.5.2.1   thorpej 	ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
   2079  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[1].lwpid);
   2080  1.5.2.1   thorpej 
   2081  1.5.2.1   thorpej 	/*
   2082  1.5.2.1   thorpej 	 * Issue one final hand-off; it should result in a fully
   2083  1.5.2.1   thorpej 	 * released lock word.  Note that we don't have any
   2084  1.5.2.1   thorpej 	 * outstaning waiters waiting, and therefore there will
   2085  1.5.2.1   thorpej 	 * not be a kernel futex; this exercises a specific code
   2086  1.5.2.1   thorpej 	 * path in the kernel designed to handle this.
   2087  1.5.2.1   thorpej 	 */
   2088  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   2089  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   2090  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 0);
   2091  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word == 0);
   2092  1.5.2.1   thorpej 
   2093  1.5.2.1   thorpej 	for (tries = 0; tries < 5; tries++) {
   2094  1.5.2.1   thorpej 		membar_sync();
   2095  1.5.2.1   thorpej 		if (nlwps_running == 0)
   2096  1.5.2.1   thorpej 			break;
   2097  1.5.2.1   thorpej 		sleep(1);
   2098  1.5.2.1   thorpej 	}
   2099  1.5.2.1   thorpej 	membar_sync();
   2100  1.5.2.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "threads failed to exit");
   2101  1.5.2.1   thorpej 
   2102  1.5.2.1   thorpej 	/* Ensure they all exited error-free. */
   2103  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[0].futex_error == 0);
   2104  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[1].futex_error == 0);
   2105  1.5.2.1   thorpej }
   2106  1.5.2.1   thorpej 
   2107  1.5.2.1   thorpej ATF_TC_WITH_CLEANUP(futex_rw_wait_write_wanted_rt_reader_preferred);
   2108  1.5.2.1   thorpej ATF_TC_HEAD(futex_rw_wait_write_wanted_rt_reader_preferred, tc)
   2109  1.5.2.1   thorpej {
   2110  1.5.2.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   2111  1.5.2.1   thorpej 	    "tests that a wait by a rt-reader acquires "
   2112  1.5.2.1   thorpej 	    "even if the rwlock is wanted by a non-rt writer");
   2113  1.5.2.1   thorpej 	atf_tc_set_md_var(tc, "require.user", "root");
   2114  1.5.2.1   thorpej }
   2115  1.5.2.1   thorpej ATF_TC_BODY(futex_rw_wait_write_wanted_rt_reader_preferred, tc)
   2116  1.5.2.1   thorpej {
   2117  1.5.2.1   thorpej 	atf_tc_skip("futex_rw_handoff is currently broken");
   2118  1.5.2.1   thorpej 	do_test_rw_wait_write_wanted_rt_reader_preferred();
   2119  1.5.2.1   thorpej }
   2120  1.5.2.1   thorpej ATF_TC_CLEANUP(futex_rw_wait_write_wanted_rt_reader_preferred, tc)
   2121  1.5.2.1   thorpej {
   2122  1.5.2.1   thorpej 	do_cleanup();
   2123  1.5.2.1   thorpej }
   2124  1.5.2.1   thorpej 
   2125  1.5.2.1   thorpej /*****************************************************************************/
   2126  1.5.2.1   thorpej 
   2127  1.5.2.1   thorpej static void
   2128  1.5.2.1   thorpej do_test_rw_handoff_rt_prio_order(void)
   2129  1.5.2.1   thorpej {
   2130  1.5.2.1   thorpej 	unsigned int i, tries;
   2131  1.5.2.1   thorpej 	lwpid_t lid;
   2132  1.5.2.1   thorpej 
   2133  1.5.2.1   thorpej 	setup_rt_params();
   2134  1.5.2.1   thorpej 
   2135  1.5.2.1   thorpej 	/*
   2136  1.5.2.1   thorpej 	 * We need to show the rwlock as write-locked to ensure
   2137  1.5.2.1   thorpej 	 * the rt read-waiter blocks.
   2138  1.5.2.1   thorpej 	 */
   2139  1.5.2.1   thorpej 	futex_word =
   2140  1.5.2.1   thorpej 	    FUTEX_WAITERS | FUTEX_RW_WRITE_WANTED | FUTEX_RW_WRITE_LOCKED;
   2141  1.5.2.1   thorpej 	membar_sync();
   2142  1.5.2.1   thorpej 
   2143  1.5.2.1   thorpej 	/*
   2144  1.5.2.1   thorpej 	 * Create LWPs in the following order:
   2145  1.5.2.1   thorpej 	 *
   2146  1.5.2.1   thorpej 	 *	0 - pri_min+0 writer
   2147  1.5.2.1   thorpej 	 *	1 - pri_min+1 reader
   2148  1.5.2.1   thorpej 	 *	2 - pri_min+2 writer
   2149  1.5.2.1   thorpej 	 *	3 - pri_min+3 reader
   2150  1.5.2.1   thorpej 	 *
   2151  1.5.2.1   thorpej 	 * We expect only one to be awakened at each hand-off and for them
   2152  1.5.2.1   thorpej 	 * to be awakened in this order:
   2153  1.5.2.1   thorpej 	 *
   2154  1.5.2.1   thorpej 	 *	3 -> 2 -> 1 -> 0
   2155  1.5.2.1   thorpej 	 */
   2156  1.5.2.1   thorpej 	for (i = 0; i < 4; i++) {
   2157  1.5.2.1   thorpej 		setup_lwp_context(&lwp_data[i], rt_simple_test_waiter_lwp);
   2158  1.5.2.1   thorpej 		lwp_data[i].rt_prio = pri_min + i;
   2159  1.5.2.1   thorpej 		lwp_data[i].op_flags = FUTEX_PRIVATE_FLAG;
   2160  1.5.2.1   thorpej 		lwp_data[i].futex_error = -1;
   2161  1.5.2.1   thorpej 		lwp_data[i].futex_ptr = &futex_word;
   2162  1.5.2.1   thorpej 		lwp_data[i].block_val = futex_word;
   2163  1.5.2.1   thorpej 		lwp_data[i].bitset = i & 1 ? FUTEX_RW_READER : FUTEX_RW_WRITER;
   2164  1.5.2.1   thorpej 		lwp_data[i].wait_op = FUTEX_NETBSD_RW_WAIT;
   2165  1.5.2.1   thorpej 		ATF_REQUIRE(_lwp_create(&lwp_data[i].context, 0,
   2166  1.5.2.1   thorpej 					&lwp_data[i].lwpid) == 0);
   2167  1.5.2.1   thorpej 
   2168  1.5.2.1   thorpej 		/*
   2169  1.5.2.1   thorpej 		 * Wait for each one to start in-turn, because we want
   2170  1.5.2.1   thorpej 		 * to know the order in which the LWPs block on the futex.
   2171  1.5.2.1   thorpej 		 */
   2172  1.5.2.1   thorpej 		for (tries = 0; tries < 5; tries++) {
   2173  1.5.2.1   thorpej 			membar_sync();
   2174  1.5.2.1   thorpej 			if (nlwps_running == i + 1)
   2175  1.5.2.1   thorpej 				break;
   2176  1.5.2.1   thorpej 			sleep(1);
   2177  1.5.2.1   thorpej 		}
   2178  1.5.2.1   thorpej 		membar_sync();
   2179  1.5.2.1   thorpej 	}
   2180  1.5.2.1   thorpej 
   2181  1.5.2.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 4, "waiters failed to start");
   2182  1.5.2.1   thorpej 
   2183  1.5.2.1   thorpej 	/* Ensure they're all blocked. */
   2184  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[0].futex_error == -1);
   2185  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[1].futex_error == -1);
   2186  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[2].futex_error == -1);
   2187  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[3].futex_error == -1);
   2188  1.5.2.1   thorpej 
   2189  1.5.2.1   thorpej 	/*
   2190  1.5.2.1   thorpej 	 * Issue a hand-off.  It should select the pri_min+3 reader, and should
   2191  1.5.2.1   thorpej 	 * indicate that there are still waiters, including a write-waiter.
   2192  1.5.2.1   thorpej 	 */
   2193  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   2194  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   2195  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 1);
   2196  1.5.2.1   thorpej 	ATF_REQUIRE((futex_word & FUTEX_RW_WRITE_LOCKED) == 0);
   2197  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_WANTED);
   2198  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_WAITERS);
   2199  1.5.2.1   thorpej 	lid = futex_word & FUTEX_TID_MASK;
   2200  1.5.2.1   thorpej 	ATF_REQUIRE(lid == 1);
   2201  1.5.2.1   thorpej 	ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
   2202  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[3].lwpid);
   2203  1.5.2.1   thorpej 
   2204  1.5.2.1   thorpej 	/*
   2205  1.5.2.1   thorpej 	 * Issue another hand-off.  It should awaken the pri_min+2 writer and
   2206  1.5.2.1   thorpej 	 * indicate that there are still waiters, including a write-waiter.
   2207  1.5.2.1   thorpej 	 */
   2208  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   2209  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   2210  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 1);
   2211  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_LOCKED);
   2212  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_WANTED);
   2213  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_WAITERS);
   2214  1.5.2.1   thorpej 	lid = futex_word & FUTEX_TID_MASK;
   2215  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[2].lwpid);
   2216  1.5.2.1   thorpej 	ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
   2217  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[2].lwpid);
   2218  1.5.2.1   thorpej 
   2219  1.5.2.1   thorpej 	/*
   2220  1.5.2.1   thorpej 	 * Issue another a hand-off.  It should select the pri_min+1 reader,
   2221  1.5.2.1   thorpej 	 * and should indicate that there are still waiters, including a
   2222  1.5.2.1   thorpej 	 * write-waiter.
   2223  1.5.2.1   thorpej 	 */
   2224  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   2225  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   2226  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 1);
   2227  1.5.2.1   thorpej 	ATF_REQUIRE((futex_word & FUTEX_RW_WRITE_LOCKED) == 0);
   2228  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_WANTED);
   2229  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_WAITERS);
   2230  1.5.2.1   thorpej 	lid = futex_word & FUTEX_TID_MASK;
   2231  1.5.2.1   thorpej 	ATF_REQUIRE(lid == 1);
   2232  1.5.2.1   thorpej 	ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
   2233  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[1].lwpid);
   2234  1.5.2.1   thorpej 
   2235  1.5.2.1   thorpej 	/*
   2236  1.5.2.1   thorpej 	 * Issue another hand-off.  It should awaken the pri_min+0 writer and
   2237  1.5.2.1   thorpej 	 * indicate that there are no more waiters.
   2238  1.5.2.1   thorpej 	 */
   2239  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   2240  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   2241  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 1);
   2242  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_LOCKED);
   2243  1.5.2.1   thorpej 	ATF_REQUIRE((futex_word & FUTEX_RW_WRITE_WANTED) == 0);
   2244  1.5.2.1   thorpej 	ATF_REQUIRE((futex_word & FUTEX_WAITERS) == 0);
   2245  1.5.2.1   thorpej 	lid = futex_word & FUTEX_TID_MASK;
   2246  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[0].lwpid);
   2247  1.5.2.1   thorpej 	ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
   2248  1.5.2.1   thorpej 	ATF_REQUIRE(lid == lwp_data[0].lwpid);
   2249  1.5.2.1   thorpej 
   2250  1.5.2.1   thorpej 	/*
   2251  1.5.2.1   thorpej 	 * Issue one final hand-off; it should result in a fully
   2252  1.5.2.1   thorpej 	 * released lock word.  Note that we don't have any
   2253  1.5.2.1   thorpej 	 * outstaning waiters waiting, and therefore there will
   2254  1.5.2.1   thorpej 	 * not be a kernel futex; this exercises a specific code
   2255  1.5.2.1   thorpej 	 * path in the kernel designed to handle this.
   2256  1.5.2.1   thorpej 	 */
   2257  1.5.2.1   thorpej 	ATF_REQUIRE(__futex(&futex_word,
   2258  1.5.2.1   thorpej 			    FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
   2259  1.5.2.1   thorpej 			    futex_word, NULL, NULL, 0, 0) == 0);
   2260  1.5.2.1   thorpej 	ATF_REQUIRE(futex_word == 0);
   2261  1.5.2.1   thorpej 
   2262  1.5.2.1   thorpej 	for (tries = 0; tries < 5; tries++) {
   2263  1.5.2.1   thorpej 		membar_sync();
   2264  1.5.2.1   thorpej 		if (nlwps_running == 0)
   2265  1.5.2.1   thorpej 			break;
   2266  1.5.2.1   thorpej 		sleep(1);
   2267  1.5.2.1   thorpej 	}
   2268  1.5.2.1   thorpej 	membar_sync();
   2269  1.5.2.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "threads failed to exit");
   2270  1.5.2.1   thorpej 
   2271  1.5.2.1   thorpej 	/* Ensure they all exited error-free. */
   2272  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[0].futex_error == 0);
   2273  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[1].futex_error == 0);
   2274  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[2].futex_error == 0);
   2275  1.5.2.1   thorpej 	ATF_REQUIRE(lwp_data[3].futex_error == 0);
   2276  1.5.2.1   thorpej }
   2277  1.5.2.1   thorpej 
   2278  1.5.2.1   thorpej ATF_TC_WITH_CLEANUP(futex_rw_handoff_rt_prio_order);
   2279  1.5.2.1   thorpej ATF_TC_HEAD(futex_rw_handoff_rt_prio_order, tc)
   2280  1.5.2.1   thorpej {
   2281  1.5.2.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   2282  1.5.2.1   thorpej 	    "tests that hand-off to mixed readers/writer occurs "
   2283  1.5.2.1   thorpej 	    "in strict priority order");
   2284  1.5.2.1   thorpej 	atf_tc_set_md_var(tc, "require.user", "root");
   2285  1.5.2.1   thorpej }
   2286  1.5.2.1   thorpej ATF_TC_BODY(futex_rw_handoff_rt_prio_order, tc)
   2287  1.5.2.1   thorpej {
   2288  1.5.2.1   thorpej 	atf_tc_skip("futex_rw_handoff is currently broken");
   2289  1.5.2.1   thorpej 	do_test_rw_handoff_rt_prio_order();
   2290  1.5.2.1   thorpej }
   2291  1.5.2.1   thorpej ATF_TC_CLEANUP(futex_rw_handoff_rt_prio_order, tc)
   2292  1.5.2.1   thorpej {
   2293  1.5.2.1   thorpej 	do_cleanup();
   2294  1.5.2.1   thorpej }
   2295  1.5.2.1   thorpej 
   2296  1.5.2.1   thorpej /*****************************************************************************/
   2297  1.5.2.1   thorpej 
   2298      1.1   thorpej ATF_TP_ADD_TCS(tp)
   2299      1.1   thorpej {
   2300      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_basic_wait_wake_private);
   2301      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_basic_wait_wake_shared);
   2302      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_private);
   2303      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_shared);
   2304      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_private);
   2305      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_shared);
   2306      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_cow_private);
   2307      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_cow_shared);
   2308      1.1   thorpej 
   2309      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_shared_proc);
   2310      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_shared_proc);
   2311      1.1   thorpej 
   2312      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_pointless_bitset);
   2313      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_bitset);
   2314      1.1   thorpej 
   2315      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_timeout_relative);
   2316      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_timeout_relative_rt);
   2317      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_timeout_deadline);
   2318      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_timeout_deadline_rt);
   2319      1.1   thorpej 
   2320      1.3   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_evil_unmapped_anon);
   2321      1.3   thorpej 
   2322      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_requeue);
   2323      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_cmp_requeue);
   2324      1.1   thorpej 
   2325      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wake_op_op);
   2326      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wake_op_cmp);
   2327      1.1   thorpej 
   2328      1.4   thorpej 	ATF_TP_ADD_TC(tp, futex_wake_highest_pri);
   2329      1.4   thorpej 
   2330  1.5.2.1   thorpej 	ATF_TP_ADD_TC(tp, futex_rw_handoff_read);
   2331  1.5.2.1   thorpej 	ATF_TP_ADD_TC(tp, futex_rw_handoff_write);
   2332  1.5.2.1   thorpej 	ATF_TP_ADD_TC(tp, futex_rw_handoff_write_preferred);
   2333  1.5.2.1   thorpej 	ATF_TP_ADD_TC(tp, futex_rw_handoff_write_locked_rt_reader_preferred);
   2334  1.5.2.1   thorpej 	ATF_TP_ADD_TC(tp, futex_rw_wait_write_wanted_rt_reader_preferred);
   2335  1.5.2.1   thorpej 	ATF_TP_ADD_TC(tp, futex_rw_handoff_rt_prio_order);
   2336  1.5.2.1   thorpej 
   2337      1.1   thorpej 	return atf_no_error();
   2338      1.1   thorpej }
   2339