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