Home | History | Annotate | Line # | Download | only in sys
t_futex_ops.c revision 1.5.8.1
      1  1.5.8.1   thorpej /* $NetBSD: t_futex_ops.c,v 1.5.8.1 2021/08/07 01:44:51 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.8.1   thorpej __RCSID("$NetBSD: t_futex_ops.c,v 1.5.8.1 2021/08/07 01:44:51 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.1   thorpej 
     82      1.1   thorpej 	void		(*exit_func)(void);
     83      1.1   thorpej 
     84      1.1   thorpej 	int		futex_error;
     85      1.1   thorpej };
     86      1.1   thorpej 
     87      1.1   thorpej #define	WAITER_LWP0		0
     88      1.1   thorpej #define	WAITER_LWP1		1
     89      1.1   thorpej #define	WAITER_LWP2		2
     90      1.1   thorpej #define	WAITER_LWP3		3
     91      1.1   thorpej #define	WAITER_LWP4		4
     92      1.1   thorpej #define	WAITER_LWP5		5
     93      1.1   thorpej #define	NLWPS			6
     94      1.1   thorpej 
     95      1.1   thorpej struct lwp_data lwp_data[NLWPS];
     96      1.1   thorpej 
     97      1.1   thorpej static const char *bs_path = "t_futex_ops_backing_store";
     98      1.1   thorpej static int bs_fd = -1;
     99      1.1   thorpej static int *bs_addr = MAP_FAILED;
    100      1.1   thorpej static void *bs_source_buffer = NULL;
    101      1.1   thorpej static void *bs_verify_buffer = NULL;
    102      1.1   thorpej static long bs_pagesize;
    103      1.1   thorpej 
    104      1.1   thorpej static void
    105      1.1   thorpej create_lwp_waiter(struct lwp_data *d)
    106      1.1   thorpej {
    107      1.1   thorpej 	ATF_REQUIRE(_lwp_create(&d->context, 0, &d->lwpid) == 0);
    108      1.1   thorpej }
    109      1.1   thorpej 
    110      1.1   thorpej static void
    111      1.1   thorpej exit_lwp_waiter(void)
    112      1.1   thorpej {
    113      1.1   thorpej 	_lwp_exit();
    114      1.1   thorpej }
    115      1.1   thorpej 
    116      1.1   thorpej static void
    117      1.1   thorpej reap_lwp_waiter(struct lwp_data *d)
    118      1.1   thorpej {
    119      1.1   thorpej 	ATF_REQUIRE(_lwp_wait(d->lwpid, NULL) == 0);
    120      1.1   thorpej }
    121      1.1   thorpej 
    122      1.1   thorpej static void
    123      1.1   thorpej create_proc_waiter(struct lwp_data *d)
    124      1.1   thorpej {
    125      1.1   thorpej 	pid_t pid;
    126      1.1   thorpej 
    127      1.1   thorpej 	ATF_REQUIRE((pid = fork()) != -1);
    128      1.1   thorpej 	if (pid == 0) {
    129      1.1   thorpej 		(*d->func)(d);
    130      1.1   thorpej 		_exit(666);		/* backstop */
    131      1.1   thorpej 	} else
    132      1.1   thorpej 		d->child = pid;
    133      1.1   thorpej }
    134      1.1   thorpej 
    135      1.1   thorpej static void
    136      1.1   thorpej exit_proc_waiter(void)
    137      1.1   thorpej {
    138      1.1   thorpej 	_exit(0);
    139      1.1   thorpej }
    140      1.1   thorpej 
    141      1.1   thorpej static void
    142      1.1   thorpej reap_proc_waiter(struct lwp_data *d)
    143      1.1   thorpej {
    144      1.1   thorpej 	int status;
    145      1.1   thorpej 
    146      1.1   thorpej 	ATF_REQUIRE(waitpid(d->child, &status, 0) == d->child);
    147      1.1   thorpej 	ATF_REQUIRE(WIFEXITED(status));
    148      1.1   thorpej 	ATF_REQUIRE(WEXITSTATUS(status) == 0);
    149      1.1   thorpej }
    150      1.1   thorpej 
    151      1.1   thorpej static void
    152      1.1   thorpej setup_lwp_context(struct lwp_data *d, void (*func)(void *))
    153      1.1   thorpej {
    154      1.1   thorpej 
    155      1.1   thorpej 	memset(d, 0, sizeof(*d));
    156      1.1   thorpej 	d->stack_base = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
    157      1.1   thorpej 	    MAP_ANON | MAP_STACK | MAP_PRIVATE, -1, 0);
    158      1.1   thorpej 	ATF_REQUIRE(d->stack_base != MAP_FAILED);
    159      1.1   thorpej 	_lwp_makecontext(&d->context, func, d, NULL, d->stack_base, STACK_SIZE);
    160      1.1   thorpej 	d->threadid = 0;
    161      1.1   thorpej 	d->func = func;
    162      1.1   thorpej }
    163      1.1   thorpej 
    164      1.1   thorpej static void
    165      1.1   thorpej simple_test_waiter_lwp(void *arg)
    166      1.1   thorpej {
    167      1.1   thorpej 	struct lwp_data *d = arg;
    168      1.1   thorpej 
    169      1.1   thorpej 	d->threadid = _lwp_self();
    170      1.1   thorpej 
    171      1.3   thorpej 	membar_producer();
    172      1.1   thorpej 	atomic_inc_uint(&nlwps_running);
    173      1.1   thorpej 	membar_sync();
    174      1.1   thorpej 
    175      1.1   thorpej 	if (__futex(d->futex_ptr, d->wait_op | d->op_flags,
    176      1.1   thorpej 		    d->block_val, NULL, NULL, 0, d->bitset) == -1) {
    177      1.1   thorpej 		d->futex_error = errno;
    178      1.3   thorpej 		membar_sync();
    179      1.3   thorpej 		atomic_dec_uint(&nlwps_running);
    180      1.1   thorpej 		_lwp_exit();
    181      1.1   thorpej 	} else {
    182      1.1   thorpej 		d->futex_error = 0;
    183      1.1   thorpej 	}
    184      1.1   thorpej 
    185      1.1   thorpej 	membar_sync();
    186      1.1   thorpej 	atomic_dec_uint(&nlwps_running);
    187      1.1   thorpej 
    188      1.1   thorpej 	_lwp_exit();
    189      1.1   thorpej }
    190      1.1   thorpej 
    191      1.1   thorpej static bool
    192      1.1   thorpej verify_zero_bs(void)
    193      1.1   thorpej {
    194      1.1   thorpej 
    195      1.1   thorpej 	if (bs_verify_buffer == NULL) {
    196      1.1   thorpej 		bs_verify_buffer = malloc(bs_pagesize);
    197      1.1   thorpej 		ATF_REQUIRE(bs_verify_buffer != NULL);
    198      1.1   thorpej 	}
    199      1.1   thorpej 
    200      1.1   thorpej 	ATF_REQUIRE(pread(bs_fd, bs_verify_buffer,
    201      1.1   thorpej 			  bs_pagesize, 0) == bs_pagesize);
    202      1.1   thorpej 
    203      1.1   thorpej 	return (memcmp(bs_verify_buffer, bs_source_buffer, bs_pagesize) == 0);
    204      1.1   thorpej }
    205      1.1   thorpej 
    206      1.1   thorpej static void
    207      1.1   thorpej create_bs(int map_flags)
    208      1.1   thorpej {
    209      1.1   thorpej 
    210      1.1   thorpej 	bs_pagesize = sysconf(_SC_PAGESIZE);
    211      1.1   thorpej 	ATF_REQUIRE(bs_pagesize > 0);
    212      1.1   thorpej 
    213      1.1   thorpej 	if ((map_flags & (MAP_FILE | MAP_ANON)) == MAP_FILE) {
    214      1.1   thorpej 		bs_source_buffer = calloc(1, bs_pagesize);
    215      1.1   thorpej 		ATF_REQUIRE(bs_source_buffer != NULL);
    216      1.1   thorpej 
    217      1.1   thorpej 		bs_fd = open(bs_path, O_RDWR | O_CREAT | O_EXCL, 0644);
    218      1.1   thorpej 		ATF_REQUIRE(bs_fd != -1);
    219      1.1   thorpej 
    220      1.1   thorpej 		ATF_REQUIRE(pwrite(bs_fd, bs_source_buffer,
    221      1.1   thorpej 				   bs_pagesize, 0) == bs_pagesize);
    222      1.1   thorpej 		ATF_REQUIRE(verify_zero_bs());
    223      1.1   thorpej 	}
    224      1.1   thorpej 
    225      1.1   thorpej 	bs_addr = mmap(NULL, bs_pagesize, PROT_READ | PROT_WRITE,
    226      1.1   thorpej 		       map_flags | MAP_HASSEMAPHORE, bs_fd, 0);
    227      1.1   thorpej 	ATF_REQUIRE(bs_addr != MAP_FAILED);
    228      1.1   thorpej }
    229      1.1   thorpej 
    230      1.1   thorpej static void
    231      1.1   thorpej cleanup_bs(void)
    232      1.1   thorpej {
    233      1.1   thorpej 
    234      1.1   thorpej 	if (bs_fd != -1) {
    235      1.1   thorpej 		(void) close(bs_fd);
    236      1.1   thorpej 		bs_fd = -1;
    237      1.1   thorpej 		(void) unlink(bs_path);
    238      1.1   thorpej 	}
    239      1.1   thorpej 	if (bs_source_buffer != NULL) {
    240      1.1   thorpej 		free(bs_source_buffer);
    241      1.1   thorpej 		bs_source_buffer = NULL;
    242      1.1   thorpej 	}
    243      1.1   thorpej 	if (bs_verify_buffer != NULL) {
    244      1.1   thorpej 		free(bs_verify_buffer);
    245      1.1   thorpej 		bs_verify_buffer = NULL;
    246      1.1   thorpej 	}
    247      1.1   thorpej 	if (bs_addr != MAP_FAILED) {
    248      1.1   thorpej 		munmap(bs_addr, bs_pagesize);
    249      1.1   thorpej 		bs_addr = MAP_FAILED;
    250      1.1   thorpej 	}
    251      1.1   thorpej }
    252      1.1   thorpej 
    253      1.1   thorpej static void
    254      1.1   thorpej do_cleanup(void)
    255      1.1   thorpej {
    256      1.1   thorpej 	int i;
    257      1.1   thorpej 
    258      1.1   thorpej 	for (i = 0; i < NLWPS; i++) {
    259      1.1   thorpej 		struct lwp_data *d = &lwp_data[i];
    260      1.1   thorpej 		if (d->stack_base != NULL && d->stack_base != MAP_FAILED) {
    261      1.1   thorpej 			(void) munmap(d->stack_base, STACK_SIZE);
    262      1.1   thorpej 		}
    263      1.1   thorpej 	}
    264      1.1   thorpej 	memset(lwp_data, 0, sizeof(lwp_data));
    265      1.1   thorpej 	STORE(&futex_word, 0);
    266      1.1   thorpej 	STORE(&futex_word1, 0);
    267      1.1   thorpej 	nlwps_running = 0;
    268      1.1   thorpej 
    269      1.1   thorpej 	cleanup_bs();
    270      1.1   thorpej }
    271      1.1   thorpej 
    272      1.1   thorpej /*****************************************************************************/
    273      1.1   thorpej 
    274      1.1   thorpej static void
    275      1.1   thorpej wait_wake_test_waiter_lwp(void *arg)
    276      1.1   thorpej {
    277      1.1   thorpej 	struct lwp_data *d = arg;
    278      1.1   thorpej 
    279      1.1   thorpej 	d->threadid = _lwp_self();
    280      1.1   thorpej 
    281      1.1   thorpej 	STORE(d->futex_ptr, 1);
    282      1.1   thorpej 	membar_sync();
    283      1.1   thorpej 
    284      1.1   thorpej 	/* This will block because *futex_ptr == 1. */
    285      1.1   thorpej 	if (__futex(d->futex_ptr, FUTEX_WAIT | d->op_flags,
    286      1.1   thorpej 		    1, NULL, NULL, 0, 0) == -1) {
    287      1.1   thorpej 		STORE(d->error_ptr, errno);
    288      1.1   thorpej 		(*d->exit_func)();
    289      1.1   thorpej 	} else {
    290      1.1   thorpej 		STORE(d->error_ptr, 0);
    291      1.1   thorpej 	}
    292      1.1   thorpej 
    293      1.1   thorpej 	do {
    294      1.1   thorpej 		membar_sync();
    295      1.1   thorpej 		sleep(1);
    296      1.1   thorpej 	} while (LOAD(d->futex_ptr) != 0);
    297      1.1   thorpej 
    298      1.1   thorpej 	STORE(d->futex_ptr, 2);
    299      1.1   thorpej 	membar_sync();
    300      1.1   thorpej 
    301      1.1   thorpej 	do {
    302      1.1   thorpej 		membar_sync();
    303      1.1   thorpej 		sleep(1);
    304      1.1   thorpej 	} while (LOAD(d->futex_ptr) != 3);
    305      1.1   thorpej 
    306      1.1   thorpej 	/* This will not block because futex_word != 666. */
    307      1.1   thorpej 	if (__futex(d->futex_ptr, FUTEX_WAIT | d->op_flags,
    308      1.1   thorpej 		    666, NULL, NULL, 0, 0) == -1) {
    309      1.1   thorpej 		/* This SHOULD be EAGAIN. */
    310      1.1   thorpej 		STORE(d->error_ptr, errno);
    311      1.1   thorpej 	}
    312      1.1   thorpej 
    313      1.1   thorpej 	STORE(d->futex_ptr, 4);
    314      1.1   thorpej 	membar_sync();
    315      1.1   thorpej 
    316      1.1   thorpej 	(*d->exit_func)();
    317      1.1   thorpej }
    318      1.1   thorpej 
    319      1.1   thorpej static void
    320      1.1   thorpej do_futex_wait_wake_test(volatile int *futex_ptr, volatile int *error_ptr,
    321      1.1   thorpej 			void (*create_func)(struct lwp_data *),
    322      1.1   thorpej 			void (*exit_func)(void),
    323      1.1   thorpej 			void (*reap_func)(struct lwp_data *),
    324      1.1   thorpej 			int flags)
    325      1.1   thorpej {
    326      1.1   thorpej 	struct lwp_data *wlwp = &lwp_data[WAITER_LWP0];
    327      1.1   thorpej 	int tries;
    328      1.1   thorpej 
    329      1.1   thorpej 	if (error_ptr == NULL)
    330      1.1   thorpej 		error_ptr = &wlwp->futex_error;
    331      1.1   thorpej 
    332      1.1   thorpej 	if (create_func == NULL)
    333      1.1   thorpej 		create_func = create_lwp_waiter;
    334      1.1   thorpej 	if (exit_func == NULL)
    335      1.1   thorpej 		exit_func = exit_lwp_waiter;
    336      1.1   thorpej 	if (reap_func == NULL)
    337      1.1   thorpej 		reap_func = reap_lwp_waiter;
    338      1.1   thorpej 
    339      1.1   thorpej 	setup_lwp_context(wlwp, wait_wake_test_waiter_lwp);
    340      1.1   thorpej 
    341      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: testing with flags 0x%x\n", flags));
    342      1.1   thorpej 	wlwp->op_flags = flags;
    343      1.1   thorpej 	wlwp->error_ptr = error_ptr;
    344      1.1   thorpej 	STORE(error_ptr, -1);
    345      1.1   thorpej 	wlwp->futex_ptr = futex_ptr;
    346      1.1   thorpej 	STORE(futex_ptr, 0);
    347      1.1   thorpej 	wlwp->exit_func = exit_func;
    348      1.1   thorpej 	membar_sync();
    349      1.1   thorpej 
    350      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: creating watier LWP\n"));
    351      1.1   thorpej 	(*create_func)(wlwp);
    352      1.1   thorpej 
    353      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: waiting for LWP %d to enter futex\n",
    354      1.1   thorpej 	    wlwp->lwpid));
    355      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    356      1.1   thorpej 		membar_sync();
    357      1.1   thorpej 		if (LOAD(futex_ptr) == 1)
    358      1.1   thorpej 			break;
    359      1.1   thorpej 		sleep(1);
    360      1.1   thorpej 	}
    361      1.1   thorpej 	membar_sync();
    362      1.1   thorpej 	ATF_REQUIRE(LOAD(futex_ptr) == 1);
    363      1.1   thorpej 
    364      1.1   thorpej 	/*
    365      1.1   thorpej 	 * If the LWP is blocked in the futex, it will not have yet
    366      1.1   thorpej 	 * modified *error_ptr.
    367      1.1   thorpej 	 */
    368      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: checking for successful wait (%d)\n",
    369      1.1   thorpej 	    LOAD(error_ptr)));
    370      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    371      1.1   thorpej 		membar_sync();
    372      1.1   thorpej 		if (LOAD(error_ptr) == -1)
    373      1.1   thorpej 			break;
    374      1.1   thorpej 		sleep(1);
    375      1.1   thorpej 	}
    376      1.1   thorpej 	membar_sync();
    377      1.1   thorpej 	ATF_REQUIRE(LOAD(error_ptr) == -1);
    378      1.1   thorpej 
    379      1.1   thorpej 	/* Make sure invalid #wakes in rejected. */
    380      1.1   thorpej 	ATF_REQUIRE_ERRNO(EINVAL,
    381      1.1   thorpej 	    __futex(futex_ptr, FUTEX_WAKE | flags,
    382      1.1   thorpej 		    -1, NULL, NULL, 0, 0) == -1);
    383      1.1   thorpej 
    384      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: waking 1 waiter\n"));
    385      1.1   thorpej 	ATF_REQUIRE(__futex(futex_ptr, FUTEX_WAKE | flags,
    386      1.1   thorpej 			    1, NULL, NULL, 0, 0) == 1);
    387      1.1   thorpej 
    388      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: checking for successful wake (%d)\n",
    389      1.1   thorpej 	    LOAD(error_ptr)));
    390      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    391      1.1   thorpej 		membar_sync();
    392      1.1   thorpej 		if (LOAD(error_ptr) == 0)
    393      1.1   thorpej 			break;
    394      1.1   thorpej 		sleep(1);
    395      1.1   thorpej 	}
    396      1.1   thorpej 	membar_sync();
    397      1.1   thorpej 	ATF_REQUIRE(LOAD(error_ptr) == 0);
    398      1.1   thorpej 
    399      1.1   thorpej 	STORE(futex_ptr, 0);
    400      1.1   thorpej 	membar_sync();
    401      1.1   thorpej 
    402      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: waiting for LWP to advance (2)\n"));
    403      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    404      1.1   thorpej 		membar_sync();
    405      1.1   thorpej 		if (LOAD(futex_ptr) == 2)
    406      1.1   thorpej 			break;
    407      1.1   thorpej 		sleep(1);
    408      1.1   thorpej 	}
    409      1.1   thorpej 	membar_sync();
    410      1.1   thorpej 	ATF_REQUIRE(LOAD(futex_ptr) == 2);
    411      1.1   thorpej 
    412      1.1   thorpej 	STORE(futex_ptr, 3);
    413      1.1   thorpej 	membar_sync();
    414      1.1   thorpej 
    415      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: waiting for LWP to advance (4)\n"));
    416      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    417      1.1   thorpej 		membar_sync();
    418      1.1   thorpej 		if (LOAD(futex_ptr) == 4)
    419      1.1   thorpej 			break;
    420      1.1   thorpej 		sleep(1);
    421      1.1   thorpej 	}
    422      1.1   thorpej 	membar_sync();
    423      1.1   thorpej 	ATF_REQUIRE(LOAD(futex_ptr) == 4);
    424      1.1   thorpej 
    425      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: checking for expected EGAIN\n"));
    426      1.1   thorpej 	ATF_REQUIRE(LOAD(error_ptr) == EAGAIN);
    427      1.1   thorpej 
    428      1.1   thorpej 	DPRINTF(("futex_basic_wait_wake: reaping LWP %d\n", wlwp->lwpid));
    429      1.1   thorpej 	(*reap_func)(wlwp);
    430      1.1   thorpej }
    431      1.1   thorpej 
    432      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_basic_wait_wake_private);
    433      1.1   thorpej ATF_TC_HEAD(futex_basic_wait_wake_private, tc)
    434      1.1   thorpej {
    435      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    436      1.1   thorpej 	    "tests basic futex WAIT + WAKE operations (PRIVATE)");
    437      1.1   thorpej }
    438      1.1   thorpej ATF_TC_BODY(futex_basic_wait_wake_private, tc)
    439      1.1   thorpej {
    440      1.1   thorpej 	do_futex_wait_wake_test(&futex_word, NULL,
    441      1.1   thorpej 				NULL, NULL, NULL,
    442      1.1   thorpej 				FUTEX_PRIVATE_FLAG);
    443      1.1   thorpej }
    444      1.1   thorpej ATF_TC_CLEANUP(futex_basic_wait_wake_private, tc)
    445      1.1   thorpej {
    446      1.1   thorpej 	do_cleanup();
    447      1.1   thorpej }
    448      1.1   thorpej 
    449      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_basic_wait_wake_shared);
    450      1.1   thorpej ATF_TC_HEAD(futex_basic_wait_wake_shared, tc)
    451      1.1   thorpej {
    452      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    453      1.1   thorpej 	    "tests basic futex WAIT + WAKE operations (SHARED)");
    454      1.1   thorpej }
    455      1.1   thorpej ATF_TC_BODY(futex_basic_wait_wake_shared, tc)
    456      1.1   thorpej {
    457      1.1   thorpej 	do_futex_wait_wake_test(&futex_word, NULL,
    458      1.1   thorpej 				NULL, NULL, NULL,
    459      1.1   thorpej 				0);
    460      1.1   thorpej }
    461      1.1   thorpej ATF_TC_CLEANUP(futex_basic_wait_wake_shared, tc)
    462      1.1   thorpej {
    463      1.1   thorpej 	do_cleanup();
    464      1.1   thorpej }
    465      1.1   thorpej 
    466      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_anon_bs_private);
    467      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_anon_bs_private, tc)
    468      1.1   thorpej {
    469      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    470      1.1   thorpej 	    "tests futex WAIT + WAKE operations (MAP_ANON + PRIVATE)");
    471      1.1   thorpej }
    472      1.1   thorpej ATF_TC_BODY(futex_wait_wake_anon_bs_private, tc)
    473      1.1   thorpej {
    474      1.1   thorpej 	create_bs(MAP_ANON | MAP_PRIVATE);
    475      1.1   thorpej 	do_futex_wait_wake_test(&bs_addr[0], NULL,
    476      1.1   thorpej 				NULL, NULL, NULL,
    477      1.1   thorpej 				FUTEX_PRIVATE_FLAG);
    478      1.1   thorpej }
    479      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_anon_bs_private, tc)
    480      1.1   thorpej {
    481      1.1   thorpej 	do_cleanup();
    482      1.1   thorpej }
    483      1.1   thorpej 
    484      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_anon_bs_shared);
    485      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_anon_bs_shared, tc)
    486      1.1   thorpej {
    487      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    488      1.1   thorpej 	    "tests futex WAIT + WAKE operations (MAP_ANON + SHARED)");
    489      1.1   thorpej }
    490      1.1   thorpej ATF_TC_BODY(futex_wait_wake_anon_bs_shared, tc)
    491      1.1   thorpej {
    492      1.1   thorpej 	create_bs(MAP_ANON | MAP_PRIVATE);
    493      1.1   thorpej 	do_futex_wait_wake_test(&bs_addr[0], NULL,
    494      1.1   thorpej 				NULL, NULL, NULL,
    495      1.1   thorpej 				0);
    496      1.1   thorpej }
    497      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_anon_bs_shared, tc)
    498      1.1   thorpej {
    499      1.1   thorpej 	do_cleanup();
    500      1.1   thorpej }
    501      1.1   thorpej 
    502      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_file_bs_private);
    503      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_file_bs_private, tc)
    504      1.1   thorpej {
    505      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    506      1.1   thorpej 	    "tests futex WAIT + WAKE operations (MAP_FILE + PRIVATE)");
    507      1.1   thorpej }
    508      1.1   thorpej ATF_TC_BODY(futex_wait_wake_file_bs_private, tc)
    509      1.1   thorpej {
    510      1.1   thorpej 	/*
    511      1.1   thorpej 	 * This combination (non-COW mapped file + PRIVATE futex)
    512      1.1   thorpej 	 * doesn't really make sense, but we should make sure it
    513      1.1   thorpej 	 * works as expected.
    514      1.1   thorpej 	 */
    515      1.1   thorpej 	create_bs(MAP_FILE | MAP_SHARED);
    516      1.1   thorpej 	do_futex_wait_wake_test(&bs_addr[0], NULL,
    517      1.1   thorpej 				NULL, NULL, NULL,
    518      1.1   thorpej 				FUTEX_PRIVATE_FLAG);
    519      1.1   thorpej 	ATF_REQUIRE(! verify_zero_bs());
    520      1.1   thorpej }
    521      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_file_bs_private, tc)
    522      1.1   thorpej {
    523      1.1   thorpej 	do_cleanup();
    524      1.1   thorpej }
    525      1.1   thorpej 
    526      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_file_bs_cow_private);
    527      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_file_bs_cow_private, tc)
    528      1.1   thorpej {
    529      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    530      1.1   thorpej 	    "tests futex WAIT + WAKE operations (MAP_FILE COW + PRIVATE)");
    531      1.1   thorpej }
    532      1.1   thorpej ATF_TC_BODY(futex_wait_wake_file_bs_cow_private, tc)
    533      1.1   thorpej {
    534      1.1   thorpej 	create_bs(MAP_FILE | MAP_PRIVATE);
    535      1.1   thorpej 	do_futex_wait_wake_test(&bs_addr[0], NULL,
    536      1.1   thorpej 				NULL, NULL, NULL,
    537      1.1   thorpej 				FUTEX_PRIVATE_FLAG);
    538      1.1   thorpej 	ATF_REQUIRE(verify_zero_bs());
    539      1.1   thorpej }
    540      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_file_bs_cow_private, tc)
    541      1.1   thorpej {
    542      1.1   thorpej 	do_cleanup();
    543      1.1   thorpej }
    544      1.1   thorpej 
    545      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_file_bs_shared);
    546      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_file_bs_shared, tc)
    547      1.1   thorpej {
    548      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    549      1.1   thorpej 	    "tests futex WAIT + WAKE operations (MAP_FILE + SHARED)");
    550      1.1   thorpej }
    551      1.1   thorpej ATF_TC_BODY(futex_wait_wake_file_bs_shared, tc)
    552      1.1   thorpej {
    553      1.1   thorpej 	create_bs(MAP_FILE | MAP_SHARED);
    554      1.1   thorpej 	do_futex_wait_wake_test(&bs_addr[0], NULL,
    555      1.1   thorpej 				NULL, NULL, NULL,
    556      1.1   thorpej 				0);
    557      1.1   thorpej 	ATF_REQUIRE(! verify_zero_bs());
    558      1.1   thorpej }
    559      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_file_bs_shared, tc)
    560      1.1   thorpej {
    561      1.1   thorpej 	do_cleanup();
    562      1.1   thorpej }
    563      1.1   thorpej 
    564      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_file_bs_cow_shared);
    565      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_file_bs_cow_shared, tc)
    566      1.1   thorpej {
    567      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    568      1.1   thorpej 	    "tests futex WAIT + WAKE operations (MAP_FILE COW + SHARED)");
    569      1.1   thorpej }
    570      1.1   thorpej ATF_TC_BODY(futex_wait_wake_file_bs_cow_shared, tc)
    571      1.1   thorpej {
    572      1.1   thorpej 	/*
    573      1.1   thorpej 	 * This combination (COW mapped file + SHARED futex)
    574      1.1   thorpej 	 * doesn't really make sense, but we should make sure it
    575      1.1   thorpej 	 * works as expected.
    576      1.1   thorpej 	 */
    577      1.1   thorpej 	create_bs(MAP_FILE | MAP_PRIVATE);
    578      1.1   thorpej 	do_futex_wait_wake_test(&bs_addr[0], NULL,
    579      1.1   thorpej 				NULL, NULL, NULL,
    580      1.1   thorpej 				0);
    581      1.1   thorpej 	ATF_REQUIRE(verify_zero_bs());
    582      1.1   thorpej }
    583      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_file_bs_cow_shared, tc)
    584      1.1   thorpej {
    585      1.1   thorpej 	do_cleanup();
    586      1.1   thorpej }
    587      1.1   thorpej 
    588      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_anon_bs_shared_proc);
    589      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_anon_bs_shared_proc, tc)
    590      1.1   thorpej {
    591      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    592      1.1   thorpej 	    "tests multiproc futex WAIT + WAKE operations (MAP_ANON + SHARED)");
    593      1.1   thorpej }
    594      1.1   thorpej ATF_TC_BODY(futex_wait_wake_anon_bs_shared_proc, tc)
    595      1.1   thorpej {
    596      1.1   thorpej 	create_bs(MAP_ANON | MAP_SHARED);
    597      1.1   thorpej 	do_futex_wait_wake_test(&bs_addr[0], &bs_addr[1],
    598      1.1   thorpej 				create_proc_waiter,
    599      1.1   thorpej 				exit_proc_waiter,
    600      1.1   thorpej 				reap_proc_waiter,
    601      1.1   thorpej 				0);
    602      1.1   thorpej }
    603      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_anon_bs_shared_proc, tc)
    604      1.1   thorpej {
    605      1.1   thorpej 	do_cleanup();
    606      1.1   thorpej }
    607      1.1   thorpej 
    608      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_file_bs_shared_proc);
    609      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_file_bs_shared_proc, tc)
    610      1.1   thorpej {
    611      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    612      1.1   thorpej 	    "tests multiproc futex WAIT + WAKE operations (MAP_ANON + SHARED)");
    613      1.1   thorpej }
    614      1.1   thorpej ATF_TC_BODY(futex_wait_wake_file_bs_shared_proc, tc)
    615      1.1   thorpej {
    616      1.1   thorpej 	create_bs(MAP_FILE | MAP_SHARED);
    617      1.1   thorpej 	do_futex_wait_wake_test(&bs_addr[0], &bs_addr[1],
    618      1.1   thorpej 				create_proc_waiter,
    619      1.1   thorpej 				exit_proc_waiter,
    620      1.1   thorpej 				reap_proc_waiter,
    621      1.1   thorpej 				0);
    622      1.1   thorpej }
    623      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_file_bs_shared_proc, tc)
    624      1.1   thorpej {
    625      1.1   thorpej 	do_cleanup();
    626      1.1   thorpej }
    627      1.1   thorpej 
    628      1.1   thorpej /*****************************************************************************/
    629      1.1   thorpej 
    630      1.1   thorpej ATF_TC(futex_wait_pointless_bitset);
    631      1.1   thorpej ATF_TC_HEAD(futex_wait_pointless_bitset, tc)
    632      1.1   thorpej {
    633      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    634      1.1   thorpej 	    "tests basic futex WAIT + WAKE operations (SHARED)");
    635      1.1   thorpej }
    636      1.1   thorpej ATF_TC_BODY(futex_wait_pointless_bitset, tc)
    637      1.1   thorpej {
    638      1.1   thorpej 
    639      1.1   thorpej 	futex_word = 1;
    640      1.2  riastrad 	ATF_REQUIRE_ERRNO(EINVAL,
    641      1.2  riastrad 	    __futex(&futex_word, FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG,
    642      1.2  riastrad 		1, NULL, NULL, 0, 0) == -1);
    643      1.1   thorpej }
    644      1.1   thorpej 
    645      1.1   thorpej static void
    646      1.1   thorpej do_futex_wait_wake_bitset_test(int flags)
    647      1.1   thorpej {
    648      1.1   thorpej 	struct lwp_data *wlwp0 = &lwp_data[WAITER_LWP0];
    649      1.1   thorpej 	struct lwp_data *wlwp1 = &lwp_data[WAITER_LWP1];
    650      1.1   thorpej 	int i, tries;
    651      1.1   thorpej 
    652      1.1   thorpej 	for (i = WAITER_LWP0; i <= WAITER_LWP1; i++) {
    653      1.1   thorpej 		setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
    654      1.1   thorpej 		lwp_data[i].op_flags = flags;
    655      1.1   thorpej 		lwp_data[i].futex_error = -1;
    656      1.1   thorpej 		lwp_data[i].bitset = __BIT(i);
    657      1.1   thorpej 		lwp_data[i].wait_op = FUTEX_WAIT_BITSET;
    658      1.1   thorpej 		lwp_data[i].futex_ptr = &futex_word;
    659      1.1   thorpej 		lwp_data[i].block_val = 1;
    660      1.1   thorpej 	}
    661      1.1   thorpej 
    662      1.1   thorpej 	STORE(&futex_word, 1);
    663      1.1   thorpej 	membar_sync();
    664      1.1   thorpej 
    665      1.1   thorpej 	ATF_REQUIRE(_lwp_create(&wlwp0->context, 0, &wlwp0->lwpid) == 0);
    666      1.1   thorpej 	ATF_REQUIRE(_lwp_create(&wlwp1->context, 0, &wlwp1->lwpid) == 0);
    667      1.1   thorpej 
    668      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    669      1.1   thorpej 		membar_sync();
    670      1.1   thorpej 		if (nlwps_running == 2)
    671      1.1   thorpej 			break;
    672      1.1   thorpej 		sleep(1);
    673      1.1   thorpej 	}
    674      1.1   thorpej 	membar_sync();
    675      1.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 2, "waiters failed to start");
    676      1.1   thorpej 
    677      1.1   thorpej 	/* Ensure they're blocked. */
    678      1.1   thorpej 	ATF_REQUIRE(wlwp0->futex_error == -1);
    679      1.1   thorpej 	ATF_REQUIRE(wlwp1->futex_error == -1);
    680      1.1   thorpej 
    681      1.1   thorpej 	/* Make sure invalid #wakes in rejected. */
    682      1.1   thorpej 	ATF_REQUIRE_ERRNO(EINVAL,
    683      1.1   thorpej 	    __futex(&futex_word, FUTEX_WAKE_BITSET | flags,
    684      1.1   thorpej 		    -1, NULL, NULL, 0, 0) == -1);
    685      1.1   thorpej 
    686      1.1   thorpej 	/* This should result in no wakeups because no bits are set. */
    687      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_BITSET | flags,
    688      1.1   thorpej 			    INT_MAX, NULL, NULL, 0, 0) == 0);
    689      1.1   thorpej 
    690      1.1   thorpej 	/* This should result in no wakeups because the wrongs bits are set. */
    691      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_BITSET | flags,
    692      1.1   thorpej 			    INT_MAX, NULL, NULL, 0,
    693      1.1   thorpej 			    ~(wlwp0->bitset | wlwp1->bitset)) == 0);
    694      1.1   thorpej 
    695      1.1   thorpej 	/* Trust, but verify. */
    696      1.1   thorpej 	sleep(1);
    697      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    698      1.1   thorpej 		membar_sync();
    699      1.1   thorpej 		if (nlwps_running == 2)
    700      1.1   thorpej 			break;
    701      1.1   thorpej 		sleep(1);
    702      1.1   thorpej 	}
    703      1.1   thorpej 	membar_sync();
    704      1.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 2, "waiters exited unexpectedly");
    705      1.1   thorpej 
    706      1.1   thorpej 	/* Wake up the first LWP. */
    707      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_BITSET | flags,
    708      1.1   thorpej 			    INT_MAX, NULL, NULL, 0,
    709      1.1   thorpej 			    wlwp0->bitset) == 1);
    710      1.1   thorpej 	sleep(1);
    711      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    712      1.1   thorpej 		membar_sync();
    713      1.1   thorpej 		if (nlwps_running == 1)
    714      1.1   thorpej 			break;
    715      1.1   thorpej 		sleep(1);
    716      1.1   thorpej 	}
    717      1.1   thorpej 	membar_sync();
    718      1.1   thorpej 	ATF_REQUIRE(nlwps_running == 1);
    719      1.1   thorpej 	ATF_REQUIRE(wlwp0->futex_error == 0);
    720      1.1   thorpej 	ATF_REQUIRE(_lwp_wait(wlwp0->lwpid, NULL) == 0);
    721      1.1   thorpej 
    722      1.1   thorpej 	/* Wake up the second LWP. */
    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 			    wlwp1->bitset) == 1);
    726      1.1   thorpej 	sleep(1);
    727      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    728      1.1   thorpej 		membar_sync();
    729      1.1   thorpej 		if (nlwps_running == 0)
    730      1.1   thorpej 			break;
    731      1.1   thorpej 		sleep(1);
    732      1.1   thorpej 	}
    733      1.1   thorpej 	membar_sync();
    734      1.1   thorpej 	ATF_REQUIRE(nlwps_running == 0);
    735      1.1   thorpej 	ATF_REQUIRE(wlwp1->futex_error == 0);
    736      1.1   thorpej 	ATF_REQUIRE(_lwp_wait(wlwp1->lwpid, NULL) == 0);
    737      1.1   thorpej }
    738      1.1   thorpej 
    739      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wait_wake_bitset);
    740      1.1   thorpej ATF_TC_HEAD(futex_wait_wake_bitset, tc)
    741      1.1   thorpej {
    742      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    743      1.1   thorpej 	    "tests futex WAIT_BITSET + WAKE_BITSET operations");
    744      1.1   thorpej }
    745      1.1   thorpej ATF_TC_BODY(futex_wait_wake_bitset, tc)
    746      1.1   thorpej {
    747      1.1   thorpej 	do_futex_wait_wake_bitset_test(FUTEX_PRIVATE_FLAG);
    748      1.1   thorpej }
    749      1.1   thorpej ATF_TC_CLEANUP(futex_wait_wake_bitset, tc)
    750      1.1   thorpej {
    751      1.1   thorpej 	do_cleanup();
    752      1.1   thorpej }
    753      1.1   thorpej 
    754      1.1   thorpej /*****************************************************************************/
    755      1.1   thorpej 
    756      1.1   thorpej static void
    757      1.1   thorpej do_futex_requeue_test(int flags, int op)
    758      1.1   thorpej {
    759      1.1   thorpej 	struct lwp_data *wlwp0 = &lwp_data[WAITER_LWP0];
    760      1.1   thorpej 	struct lwp_data *wlwp1 = &lwp_data[WAITER_LWP1];
    761      1.1   thorpej 	struct lwp_data *wlwp2 = &lwp_data[WAITER_LWP2];
    762      1.1   thorpej 	struct lwp_data *wlwp3 = &lwp_data[WAITER_LWP3];
    763      1.1   thorpej 	const int good_val3 = (op == FUTEX_CMP_REQUEUE) ?   1 : 0;
    764      1.1   thorpej 	const int bad_val3  = (op == FUTEX_CMP_REQUEUE) ? 666 : 0;
    765      1.1   thorpej 	int i, tries;
    766      1.1   thorpej 
    767      1.1   thorpej 	for (i = WAITER_LWP0; i <= WAITER_LWP3; i++) {
    768      1.1   thorpej 		setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
    769      1.1   thorpej 		lwp_data[i].op_flags = flags;
    770      1.1   thorpej 		lwp_data[i].futex_error = -1;
    771      1.1   thorpej 		lwp_data[i].futex_ptr = &futex_word;
    772      1.1   thorpej 		lwp_data[i].block_val = 1;
    773      1.1   thorpej 		lwp_data[i].bitset = 0;
    774      1.1   thorpej 		lwp_data[i].wait_op = FUTEX_WAIT;
    775      1.1   thorpej 	}
    776      1.1   thorpej 
    777      1.1   thorpej 	STORE(&futex_word, 1);
    778      1.1   thorpej 	STORE(&futex_word1, 1);
    779      1.1   thorpej 	membar_sync();
    780      1.1   thorpej 
    781      1.1   thorpej 	ATF_REQUIRE(_lwp_create(&wlwp0->context, 0, &wlwp0->lwpid) == 0);
    782      1.1   thorpej 	ATF_REQUIRE(_lwp_create(&wlwp1->context, 0, &wlwp1->lwpid) == 0);
    783      1.1   thorpej 	ATF_REQUIRE(_lwp_create(&wlwp2->context, 0, &wlwp2->lwpid) == 0);
    784      1.1   thorpej 	ATF_REQUIRE(_lwp_create(&wlwp3->context, 0, &wlwp3->lwpid) == 0);
    785      1.1   thorpej 
    786      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    787      1.1   thorpej 		membar_sync();
    788      1.1   thorpej 		if (nlwps_running == 4)
    789      1.1   thorpej 			break;
    790      1.1   thorpej 		sleep(1);
    791      1.1   thorpej 	}
    792      1.1   thorpej 	membar_sync();
    793      1.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 4, "waiters failed to start");
    794      1.1   thorpej 
    795      1.1   thorpej 	/* Ensure they're blocked. */
    796      1.1   thorpej 	ATF_REQUIRE(wlwp0->futex_error == -1);
    797      1.1   thorpej 	ATF_REQUIRE(wlwp1->futex_error == -1);
    798      1.1   thorpej 	ATF_REQUIRE(wlwp2->futex_error == -1);
    799      1.1   thorpej 	ATF_REQUIRE(wlwp3->futex_error == -1);
    800      1.1   thorpej 
    801      1.1   thorpej 	/* Make sure invalid #wakes and #requeues are rejected. */
    802      1.1   thorpej 	ATF_REQUIRE_ERRNO(EINVAL,
    803      1.1   thorpej 	    __futex(&futex_word, op | flags,
    804      1.1   thorpej 		    -1, NULL, &futex_word1, INT_MAX, bad_val3) == -1);
    805      1.1   thorpej 
    806      1.1   thorpej 	ATF_REQUIRE_ERRNO(EINVAL,
    807      1.1   thorpej 	    __futex(&futex_word, op | flags,
    808      1.1   thorpej 		    0, NULL, &futex_word1, -1, bad_val3) == -1);
    809      1.1   thorpej 
    810      1.1   thorpej 	/*
    811      1.1   thorpej 	 * FUTEX 0: 4 LWPs
    812      1.1   thorpej 	 * FUTEX 1: 0 LWPs
    813      1.1   thorpej 	 */
    814      1.1   thorpej 
    815      1.1   thorpej 	if (op == FUTEX_CMP_REQUEUE) {
    816      1.1   thorpej 		/* This should fail because the futex_word value is 1. */
    817      1.1   thorpej 		ATF_REQUIRE_ERRNO(EAGAIN,
    818      1.1   thorpej 		    __futex(&futex_word, op | flags,
    819      1.1   thorpej 			    0, NULL, &futex_word1, INT_MAX, bad_val3) == -1);
    820      1.1   thorpej 	}
    821      1.1   thorpej 
    822      1.1   thorpej 	/*
    823      1.1   thorpej 	 * FUTEX 0: 4 LWPs
    824      1.1   thorpej 	 * FUTEX 1: 0 LWPs
    825      1.1   thorpej 	 */
    826      1.1   thorpej 
    827  1.5.8.1   thorpej 	/*
    828  1.5.8.1   thorpej 	 * Move all waiters from 0 to 1.
    829  1.5.8.1   thorpej 	 *
    830  1.5.8.1   thorpej 	 * N.B. different return value semantics for FUTEX_REQUEUE
    831  1.5.8.1   thorpej 	 * vs. FUTEX_CMP_REQUEUE.
    832  1.5.8.1   thorpej 	 */
    833  1.5.8.1   thorpej 	if (op == FUTEX_CMP_REQUEUE) {
    834  1.5.8.1   thorpej 		ATF_REQUIRE(__futex(&futex_word, op | flags,
    835  1.5.8.1   thorpej 				    0, NULL, &futex_word1, INT_MAX,
    836  1.5.8.1   thorpej 				    good_val3) == 4);
    837  1.5.8.1   thorpej 	} else {
    838  1.5.8.1   thorpej 		ATF_REQUIRE(__futex(&futex_word, op | flags,
    839  1.5.8.1   thorpej 				    0, NULL, &futex_word1, INT_MAX,
    840  1.5.8.1   thorpej 				    good_val3) == 0);
    841  1.5.8.1   thorpej 	}
    842      1.1   thorpej 
    843      1.1   thorpej 	/*
    844      1.1   thorpej 	 * FUTEX 0: 0 LWPs
    845      1.1   thorpej 	 * FUTEX 1: 4 LWPs
    846      1.1   thorpej 	 */
    847      1.1   thorpej 
    848      1.1   thorpej 	if (op == FUTEX_CMP_REQUEUE) {
    849      1.1   thorpej 		/* This should fail because the futex_word1 value is 1. */
    850      1.1   thorpej 		ATF_REQUIRE_ERRNO(EAGAIN,
    851      1.1   thorpej 		    __futex(&futex_word1, op | flags,
    852      1.1   thorpej 			    1, NULL, &futex_word, 1, bad_val3) == -1);
    853      1.1   thorpej 	}
    854      1.1   thorpej 
    855      1.1   thorpej 	/*
    856      1.1   thorpej 	 * FUTEX 0: 0 LWPs
    857      1.1   thorpej 	 * FUTEX 1: 4 LWPs
    858      1.1   thorpej 	 */
    859      1.1   thorpej 
    860      1.1   thorpej 	/* Wake one waiter on 1, move one waiter to 0. */
    861      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word1, op | flags,
    862      1.1   thorpej 			    1, NULL, &futex_word, 1, good_val3) == 1);
    863      1.1   thorpej 
    864      1.1   thorpej 	/*
    865      1.1   thorpej 	 * FUTEX 0: 1 LWP
    866      1.1   thorpej 	 * FUTEX 1: 2 LWPs
    867      1.1   thorpej 	 */
    868      1.1   thorpej 
    869      1.1   thorpej 	/* Wake all waiters on 0 (should be 1). */
    870      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE | flags,
    871      1.1   thorpej 			    INT_MAX, NULL, NULL, 0, 0) == 1);
    872      1.1   thorpej 
    873      1.1   thorpej 	/* Wake all waiters on 1 (should be 2). */
    874      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word1, FUTEX_WAKE | flags,
    875      1.1   thorpej 			    INT_MAX, NULL, NULL, 0, 0) == 2);
    876      1.1   thorpej 
    877      1.1   thorpej 	/* Trust, but verify. */
    878      1.1   thorpej 	sleep(1);
    879      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
    880      1.1   thorpej 		membar_sync();
    881      1.1   thorpej 		if (nlwps_running == 0)
    882      1.1   thorpej 			break;
    883      1.1   thorpej 		sleep(1);
    884      1.1   thorpej 	}
    885      1.1   thorpej 	membar_sync();
    886      1.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "waiters failed to exit");
    887      1.1   thorpej 
    888      1.1   thorpej 	ATF_REQUIRE(_lwp_wait(wlwp0->lwpid, NULL) == 0);
    889      1.1   thorpej 	ATF_REQUIRE(_lwp_wait(wlwp1->lwpid, NULL) == 0);
    890      1.1   thorpej 	ATF_REQUIRE(_lwp_wait(wlwp2->lwpid, NULL) == 0);
    891      1.1   thorpej 	ATF_REQUIRE(_lwp_wait(wlwp3->lwpid, NULL) == 0);
    892      1.1   thorpej }
    893      1.1   thorpej 
    894      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_requeue);
    895      1.1   thorpej ATF_TC_HEAD(futex_requeue, tc)
    896      1.1   thorpej {
    897      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    898      1.1   thorpej 	    "tests futex REQUEUE operations");
    899      1.1   thorpej }
    900      1.1   thorpej ATF_TC_BODY(futex_requeue, tc)
    901      1.1   thorpej {
    902      1.1   thorpej 	do_futex_requeue_test(FUTEX_PRIVATE_FLAG, FUTEX_REQUEUE);
    903      1.1   thorpej }
    904      1.1   thorpej ATF_TC_CLEANUP(futex_requeue, tc)
    905      1.1   thorpej {
    906      1.1   thorpej 	do_cleanup();
    907      1.1   thorpej }
    908      1.1   thorpej 
    909      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_cmp_requeue);
    910      1.1   thorpej ATF_TC_HEAD(futex_cmp_requeue, tc)
    911      1.1   thorpej {
    912      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
    913      1.1   thorpej 	    "tests futex CMP_REQUEUE operations");
    914      1.1   thorpej }
    915      1.1   thorpej ATF_TC_BODY(futex_cmp_requeue, tc)
    916      1.1   thorpej {
    917      1.1   thorpej 	do_futex_requeue_test(FUTEX_PRIVATE_FLAG, FUTEX_CMP_REQUEUE);
    918      1.1   thorpej }
    919      1.1   thorpej ATF_TC_CLEANUP(futex_cmp_requeue, tc)
    920      1.1   thorpej {
    921      1.1   thorpej 	do_cleanup();
    922      1.1   thorpej }
    923      1.1   thorpej 
    924      1.1   thorpej /*****************************************************************************/
    925      1.1   thorpej 
    926      1.1   thorpej static void
    927      1.1   thorpej do_futex_wake_op_op_test(int flags)
    928      1.1   thorpej {
    929      1.1   thorpej 	int op;
    930      1.1   thorpej 
    931      1.1   thorpej 	futex_word = 0;
    932      1.1   thorpej 	futex_word1 = 0;
    933      1.1   thorpej 
    934      1.1   thorpej 	/*
    935      1.1   thorpej 	 * The op= operations should work even if there are no waiters.
    936      1.1   thorpej 	 */
    937      1.1   thorpej 
    938      1.1   thorpej 	/*
    939      1.1   thorpej 	 * Because these operations use both futex addresses, exercise
    940      1.1   thorpej 	 * rejecting unaligned futex addresses here.
    941      1.1   thorpej 	 */
    942      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_EQ, 0);
    943      1.1   thorpej 	ATF_REQUIRE_ERRNO(EINVAL,
    944      1.1   thorpej 	    __futex((int *)1, FUTEX_WAKE_OP | flags,
    945      1.1   thorpej 		    0, NULL, &futex_word1, 0, op) == -1);
    946      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 0);
    947      1.1   thorpej 
    948      1.1   thorpej 	ATF_REQUIRE_ERRNO(EINVAL,
    949      1.1   thorpej 	    __futex(&futex_word, FUTEX_WAKE_OP | flags,
    950      1.1   thorpej 		    0, NULL, (int *)1, 0, op) == -1);
    951      1.1   thorpej 	ATF_REQUIRE(futex_word == 0);
    952      1.1   thorpej 
    953      1.1   thorpej 	/* Check unmapped uaddr2 handling, too. */
    954      1.1   thorpej 	ATF_REQUIRE_ERRNO(EFAULT,
    955      1.1   thorpej 	    __futex(&futex_word, FUTEX_WAKE_OP | flags,
    956      1.1   thorpej 		    0, NULL, NULL, 0, op) == -1);
    957      1.1   thorpej 	ATF_REQUIRE(futex_word == 0);
    958      1.1   thorpej 
    959      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_EQ, 0);
    960      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
    961      1.1   thorpej 			    0, NULL, &futex_word1, 0, op) == 0);
    962      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 1);
    963      1.1   thorpej 
    964      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_ADD, 1, FUTEX_OP_CMP_EQ, 0);
    965      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
    966      1.1   thorpej 			    0, NULL, &futex_word1, 0, op) == 0);
    967      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
    968      1.1   thorpej 
    969      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_OR, 2, FUTEX_OP_CMP_EQ, 0);
    970      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
    971      1.1   thorpej 			    0, NULL, &futex_word1, 0, op) == 0);
    972      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
    973      1.1   thorpej 
    974      1.1   thorpej 	/* This should fail because of invalid shift value 32. */
    975      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_OR | FUTEX_OP_OPARG_SHIFT, 32,
    976      1.1   thorpej 		      FUTEX_OP_CMP_EQ, 0);
    977      1.1   thorpej 	ATF_REQUIRE_ERRNO(EINVAL,
    978      1.1   thorpej 	    __futex(&futex_word, FUTEX_WAKE_OP | flags,
    979      1.1   thorpej 		    0, NULL, &futex_word1, 0, op) == -1);
    980      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
    981      1.1   thorpej 
    982      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_OR | FUTEX_OP_OPARG_SHIFT, 31,
    983      1.1   thorpej 		      FUTEX_OP_CMP_EQ, 0);
    984      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
    985      1.1   thorpej 			    0, NULL, &futex_word1, 0, op) == 0);
    986      1.1   thorpej 	ATF_REQUIRE(futex_word1 == (int)0x80000002);
    987      1.1   thorpej 
    988      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_ANDN | FUTEX_OP_OPARG_SHIFT, 31,
    989      1.1   thorpej 		      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 	op = FUTEX_OP(FUTEX_OP_XOR, 2, FUTEX_OP_CMP_EQ, 0);
    995      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
    996      1.1   thorpej 			    0, NULL, &futex_word1, 0, op) == 0);
    997      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 0);
    998      1.1   thorpej }
    999      1.1   thorpej 
   1000      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wake_op_op);
   1001      1.1   thorpej ATF_TC_HEAD(futex_wake_op_op, tc)
   1002      1.1   thorpej {
   1003      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   1004      1.1   thorpej 	    "tests futex WAKE_OP OP operations");
   1005      1.1   thorpej }
   1006      1.1   thorpej ATF_TC_BODY(futex_wake_op_op, tc)
   1007      1.1   thorpej {
   1008      1.1   thorpej 	do_futex_wake_op_op_test(FUTEX_PRIVATE_FLAG);
   1009      1.1   thorpej }
   1010      1.1   thorpej ATF_TC_CLEANUP(futex_wake_op_op, tc)
   1011      1.1   thorpej {
   1012      1.1   thorpej 	do_cleanup();
   1013      1.1   thorpej }
   1014      1.1   thorpej 
   1015      1.1   thorpej static void
   1016      1.1   thorpej create_wake_op_test_lwps(int flags)
   1017      1.1   thorpej {
   1018      1.1   thorpej 	int i;
   1019      1.1   thorpej 
   1020      1.1   thorpej 	futex_word1 = 0;
   1021      1.1   thorpej 	membar_sync();
   1022      1.1   thorpej 
   1023      1.1   thorpej 	for (i = WAITER_LWP0; i <= WAITER_LWP5; i++) {
   1024      1.1   thorpej 		setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
   1025      1.1   thorpej 		lwp_data[i].op_flags = flags;
   1026      1.1   thorpej 		lwp_data[i].futex_error = -1;
   1027      1.1   thorpej 		lwp_data[i].futex_ptr = &futex_word1;
   1028      1.1   thorpej 		lwp_data[i].block_val = 0;
   1029      1.1   thorpej 		lwp_data[i].bitset = 0;
   1030      1.1   thorpej 		lwp_data[i].wait_op = FUTEX_WAIT;
   1031      1.1   thorpej 		ATF_REQUIRE(_lwp_create(&lwp_data[i].context, 0,
   1032      1.1   thorpej 					&lwp_data[i].lwpid) == 0);
   1033      1.1   thorpej 	}
   1034      1.1   thorpej 
   1035      1.1   thorpej 	for (i = 0; i < 5; i++) {
   1036      1.1   thorpej 		membar_sync();
   1037      1.1   thorpej 		if (nlwps_running == 6)
   1038      1.1   thorpej 			break;
   1039      1.1   thorpej 		sleep(1);
   1040      1.1   thorpej 	}
   1041      1.1   thorpej 	membar_sync();
   1042      1.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 6, "waiters failed to start");
   1043      1.1   thorpej 
   1044      1.1   thorpej 	/* Ensure they're blocked. */
   1045      1.1   thorpej 	for (i = WAITER_LWP0; i <= WAITER_LWP5; i++) {
   1046      1.1   thorpej 		ATF_REQUIRE(lwp_data[i].futex_error == -1);
   1047      1.1   thorpej 	}
   1048      1.1   thorpej }
   1049      1.1   thorpej 
   1050      1.1   thorpej static void
   1051      1.1   thorpej reap_wake_op_test_lwps(void)
   1052      1.1   thorpej {
   1053      1.1   thorpej 	int i;
   1054      1.1   thorpej 
   1055      1.1   thorpej 	for (i = WAITER_LWP0; i <= WAITER_LWP5; i++) {
   1056      1.1   thorpej 		ATF_REQUIRE(_lwp_wait(lwp_data[i].lwpid, NULL) == 0);
   1057      1.1   thorpej 	}
   1058      1.1   thorpej }
   1059      1.1   thorpej 
   1060      1.1   thorpej static void
   1061      1.1   thorpej do_futex_wake_op_cmp_test(int flags)
   1062      1.1   thorpej {
   1063      1.1   thorpej 	int tries, op;
   1064      1.1   thorpej 
   1065      1.1   thorpej 	futex_word = 0;
   1066      1.1   thorpej 	membar_sync();
   1067      1.1   thorpej 
   1068      1.1   thorpej 	/*
   1069      1.1   thorpej 	 * Verify and negative and positive for each individual
   1070      1.1   thorpej 	 * compare.
   1071      1.1   thorpej 	 */
   1072      1.1   thorpej 
   1073      1.1   thorpej 	create_wake_op_test_lwps(flags);
   1074      1.1   thorpej 
   1075      1.1   thorpej 	/* #LWPs = 6 */
   1076      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 1);
   1077      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1078      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 0);
   1079      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 0);
   1080      1.1   thorpej 
   1081      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_EQ, 0);
   1082      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1083      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 1);
   1084      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 1);
   1085      1.1   thorpej 
   1086      1.1   thorpej 	/* #LWPs = 5 */
   1087      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_NE, 1);
   1088      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1089      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 0);
   1090      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 1);
   1091      1.1   thorpej 
   1092      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_NE, 2);
   1093      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1094      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 1);
   1095      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
   1096      1.1   thorpej 
   1097      1.1   thorpej 	/* #LWPs = 4 */
   1098      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_LT, 2);
   1099      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1100      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 0);
   1101      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
   1102      1.1   thorpej 
   1103      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_LT, 3);
   1104      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1105      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 1);
   1106      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
   1107      1.1   thorpej 
   1108      1.1   thorpej 	/* #LWPs = 3 */
   1109      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_LE, 1);
   1110      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1111      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 0);
   1112      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 1);
   1113      1.1   thorpej 
   1114      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_LE, 1);
   1115      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1116      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 1);
   1117      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 1);
   1118      1.1   thorpej 
   1119      1.1   thorpej 	/* #LWPs = 2 */
   1120      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 3, FUTEX_OP_CMP_GT, 3);
   1121      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1122      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 0);
   1123      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 3);
   1124      1.1   thorpej 
   1125      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_GT, 2);
   1126      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1127      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 1);
   1128      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
   1129      1.1   thorpej 
   1130      1.1   thorpej 	/* #LWPs = 1 */
   1131      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 3, FUTEX_OP_CMP_GE, 4);
   1132      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1133      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 0);
   1134      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 3);
   1135      1.1   thorpej 
   1136      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_GE, 3);
   1137      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1138      1.1   thorpej 			    0, NULL, &futex_word1, 1, op) == 1);
   1139      1.1   thorpej 	ATF_REQUIRE(futex_word1 == 2);
   1140      1.1   thorpej 
   1141      1.1   thorpej 	/* #LWPs = 0 */
   1142      1.1   thorpej 
   1143      1.1   thorpej 	/* Trust, but verify. */
   1144      1.1   thorpej 	sleep(1);
   1145      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
   1146      1.1   thorpej 		membar_sync();
   1147      1.1   thorpej 		if (nlwps_running == 0)
   1148      1.1   thorpej 			break;
   1149      1.1   thorpej 		sleep(1);
   1150      1.1   thorpej 	}
   1151      1.1   thorpej 	membar_sync();
   1152      1.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "waiters failed to exit");
   1153      1.1   thorpej 
   1154      1.1   thorpej 	reap_wake_op_test_lwps();
   1155      1.1   thorpej 
   1156      1.1   thorpej 	/*
   1157      1.1   thorpej 	 * Verify wakes on uaddr work even if the uaddr2 comparison
   1158      1.1   thorpej 	 * fails.
   1159      1.1   thorpej 	 */
   1160      1.1   thorpej 
   1161      1.1   thorpej 	create_wake_op_test_lwps(flags);
   1162      1.1   thorpej 
   1163      1.1   thorpej 	/* #LWPs = 6 */
   1164      1.1   thorpej 	ATF_REQUIRE(futex_word == 0);
   1165      1.1   thorpej 	op = FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 666);
   1166      1.1   thorpej 	ATF_REQUIRE(__futex(&futex_word1, FUTEX_WAKE_OP | flags,
   1167      1.1   thorpej 			    INT_MAX, NULL, &futex_word, 0, op) == 6);
   1168      1.1   thorpej 	ATF_REQUIRE(futex_word == 0);
   1169      1.1   thorpej 
   1170      1.1   thorpej 	/* #LWPs = 0 */
   1171      1.1   thorpej 
   1172      1.1   thorpej 	/* Trust, but verify. */
   1173      1.1   thorpej 	sleep(1);
   1174      1.1   thorpej 	for (tries = 0; tries < 5; tries++) {
   1175      1.1   thorpej 		membar_sync();
   1176      1.1   thorpej 		if (nlwps_running == 0)
   1177      1.1   thorpej 			break;
   1178      1.1   thorpej 		sleep(1);
   1179      1.1   thorpej 	}
   1180      1.1   thorpej 	membar_sync();
   1181      1.1   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "waiters failed to exit");
   1182      1.1   thorpej 
   1183      1.1   thorpej 	reap_wake_op_test_lwps();
   1184      1.1   thorpej }
   1185      1.1   thorpej 
   1186      1.1   thorpej ATF_TC_WITH_CLEANUP(futex_wake_op_cmp);
   1187      1.1   thorpej ATF_TC_HEAD(futex_wake_op_cmp, tc)
   1188      1.1   thorpej {
   1189      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   1190      1.1   thorpej 	    "tests futex WAKE_OP CMP operations");
   1191      1.1   thorpej }
   1192      1.1   thorpej ATF_TC_BODY(futex_wake_op_cmp, tc)
   1193      1.1   thorpej {
   1194      1.1   thorpej 	do_futex_wake_op_cmp_test(FUTEX_PRIVATE_FLAG);
   1195      1.1   thorpej }
   1196      1.1   thorpej ATF_TC_CLEANUP(futex_wake_op_cmp, tc)
   1197      1.1   thorpej {
   1198      1.1   thorpej 	do_cleanup();
   1199      1.1   thorpej }
   1200      1.1   thorpej 
   1201      1.1   thorpej /*****************************************************************************/
   1202      1.1   thorpej 
   1203      1.1   thorpej static void
   1204      1.1   thorpej do_futex_wait_timeout(bool relative, clockid_t clock)
   1205      1.1   thorpej {
   1206      1.1   thorpej 	struct timespec ts;
   1207      1.1   thorpej 	struct timespec deadline;
   1208      1.1   thorpej 	int op = relative ? FUTEX_WAIT : FUTEX_WAIT_BITSET;
   1209      1.1   thorpej 
   1210      1.1   thorpej 	if (clock == CLOCK_REALTIME)
   1211      1.1   thorpej 		op |= FUTEX_CLOCK_REALTIME;
   1212      1.1   thorpej 
   1213      1.1   thorpej 	ATF_REQUIRE(clock_gettime(clock, &deadline) == 0);
   1214      1.1   thorpej 	deadline.tv_sec += 2;
   1215      1.1   thorpej 	if (relative) {
   1216      1.1   thorpej 		ts.tv_sec = 2;
   1217      1.1   thorpej 		ts.tv_nsec = 0;
   1218      1.1   thorpej 	} else {
   1219      1.1   thorpej 		ts = deadline;
   1220      1.1   thorpej 	}
   1221      1.1   thorpej 
   1222      1.1   thorpej 	futex_word = 1;
   1223      1.1   thorpej 	ATF_REQUIRE_ERRNO(ETIMEDOUT,
   1224      1.1   thorpej 	    __futex(&futex_word, op | FUTEX_PRIVATE_FLAG,
   1225      1.1   thorpej 		    1, &ts, NULL, 0, FUTEX_BITSET_MATCH_ANY) == -1);
   1226      1.1   thorpej 
   1227      1.1   thorpej 	/* Can't reliably check CLOCK_REALTIME in the presence of NTP. */
   1228      1.1   thorpej 	if (clock != CLOCK_REALTIME) {
   1229      1.1   thorpej 		ATF_REQUIRE(clock_gettime(clock, &ts) == 0);
   1230      1.1   thorpej 		ATF_REQUIRE(ts.tv_sec >= deadline.tv_sec);
   1231      1.1   thorpej 		ATF_REQUIRE(ts.tv_sec > deadline.tv_sec ||
   1232      1.1   thorpej 			    ts.tv_nsec >= deadline.tv_nsec);
   1233      1.1   thorpej 	}
   1234      1.1   thorpej }
   1235      1.1   thorpej 
   1236      1.1   thorpej ATF_TC(futex_wait_timeout_relative);
   1237      1.1   thorpej ATF_TC_HEAD(futex_wait_timeout_relative, tc)
   1238      1.1   thorpej {
   1239      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   1240      1.1   thorpej 	    "tests futex WAIT with relative timeout");
   1241      1.1   thorpej }
   1242      1.1   thorpej ATF_TC_BODY(futex_wait_timeout_relative, tc)
   1243      1.1   thorpej {
   1244      1.1   thorpej 	do_futex_wait_timeout(true, CLOCK_MONOTONIC);
   1245      1.1   thorpej }
   1246      1.1   thorpej 
   1247      1.1   thorpej ATF_TC(futex_wait_timeout_relative_rt);
   1248      1.1   thorpej ATF_TC_HEAD(futex_wait_timeout_relative_rt, tc)
   1249      1.1   thorpej {
   1250      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   1251      1.1   thorpej 	    "tests futex WAIT with relative timeout (REALTIME)");
   1252      1.1   thorpej }
   1253      1.1   thorpej ATF_TC_BODY(futex_wait_timeout_relative_rt, tc)
   1254      1.1   thorpej {
   1255      1.1   thorpej 	do_futex_wait_timeout(true, CLOCK_REALTIME);
   1256      1.1   thorpej }
   1257      1.1   thorpej 
   1258      1.1   thorpej ATF_TC(futex_wait_timeout_deadline);
   1259      1.1   thorpej ATF_TC_HEAD(futex_wait_timeout_deadline, tc)
   1260      1.1   thorpej {
   1261      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   1262      1.1   thorpej 	    "tests futex WAIT with absolute deadline");
   1263      1.1   thorpej }
   1264      1.1   thorpej ATF_TC_BODY(futex_wait_timeout_deadline, tc)
   1265      1.1   thorpej {
   1266      1.1   thorpej 	do_futex_wait_timeout(false, CLOCK_MONOTONIC);
   1267      1.1   thorpej }
   1268      1.1   thorpej 
   1269      1.1   thorpej ATF_TC(futex_wait_timeout_deadline_rt);
   1270      1.1   thorpej ATF_TC_HEAD(futex_wait_timeout_deadline_rt, tc)
   1271      1.1   thorpej {
   1272      1.1   thorpej 	atf_tc_set_md_var(tc, "descr",
   1273      1.1   thorpej 	    "tests futex WAIT with absolute deadline (REALTIME)");
   1274      1.1   thorpej }
   1275      1.1   thorpej ATF_TC_BODY(futex_wait_timeout_deadline_rt, tc)
   1276      1.1   thorpej {
   1277      1.1   thorpej 	do_futex_wait_timeout(false, CLOCK_REALTIME);
   1278      1.1   thorpej }
   1279      1.1   thorpej 
   1280      1.1   thorpej /*****************************************************************************/
   1281      1.1   thorpej 
   1282      1.3   thorpej static void
   1283      1.3   thorpej sig_noop(int sig __unused)
   1284      1.3   thorpej {
   1285      1.3   thorpej }
   1286      1.3   thorpej 
   1287      1.3   thorpej static void (*old_act)(int) = SIG_DFL;
   1288      1.3   thorpej 
   1289      1.3   thorpej static void
   1290      1.3   thorpej do_futex_wait_evil_unmapped(int map_flags)
   1291      1.3   thorpej {
   1292      1.3   thorpej 	int i;
   1293      1.3   thorpej 
   1294      1.3   thorpej 	create_bs(map_flags);
   1295      1.3   thorpej 
   1296      1.3   thorpej 	old_act = signal(SIGUSR1, sig_noop);
   1297      1.3   thorpej 	ATF_REQUIRE(old_act != SIG_ERR);
   1298      1.3   thorpej 
   1299      1.3   thorpej 	setup_lwp_context(&lwp_data[0], simple_test_waiter_lwp);
   1300      1.3   thorpej 	lwp_data[0].op_flags = 0;
   1301      1.3   thorpej 	lwp_data[0].futex_error = -1;
   1302      1.3   thorpej 	lwp_data[0].futex_ptr = &bs_addr[0];
   1303      1.3   thorpej 	lwp_data[0].block_val = 0;
   1304      1.3   thorpej 	lwp_data[0].bitset = 0;
   1305      1.3   thorpej 	lwp_data[0].wait_op = FUTEX_WAIT;
   1306      1.3   thorpej 	ATF_REQUIRE(_lwp_create(&lwp_data[0].context, 0,
   1307      1.3   thorpej 				&lwp_data[0].lwpid) == 0);
   1308      1.3   thorpej 
   1309      1.3   thorpej 	for (i = 0; i < 5; i++) {
   1310      1.3   thorpej 		membar_sync();
   1311      1.3   thorpej 		if (nlwps_running == 1)
   1312      1.3   thorpej 			break;
   1313      1.3   thorpej 		sleep(1);
   1314      1.3   thorpej 	}
   1315      1.3   thorpej 	membar_sync();
   1316      1.3   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 1, "waiters failed to start");
   1317      1.3   thorpej 
   1318      1.3   thorpej 	/* Ensure it's blocked. */
   1319      1.3   thorpej 	ATF_REQUIRE(lwp_data[0].futex_error == -1);
   1320      1.3   thorpej 
   1321      1.3   thorpej 	/* Rudely unmap the backing store. */
   1322      1.3   thorpej 	cleanup_bs();
   1323      1.3   thorpej 
   1324      1.3   thorpej 	/* Signal the waiter so that it leaves the futex. */
   1325      1.3   thorpej 	ATF_REQUIRE(_lwp_kill(lwp_data[0].threadid, SIGUSR1) == 0);
   1326      1.3   thorpej 
   1327      1.3   thorpej 	/* Yay! No panic! */
   1328      1.3   thorpej 
   1329      1.3   thorpej 	reap_lwp_waiter(&lwp_data[0]);
   1330      1.3   thorpej }
   1331      1.3   thorpej 
   1332      1.3   thorpej ATF_TC_WITH_CLEANUP(futex_wait_evil_unmapped_anon);
   1333      1.3   thorpej ATF_TC_HEAD(futex_wait_evil_unmapped_anon, tc)
   1334      1.3   thorpej {
   1335      1.3   thorpej 	atf_tc_set_md_var(tc, "descr",
   1336      1.3   thorpej 	    "tests futex WAIT while futex is unmapped - anon memory");
   1337      1.3   thorpej }
   1338      1.3   thorpej ATF_TC_BODY(futex_wait_evil_unmapped_anon, tc)
   1339      1.3   thorpej {
   1340      1.3   thorpej 	do_futex_wait_evil_unmapped(MAP_ANON);
   1341      1.3   thorpej }
   1342      1.3   thorpej ATF_TC_CLEANUP(futex_wait_evil_unmapped_anon, tc)
   1343      1.3   thorpej {
   1344      1.3   thorpej 	signal(SIGUSR1, old_act);
   1345      1.3   thorpej 	do_cleanup();
   1346      1.3   thorpej }
   1347      1.3   thorpej 
   1348      1.3   thorpej /*****************************************************************************/
   1349      1.3   thorpej 
   1350      1.4   thorpej static int pri_min;
   1351      1.4   thorpej static int pri_max;
   1352      1.4   thorpej 
   1353      1.4   thorpej static void
   1354      1.4   thorpej lowpri_simple_test_waiter_lwp(void *arg)
   1355      1.4   thorpej {
   1356      1.4   thorpej 	struct lwp_data *d = arg;
   1357      1.4   thorpej 	struct sched_param sp;
   1358      1.4   thorpej 	int policy;
   1359      1.4   thorpej 
   1360      1.4   thorpej 	d->threadid = _lwp_self();
   1361      1.4   thorpej 
   1362      1.4   thorpej 	ATF_REQUIRE(_sched_getparam(getpid(), d->threadid, &policy, &sp) == 0);
   1363      1.4   thorpej 	policy = SCHED_RR;
   1364      1.4   thorpej 	sp.sched_priority = pri_min;
   1365      1.4   thorpej 	ATF_REQUIRE(_sched_setparam(getpid(), d->threadid, policy, &sp) == 0);
   1366      1.4   thorpej 
   1367      1.4   thorpej 	simple_test_waiter_lwp(arg);
   1368      1.4   thorpej }
   1369      1.4   thorpej 
   1370      1.4   thorpej static void
   1371      1.4   thorpej highpri_simple_test_waiter_lwp(void *arg)
   1372      1.4   thorpej {
   1373      1.4   thorpej 	struct lwp_data *d = arg;
   1374      1.4   thorpej 	struct sched_param sp;
   1375      1.4   thorpej 	int policy;
   1376      1.4   thorpej 
   1377      1.4   thorpej 	d->threadid = _lwp_self();
   1378      1.4   thorpej 
   1379      1.4   thorpej 	ATF_REQUIRE(_sched_getparam(getpid(), d->threadid, &policy, &sp) == 0);
   1380      1.4   thorpej 	policy = SCHED_RR;
   1381      1.4   thorpej 	sp.sched_priority = pri_max;
   1382      1.4   thorpej 	ATF_REQUIRE(_sched_setparam(getpid(), d->threadid, policy, &sp) == 0);
   1383      1.4   thorpej 
   1384      1.4   thorpej 	simple_test_waiter_lwp(arg);
   1385      1.4   thorpej }
   1386      1.4   thorpej 
   1387      1.4   thorpej static void
   1388      1.4   thorpej do_test_wake_highest_pri(void)
   1389      1.4   thorpej {
   1390      1.4   thorpej 	lwpid_t waiter;
   1391      1.4   thorpej 	int tries;
   1392      1.4   thorpej 	long pri;
   1393      1.4   thorpej 
   1394      1.4   thorpej 	ATF_REQUIRE((pri = sysconf(_SC_SCHED_PRI_MIN)) != -1);
   1395      1.4   thorpej 	pri_min = (int)pri;
   1396      1.4   thorpej 	ATF_REQUIRE((pri = sysconf(_SC_SCHED_PRI_MAX)) != -1);
   1397      1.4   thorpej 	pri_max = (int)pri;
   1398      1.4   thorpej 
   1399      1.4   thorpej 	futex_word = 0;
   1400      1.4   thorpej 	membar_sync();
   1401      1.4   thorpej 
   1402      1.4   thorpej 	setup_lwp_context(&lwp_data[0], lowpri_simple_test_waiter_lwp);
   1403      1.4   thorpej 	lwp_data[0].op_flags = FUTEX_PRIVATE_FLAG;
   1404      1.4   thorpej 	lwp_data[0].futex_error = -1;
   1405      1.4   thorpej 	lwp_data[0].futex_ptr = &futex_word;
   1406      1.4   thorpej 	lwp_data[0].block_val = 0;
   1407      1.4   thorpej 	lwp_data[0].bitset = 0;
   1408      1.4   thorpej 	lwp_data[0].wait_op = FUTEX_WAIT;
   1409      1.4   thorpej 	ATF_REQUIRE(_lwp_create(&lwp_data[0].context, 0,
   1410      1.4   thorpej 				&lwp_data[0].lwpid) == 0);
   1411      1.4   thorpej 
   1412      1.4   thorpej 	for (tries = 0; tries < 5; tries++) {
   1413      1.4   thorpej 		membar_sync();
   1414      1.4   thorpej 		if (nlwps_running == 1)
   1415      1.4   thorpej 			break;
   1416      1.4   thorpej 		sleep(1);
   1417      1.4   thorpej 	}
   1418      1.4   thorpej 	membar_sync();
   1419      1.4   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 1, "lowpri waiter failed to start");
   1420      1.4   thorpej 
   1421      1.4   thorpej 	/* Ensure it's blocked. */
   1422      1.4   thorpej 	ATF_REQUIRE(lwp_data[0].futex_error == -1);
   1423      1.4   thorpej 
   1424      1.4   thorpej 	setup_lwp_context(&lwp_data[1], highpri_simple_test_waiter_lwp);
   1425      1.4   thorpej 	lwp_data[1].op_flags = FUTEX_PRIVATE_FLAG;
   1426      1.4   thorpej 	lwp_data[1].futex_error = -1;
   1427      1.4   thorpej 	lwp_data[1].futex_ptr = &futex_word;
   1428      1.4   thorpej 	lwp_data[1].block_val = 0;
   1429      1.4   thorpej 	lwp_data[1].bitset = 0;
   1430      1.4   thorpej 	lwp_data[1].wait_op = FUTEX_WAIT;
   1431      1.5   thorpej 	ATF_REQUIRE(_lwp_create(&lwp_data[1].context, 0,
   1432      1.5   thorpej 				&lwp_data[1].lwpid) == 0);
   1433      1.4   thorpej 
   1434      1.4   thorpej 	for (tries = 0; tries < 5; tries++) {
   1435      1.4   thorpej 		membar_sync();
   1436      1.4   thorpej 		if (nlwps_running == 2)
   1437      1.4   thorpej 			break;
   1438      1.4   thorpej 		sleep(1);
   1439      1.4   thorpej 	}
   1440      1.4   thorpej 	membar_sync();
   1441      1.4   thorpej 	ATF_REQUIRE_EQ_MSG(nlwps_running, 2, "highpri waiter failed to start");
   1442      1.4   thorpej 
   1443      1.4   thorpej 	/* Ensure it's blocked. */
   1444      1.4   thorpej 	ATF_REQUIRE(lwp_data[1].futex_error == -1);
   1445      1.4   thorpej 
   1446      1.4   thorpej 	/* Wake the first LWP.  We should get the highpri thread. */
   1447      1.4   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE | FUTEX_PRIVATE_FLAG,
   1448      1.4   thorpej 			    1, NULL, NULL, 0, 0) == 1);
   1449      1.4   thorpej 	sleep(1);
   1450      1.4   thorpej 	for (tries = 0; tries < 5; tries++) {
   1451      1.4   thorpej 		membar_sync();
   1452      1.4   thorpej 		if (nlwps_running == 1)
   1453      1.4   thorpej 			break;
   1454      1.4   thorpej 		sleep(1);
   1455      1.4   thorpej 	}
   1456      1.4   thorpej 	membar_sync();
   1457      1.4   thorpej 	ATF_REQUIRE(nlwps_running == 1);
   1458      1.4   thorpej 	ATF_REQUIRE(_lwp_wait(0, &waiter) == 0);
   1459      1.4   thorpej 	ATF_REQUIRE(waiter == lwp_data[1].threadid);
   1460      1.4   thorpej 
   1461      1.4   thorpej 	/* Wake the second LWP.  We should get the lowpri thread. */
   1462      1.4   thorpej 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE | FUTEX_PRIVATE_FLAG,
   1463      1.4   thorpej 			    1, NULL, NULL, 0, 0) == 1);
   1464      1.4   thorpej 	sleep(1);
   1465      1.4   thorpej 	for (tries = 0; tries < 5; tries++) {
   1466      1.4   thorpej 		membar_sync();
   1467      1.4   thorpej 		if (nlwps_running == 0)
   1468      1.4   thorpej 			break;
   1469      1.4   thorpej 		sleep(1);
   1470      1.4   thorpej 	}
   1471      1.4   thorpej 	membar_sync();
   1472      1.4   thorpej 	ATF_REQUIRE(nlwps_running == 0);
   1473      1.4   thorpej 	ATF_REQUIRE(_lwp_wait(0, &waiter) == 0);
   1474      1.4   thorpej 	ATF_REQUIRE(waiter == lwp_data[0].threadid);
   1475      1.4   thorpej }
   1476      1.4   thorpej 
   1477      1.4   thorpej ATF_TC_WITH_CLEANUP(futex_wake_highest_pri);
   1478      1.4   thorpej ATF_TC_HEAD(futex_wake_highest_pri, tc)
   1479      1.4   thorpej {
   1480      1.4   thorpej 	atf_tc_set_md_var(tc, "descr",
   1481      1.4   thorpej 	    "tests that futex WAKE wakes the highest priority waiter");
   1482      1.4   thorpej 	atf_tc_set_md_var(tc, "require.user", "root");
   1483      1.4   thorpej }
   1484      1.4   thorpej ATF_TC_BODY(futex_wake_highest_pri, tc)
   1485      1.4   thorpej {
   1486      1.4   thorpej 	atf_tc_expect_fail("PR kern/55230");
   1487      1.4   thorpej 	do_test_wake_highest_pri();
   1488      1.4   thorpej }
   1489      1.4   thorpej ATF_TC_CLEANUP(futex_wake_highest_pri, tc)
   1490      1.4   thorpej {
   1491      1.4   thorpej 	do_cleanup();
   1492      1.4   thorpej }
   1493      1.4   thorpej 
   1494      1.4   thorpej /*****************************************************************************/
   1495      1.4   thorpej 
   1496      1.1   thorpej ATF_TP_ADD_TCS(tp)
   1497      1.1   thorpej {
   1498      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_basic_wait_wake_private);
   1499      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_basic_wait_wake_shared);
   1500      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_private);
   1501      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_shared);
   1502      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_private);
   1503      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_shared);
   1504      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_cow_private);
   1505      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_cow_shared);
   1506      1.1   thorpej 
   1507      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_shared_proc);
   1508      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_shared_proc);
   1509      1.1   thorpej 
   1510      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_pointless_bitset);
   1511      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_wake_bitset);
   1512      1.1   thorpej 
   1513      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_timeout_relative);
   1514      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_timeout_relative_rt);
   1515      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_timeout_deadline);
   1516      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_timeout_deadline_rt);
   1517      1.1   thorpej 
   1518      1.3   thorpej 	ATF_TP_ADD_TC(tp, futex_wait_evil_unmapped_anon);
   1519      1.3   thorpej 
   1520      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_requeue);
   1521      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_cmp_requeue);
   1522      1.1   thorpej 
   1523      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wake_op_op);
   1524      1.1   thorpej 	ATF_TP_ADD_TC(tp, futex_wake_op_cmp);
   1525      1.1   thorpej 
   1526      1.4   thorpej 	ATF_TP_ADD_TC(tp, futex_wake_highest_pri);
   1527      1.4   thorpej 
   1528      1.1   thorpej 	return atf_no_error();
   1529      1.1   thorpej }
   1530