Home | History | Annotate | Line # | Download | only in sys
t_futex_ops.c revision 1.11
      1 /* $NetBSD: t_futex_ops.c,v 1.11 2025/03/05 00:02:47 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.11 2025/03/05 00:02:47 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_REQUIRE_EQ_MSG(pid, d->child,
    151 	    "pid=%lld d->child=%lld", (long long)pid, (long long)d->child);
    152 	ATF_REQUIRE_MSG(WIFEXITED(status), "status=0x%x", status);
    153 	ATF_REQUIRE_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_REQUIRE_ERRNO(EINVAL,
    984 	    __futex((int *)1, FUTEX_WAKE_OP | flags,
    985 		0, NULL, &futex_word1, 0, op) == -1);
    986 	ATF_REQUIRE_EQ_MSG(futex_word1, 0, "futex_word1=%d", futex_word1);
    987 
    988 	ATF_REQUIRE_ERRNO(EINVAL,
    989 	    __futex(&futex_word, FUTEX_WAKE_OP | flags,
    990 		0, NULL, (int *)1, 0, op) == -1);
    991 	ATF_REQUIRE_EQ_MSG(futex_word, 0, "futex_word=%d", futex_word);
    992 
    993 	/* Check unmapped uaddr2 handling, too. */
    994 	ATF_REQUIRE_ERRNO(EFAULT,
    995 	    __futex(&futex_word, FUTEX_WAKE_OP | flags,
    996 		0, NULL, NULL, 0, op) == -1);
    997 	ATF_REQUIRE_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_REQUIRE_EQ_MSG(n, 0, "n=%d woken", n);
   1003 	ATF_REQUIRE_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_REQUIRE_EQ_MSG(n, 0, "n=%d woken", n);
   1009 	ATF_REQUIRE_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_REQUIRE_EQ_MSG(n, 0, "n=%d woken", n);
   1015 	ATF_REQUIRE_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_REQUIRE_ERRNO(EINVAL,
   1021 	    __futex(&futex_word, FUTEX_WAKE_OP | flags,
   1022 		0, NULL, &futex_word1, 0, op) == -1);
   1023 	ATF_REQUIRE_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_REQUIRE_EQ_MSG(n, 0, "n=%d woken", n);
   1030 	ATF_REQUIRE_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_REQUIRE_EQ_MSG(n, 0, "n=%d woken", n);
   1038 	ATF_REQUIRE_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_REQUIRE_EQ_MSG(n, 0, "n=%d woken", n);
   1044 	ATF_REQUIRE_EQ_MSG(futex_word1, 0, "futex_word1=%d", futex_word1);
   1045 }
   1046 
   1047 ATF_TC_WITH_CLEANUP(futex_wake_op_op);
   1048 ATF_TC_HEAD(futex_wake_op_op, tc)
   1049 {
   1050 	atf_tc_set_md_var(tc, "descr",
   1051 	    "tests futex WAKE_OP OP operations");
   1052 }
   1053 ATF_TC_BODY(futex_wake_op_op, tc)
   1054 {
   1055 	do_futex_wake_op_op_test(FUTEX_PRIVATE_FLAG);
   1056 }
   1057 ATF_TC_CLEANUP(futex_wake_op_op, tc)
   1058 {
   1059 	do_cleanup();
   1060 }
   1061 
   1062 static void
   1063 create_wake_op_test_lwps(int flags)
   1064 {
   1065 	int i;
   1066 
   1067 	futex_word1 = 0;
   1068 	membar_sync();
   1069 
   1070 	for (i = WAITER_LWP0; i <= WAITER_LWP5; i++) {
   1071 		setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
   1072 		lwp_data[i].op_flags = flags;
   1073 		lwp_data[i].futex_error = -1;
   1074 		lwp_data[i].futex_ptr = &futex_word1;
   1075 		lwp_data[i].block_val = 0;
   1076 		lwp_data[i].bitset = 0;
   1077 		lwp_data[i].wait_op = FUTEX_WAIT;
   1078 		RL(_lwp_create(&lwp_data[i].context, 0, &lwp_data[i].lwpid));
   1079 	}
   1080 
   1081 	for (i = 0; i < 5; i++) {
   1082 		membar_sync();
   1083 		if (nlwps_running == 6)
   1084 			break;
   1085 		sleep(1);
   1086 	}
   1087 	membar_sync();
   1088 	ATF_REQUIRE_EQ_MSG(nlwps_running, 6,
   1089 	    "waiters failed to start, nlwps_running=%u", nlwps_running);
   1090 
   1091 	/* Ensure they're blocked. */
   1092 	for (i = WAITER_LWP0; i <= WAITER_LWP5; i++) {
   1093 		ATF_REQUIRE_EQ_MSG(lwp_data[i].futex_error, -1,
   1094 		    "i=%d lwp_data[i].futex_error=%d",
   1095 		    i, lwp_data[i].futex_error);
   1096 	}
   1097 }
   1098 
   1099 static void
   1100 reap_wake_op_test_lwps(void)
   1101 {
   1102 	int i;
   1103 
   1104 	for (i = WAITER_LWP0; i <= WAITER_LWP5; i++) {
   1105 		RL(_lwp_wait(lwp_data[i].lwpid, NULL));
   1106 	}
   1107 }
   1108 
   1109 static void
   1110 do_futex_wake_op_cmp_test(int flags)
   1111 {
   1112 	int tries, op, n;
   1113 
   1114 	futex_word = 0;
   1115 	membar_sync();
   1116 
   1117 	/*
   1118 	 * Verify and negative and positive for each individual
   1119 	 * compare.
   1120 	 */
   1121 
   1122 	create_wake_op_test_lwps(flags);
   1123 
   1124 	/* #LWPs = 6 */
   1125 	op = FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 1);
   1126 	RL(n = __futex(&futex_word, FUTEX_WAKE_OP | flags,
   1127 		0, NULL, &futex_word1, 1, op));
   1128 	ATF_REQUIRE_EQ_MSG(n, 0, "n=%d woken", n);
   1129 	ATF_REQUIRE_EQ_MSG(futex_word1, 0, "futex_word1=%d", futex_word1);
   1130 
   1131 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_EQ, 0);
   1132 	RL(n = __futex(&futex_word, FUTEX_WAKE_OP | flags,
   1133 		0, NULL, &futex_word1, 1, op));
   1134 	ATF_REQUIRE_EQ_MSG(n, 1, "n=%d woken", n);
   1135 	ATF_REQUIRE_EQ_MSG(futex_word1, 1, "futex_word1=%d", futex_word1);
   1136 
   1137 	/* #LWPs = 5 */
   1138 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_NE, 1);
   1139 	RL(n = __futex(&futex_word, FUTEX_WAKE_OP | flags,
   1140 		0, NULL, &futex_word1, 1, op));
   1141 	ATF_REQUIRE_EQ_MSG(n, 0, "n=%d woken", n);
   1142 	ATF_REQUIRE(futex_word1 == 1);
   1143 
   1144 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_NE, 2);
   1145 	RL(n = __futex(&futex_word, FUTEX_WAKE_OP | flags,
   1146 		0, NULL, &futex_word1, 1, op));
   1147 	ATF_REQUIRE_EQ_MSG(n, 1, "n=%d woken", n);
   1148 	ATF_REQUIRE_EQ_MSG(futex_word1, 2, "futex_word1=%d", futex_word1);
   1149 
   1150 	/* #LWPs = 4 */
   1151 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_LT, 2);
   1152 	RL(n = __futex(&futex_word, FUTEX_WAKE_OP | flags,
   1153 		0, NULL, &futex_word1, 1, op));
   1154 	ATF_REQUIRE_EQ_MSG(n, 0, "n=%d woken", n);
   1155 	ATF_REQUIRE_EQ_MSG(futex_word1, 2, "futex_word1=%d", futex_word1);
   1156 
   1157 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_LT, 3);
   1158 	RL(n = __futex(&futex_word, FUTEX_WAKE_OP | flags,
   1159 		0, NULL, &futex_word1, 1, op));
   1160 	ATF_REQUIRE_EQ_MSG(n, 1, "n=%d woken", n);
   1161 	ATF_REQUIRE_EQ_MSG(futex_word1, 2, "futex_word1=%d", futex_word1);
   1162 
   1163 	/* #LWPs = 3 */
   1164 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_LE, 1);
   1165 	RL(n = __futex(&futex_word, FUTEX_WAKE_OP | flags,
   1166 		0, NULL, &futex_word1, 1, op));
   1167 	ATF_REQUIRE_EQ_MSG(n, 0, "n=%d woken", n);
   1168 	ATF_REQUIRE_EQ_MSG(futex_word1, 1, "futex_word1=%d", futex_word1);
   1169 
   1170 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_LE, 1);
   1171 	RL(n = __futex(&futex_word, FUTEX_WAKE_OP | flags,
   1172 		0, NULL, &futex_word1, 1, op));
   1173 	ATF_REQUIRE_EQ_MSG(n, 1, "n=%d woken", n);
   1174 	ATF_REQUIRE_EQ_MSG(futex_word1, 1, "futex_word1=%d", futex_word1);
   1175 
   1176 	/* #LWPs = 2 */
   1177 	op = FUTEX_OP(FUTEX_OP_SET, 3, FUTEX_OP_CMP_GT, 3);
   1178 	RL(n = __futex(&futex_word, FUTEX_WAKE_OP | flags,
   1179 		0, NULL, &futex_word1, 1, op));
   1180 	ATF_REQUIRE_EQ_MSG(n, 0, "n=%d woken", n);
   1181 	ATF_REQUIRE_EQ_MSG(futex_word1, 3, "futex_word1=%d", futex_word1);
   1182 
   1183 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_GT, 2);
   1184 	RL(n = __futex(&futex_word, FUTEX_WAKE_OP | flags,
   1185 		0, NULL, &futex_word1, 1, op));
   1186 	ATF_REQUIRE_EQ_MSG(n, 1, "n=%d woken", n);
   1187 	ATF_REQUIRE_EQ_MSG(futex_word1, 2, "futex_word1=%d", futex_word1);
   1188 
   1189 	/* #LWPs = 1 */
   1190 	op = FUTEX_OP(FUTEX_OP_SET, 3, FUTEX_OP_CMP_GE, 4);
   1191 	RL(n = __futex(&futex_word, FUTEX_WAKE_OP | flags,
   1192 		0, NULL, &futex_word1, 1, op));
   1193 	ATF_REQUIRE_EQ_MSG(n, 0, "n=%d woken", n);
   1194 	ATF_REQUIRE_EQ_MSG(futex_word1, 3, "futex_word1=%d", futex_word1);
   1195 
   1196 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_GE, 3);
   1197 	RL(n = __futex(&futex_word, FUTEX_WAKE_OP | flags,
   1198 		0, NULL, &futex_word1, 1, op));
   1199 	ATF_REQUIRE_EQ_MSG(n, 1, "n=%d woken", n);
   1200 	ATF_REQUIRE_EQ_MSG(futex_word1, 2, "futex_word1=%d", futex_word1);
   1201 
   1202 	/* #LWPs = 0 */
   1203 
   1204 	/* Trust, but verify. */
   1205 	sleep(1);
   1206 	for (tries = 0; tries < 5; tries++) {
   1207 		membar_sync();
   1208 		if (nlwps_running == 0)
   1209 			break;
   1210 		sleep(1);
   1211 	}
   1212 	membar_sync();
   1213 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0,
   1214 	    "waiters failed to exit, nlwps_running=%u", nlwps_running);
   1215 
   1216 	reap_wake_op_test_lwps();
   1217 
   1218 	/*
   1219 	 * Verify wakes on uaddr work even if the uaddr2 comparison
   1220 	 * fails.
   1221 	 */
   1222 
   1223 	create_wake_op_test_lwps(flags);
   1224 
   1225 	/* #LWPs = 6 */
   1226 	ATF_REQUIRE_EQ_MSG(futex_word, 0, "futex_word=%d", futex_word);
   1227 	op = FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 666);
   1228 	RL(n = __futex(&futex_word1, FUTEX_WAKE_OP | flags,
   1229 		INT_MAX, NULL, &futex_word, 0, op));
   1230 	ATF_REQUIRE_EQ_MSG(n, 6, "n=%d woken", n);
   1231 	ATF_REQUIRE_EQ_MSG(futex_word, 0, "futex_word=%d", futex_word);
   1232 
   1233 	/* #LWPs = 0 */
   1234 
   1235 	/* Trust, but verify. */
   1236 	sleep(1);
   1237 	for (tries = 0; tries < 5; tries++) {
   1238 		membar_sync();
   1239 		if (nlwps_running == 0)
   1240 			break;
   1241 		sleep(1);
   1242 	}
   1243 	membar_sync();
   1244 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0,
   1245 	    "waiters failed to exit, nlwps_running=%u", nlwps_running);
   1246 
   1247 	reap_wake_op_test_lwps();
   1248 }
   1249 
   1250 ATF_TC_WITH_CLEANUP(futex_wake_op_cmp);
   1251 ATF_TC_HEAD(futex_wake_op_cmp, tc)
   1252 {
   1253 	atf_tc_set_md_var(tc, "descr",
   1254 	    "tests futex WAKE_OP CMP operations");
   1255 }
   1256 ATF_TC_BODY(futex_wake_op_cmp, tc)
   1257 {
   1258 	do_futex_wake_op_cmp_test(FUTEX_PRIVATE_FLAG);
   1259 }
   1260 ATF_TC_CLEANUP(futex_wake_op_cmp, tc)
   1261 {
   1262 	do_cleanup();
   1263 }
   1264 
   1265 /*****************************************************************************/
   1266 
   1267 
   1268 
   1269 /*****************************************************************************/
   1270 
   1271 static void
   1272 do_futex_wait_timeout(bool relative, clockid_t clock)
   1273 {
   1274 	struct timespec ts;
   1275 	struct timespec deadline;
   1276 	int op = relative ? FUTEX_WAIT : FUTEX_WAIT_BITSET;
   1277 
   1278 	if (clock == CLOCK_REALTIME)
   1279 		op |= FUTEX_CLOCK_REALTIME;
   1280 
   1281 	RL(clock_gettime(clock, &deadline));
   1282 	deadline.tv_sec += 2;
   1283 	if (relative) {
   1284 		ts.tv_sec = 2;
   1285 		ts.tv_nsec = 0;
   1286 	} else {
   1287 		ts = deadline;
   1288 	}
   1289 
   1290 	futex_word = 1;
   1291 	ATF_REQUIRE_ERRNO(ETIMEDOUT,
   1292 	    __futex(&futex_word, op | FUTEX_PRIVATE_FLAG,
   1293 		1, &ts, NULL, 0, FUTEX_BITSET_MATCH_ANY) == -1);
   1294 
   1295 	/* Can't reliably check CLOCK_REALTIME in the presence of NTP. */
   1296 	if (clock != CLOCK_REALTIME) {
   1297 		RL(clock_gettime(clock, &ts));
   1298 		ATF_REQUIRE_MSG(ts.tv_sec >= deadline.tv_sec,
   1299 		    "ts=%lld.%09ldsec deadline=%lld.%09ldsec",
   1300 		    (long long)ts.tv_sec, ts.tv_nsec,
   1301 		    (long long)deadline.tv_sec, deadline.tv_nsec);
   1302 		ATF_REQUIRE_MSG((ts.tv_sec > deadline.tv_sec ||
   1303 			ts.tv_nsec >= deadline.tv_nsec),
   1304 		    "ts=%lld.%09ldsec deadline=%lld.%09ldsec",
   1305 		    (long long)ts.tv_sec, ts.tv_nsec,
   1306 		    (long long)deadline.tv_sec, deadline.tv_nsec);
   1307 	}
   1308 }
   1309 
   1310 ATF_TC(futex_wait_timeout_relative);
   1311 ATF_TC_HEAD(futex_wait_timeout_relative, tc)
   1312 {
   1313 	atf_tc_set_md_var(tc, "descr",
   1314 	    "tests futex WAIT with relative timeout");
   1315 }
   1316 ATF_TC_BODY(futex_wait_timeout_relative, tc)
   1317 {
   1318 	do_futex_wait_timeout(true, CLOCK_MONOTONIC);
   1319 }
   1320 
   1321 ATF_TC(futex_wait_timeout_relative_rt);
   1322 ATF_TC_HEAD(futex_wait_timeout_relative_rt, tc)
   1323 {
   1324 	atf_tc_set_md_var(tc, "descr",
   1325 	    "tests futex WAIT with relative timeout (REALTIME)");
   1326 }
   1327 ATF_TC_BODY(futex_wait_timeout_relative_rt, tc)
   1328 {
   1329 	do_futex_wait_timeout(true, CLOCK_REALTIME);
   1330 }
   1331 
   1332 ATF_TC(futex_wait_timeout_deadline);
   1333 ATF_TC_HEAD(futex_wait_timeout_deadline, tc)
   1334 {
   1335 	atf_tc_set_md_var(tc, "descr",
   1336 	    "tests futex WAIT with absolute deadline");
   1337 }
   1338 ATF_TC_BODY(futex_wait_timeout_deadline, tc)
   1339 {
   1340 	do_futex_wait_timeout(false, CLOCK_MONOTONIC);
   1341 }
   1342 
   1343 ATF_TC(futex_wait_timeout_deadline_rt);
   1344 ATF_TC_HEAD(futex_wait_timeout_deadline_rt, tc)
   1345 {
   1346 	atf_tc_set_md_var(tc, "descr",
   1347 	    "tests futex WAIT with absolute deadline (REALTIME)");
   1348 }
   1349 ATF_TC_BODY(futex_wait_timeout_deadline_rt, tc)
   1350 {
   1351 	do_futex_wait_timeout(false, CLOCK_REALTIME);
   1352 }
   1353 
   1354 /*****************************************************************************/
   1355 
   1356 static void
   1357 sig_noop(int sig __unused)
   1358 {
   1359 }
   1360 
   1361 static void (*old_act)(int) = SIG_DFL;
   1362 
   1363 static void
   1364 do_futex_wait_evil_unmapped(int map_flags)
   1365 {
   1366 	int i;
   1367 
   1368 	create_bs(map_flags);
   1369 
   1370 	REQUIRE_LIBC(signal(SIGUSR1, sig_noop), SIG_ERR);
   1371 
   1372 	setup_lwp_context(&lwp_data[0], simple_test_waiter_lwp);
   1373 	lwp_data[0].op_flags = 0;
   1374 	lwp_data[0].futex_error = -1;
   1375 	lwp_data[0].futex_ptr = &bs_addr[0];
   1376 	lwp_data[0].block_val = 0;
   1377 	lwp_data[0].bitset = 0;
   1378 	lwp_data[0].wait_op = FUTEX_WAIT;
   1379 	RL(_lwp_create(&lwp_data[0].context, 0, &lwp_data[0].lwpid));
   1380 
   1381 	for (i = 0; i < 5; i++) {
   1382 		membar_sync();
   1383 		if (nlwps_running == 1)
   1384 			break;
   1385 		sleep(1);
   1386 	}
   1387 	membar_sync();
   1388 	ATF_REQUIRE_EQ_MSG(nlwps_running, 1,
   1389 	    "waiters failed to start, nlwps_running=%u", nlwps_running);
   1390 
   1391 	/* Ensure it's blocked. */
   1392 	ATF_REQUIRE_EQ_MSG(lwp_data[0].futex_error, -1,
   1393 	    "lwp_data[0].futex_error=%d", lwp_data[0].futex_error);
   1394 
   1395 	/* Rudely unmap the backing store. */
   1396 	cleanup_bs();
   1397 
   1398 	/* Signal the waiter so that it leaves the futex. */
   1399 	RL(_lwp_kill(lwp_data[0].threadid, SIGUSR1));
   1400 
   1401 	/* Yay! No panic! */
   1402 
   1403 	reap_lwp_waiter(&lwp_data[0]);
   1404 }
   1405 
   1406 ATF_TC_WITH_CLEANUP(futex_wait_evil_unmapped_anon);
   1407 ATF_TC_HEAD(futex_wait_evil_unmapped_anon, tc)
   1408 {
   1409 	atf_tc_set_md_var(tc, "descr",
   1410 	    "tests futex WAIT while futex is unmapped - anon memory");
   1411 }
   1412 ATF_TC_BODY(futex_wait_evil_unmapped_anon, tc)
   1413 {
   1414 	do_futex_wait_evil_unmapped(MAP_ANON);
   1415 }
   1416 ATF_TC_CLEANUP(futex_wait_evil_unmapped_anon, tc)
   1417 {
   1418 	signal(SIGUSR1, old_act);
   1419 	do_cleanup();
   1420 }
   1421 
   1422 /*****************************************************************************/
   1423 
   1424 static int pri_min;
   1425 static int pri_max;
   1426 
   1427 static void
   1428 lowpri_simple_test_waiter_lwp(void *arg)
   1429 {
   1430 	struct lwp_data *d = arg;
   1431 	struct sched_param sp;
   1432 	int policy;
   1433 
   1434 	d->threadid = _lwp_self();
   1435 
   1436 	RL(_sched_getparam(getpid(), d->threadid, &policy, &sp));
   1437 	policy = SCHED_RR;
   1438 	sp.sched_priority = pri_min;
   1439 	RL(_sched_setparam(getpid(), d->threadid, policy, &sp));
   1440 
   1441 	simple_test_waiter_lwp(arg);
   1442 }
   1443 
   1444 static void
   1445 highpri_simple_test_waiter_lwp(void *arg)
   1446 {
   1447 	struct lwp_data *d = arg;
   1448 	struct sched_param sp;
   1449 	int policy;
   1450 
   1451 	d->threadid = _lwp_self();
   1452 
   1453 	RL(_sched_getparam(getpid(), d->threadid, &policy, &sp));
   1454 	policy = SCHED_RR;
   1455 	sp.sched_priority = pri_max;
   1456 	RL(_sched_setparam(getpid(), d->threadid, policy, &sp));
   1457 
   1458 	simple_test_waiter_lwp(arg);
   1459 }
   1460 
   1461 static void
   1462 do_test_wake_highest_pri(void)
   1463 {
   1464 	lwpid_t waiter;
   1465 	int tries;
   1466 	long pri;
   1467 	int n;
   1468 
   1469 	RL(pri = sysconf(_SC_SCHED_PRI_MIN));
   1470 	pri_min = (int)pri;
   1471 	RL(pri = sysconf(_SC_SCHED_PRI_MAX));
   1472 	pri_max = (int)pri;
   1473 
   1474 	futex_word = 0;
   1475 	membar_sync();
   1476 
   1477 	setup_lwp_context(&lwp_data[0], lowpri_simple_test_waiter_lwp);
   1478 	lwp_data[0].op_flags = FUTEX_PRIVATE_FLAG;
   1479 	lwp_data[0].futex_error = -1;
   1480 	lwp_data[0].futex_ptr = &futex_word;
   1481 	lwp_data[0].block_val = 0;
   1482 	lwp_data[0].bitset = 0;
   1483 	lwp_data[0].wait_op = FUTEX_WAIT;
   1484 	RL(_lwp_create(&lwp_data[0].context, 0, &lwp_data[0].lwpid));
   1485 
   1486 	for (tries = 0; tries < 5; tries++) {
   1487 		membar_sync();
   1488 		if (nlwps_running == 1)
   1489 			break;
   1490 		sleep(1);
   1491 	}
   1492 	membar_sync();
   1493 	ATF_REQUIRE_EQ_MSG(nlwps_running, 1,
   1494 	    "lowpri waiter failed to start, nlwps_running=%u", nlwps_running);
   1495 
   1496 	/* Ensure it's blocked. */
   1497 	ATF_REQUIRE_EQ_MSG(lwp_data[0].futex_error, -1,
   1498 	    "lwp_data[0].futex_error=%d", lwp_data[0].futex_error);
   1499 
   1500 	setup_lwp_context(&lwp_data[1], highpri_simple_test_waiter_lwp);
   1501 	lwp_data[1].op_flags = FUTEX_PRIVATE_FLAG;
   1502 	lwp_data[1].futex_error = -1;
   1503 	lwp_data[1].futex_ptr = &futex_word;
   1504 	lwp_data[1].block_val = 0;
   1505 	lwp_data[1].bitset = 0;
   1506 	lwp_data[1].wait_op = FUTEX_WAIT;
   1507 	RL(_lwp_create(&lwp_data[1].context, 0, &lwp_data[1].lwpid));
   1508 
   1509 	for (tries = 0; tries < 5; tries++) {
   1510 		membar_sync();
   1511 		if (nlwps_running == 2)
   1512 			break;
   1513 		sleep(1);
   1514 	}
   1515 	membar_sync();
   1516 	ATF_REQUIRE_EQ_MSG(nlwps_running, 2,
   1517 	    "highpri waiter failed to start, nlwps_running=%u", nlwps_running);
   1518 
   1519 	/* Ensure it's blocked. */
   1520 	ATF_REQUIRE_EQ_MSG(lwp_data[1].futex_error, -1,
   1521 	    "lwp_data[1].futex_error=%d", lwp_data[1].futex_error);
   1522 
   1523 	/* Wake the first LWP.  We should get the highpri thread. */
   1524 	RL(n = __futex(&futex_word, FUTEX_WAKE | FUTEX_PRIVATE_FLAG,
   1525 		1, NULL, NULL, 0, 0));
   1526 	ATF_REQUIRE_EQ_MSG(n, 1, "n=%d woken", n);
   1527 	sleep(1);
   1528 	for (tries = 0; tries < 5; tries++) {
   1529 		membar_sync();
   1530 		if (nlwps_running == 1)
   1531 			break;
   1532 		sleep(1);
   1533 	}
   1534 	membar_sync();
   1535 	ATF_REQUIRE_EQ_MSG(nlwps_running, 1, "nlwps_running=%u",
   1536 	    nlwps_running);
   1537 	RL(_lwp_wait(0, &waiter));
   1538 	ATF_REQUIRE_EQ_MSG(waiter, lwp_data[1].threadid,
   1539 	    "waiter=%ld lwp_data[1].threadid=%ld",
   1540 	    (long)waiter, (long)lwp_data[1].threadid);
   1541 
   1542 	/* Wake the second LWP.  We should get the lowpri thread. */
   1543 	RL(n = __futex(&futex_word, FUTEX_WAKE | FUTEX_PRIVATE_FLAG,
   1544 		1, NULL, NULL, 0, 0));
   1545 	ATF_REQUIRE_EQ_MSG(n, 1, "n=%d woken", n);
   1546 	sleep(1);
   1547 	for (tries = 0; tries < 5; tries++) {
   1548 		membar_sync();
   1549 		if (nlwps_running == 0)
   1550 			break;
   1551 		sleep(1);
   1552 	}
   1553 	membar_sync();
   1554 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "nlwps_running=%u",
   1555 	    nlwps_running);
   1556 	RL(_lwp_wait(0, &waiter));
   1557 	ATF_REQUIRE_EQ_MSG(waiter, lwp_data[0].threadid,
   1558 	    "waiter=%ld lwp_data[0].threadid=%ld",
   1559 	    (long)waiter, (long)lwp_data[0].threadid);
   1560 }
   1561 
   1562 ATF_TC_WITH_CLEANUP(futex_wake_highest_pri);
   1563 ATF_TC_HEAD(futex_wake_highest_pri, tc)
   1564 {
   1565 	atf_tc_set_md_var(tc, "descr",
   1566 	    "tests that futex WAKE wakes the highest priority waiter");
   1567 	atf_tc_set_md_var(tc, "require.user", "root");
   1568 }
   1569 ATF_TC_BODY(futex_wake_highest_pri, tc)
   1570 {
   1571 	atf_tc_expect_fail("PR kern/55230");
   1572 	do_test_wake_highest_pri();
   1573 }
   1574 ATF_TC_CLEANUP(futex_wake_highest_pri, tc)
   1575 {
   1576 	do_cleanup();
   1577 }
   1578 
   1579 /*****************************************************************************/
   1580 
   1581 ATF_TP_ADD_TCS(tp)
   1582 {
   1583 	ATF_TP_ADD_TC(tp, futex_basic_wait_wake_private);
   1584 	ATF_TP_ADD_TC(tp, futex_basic_wait_wake_shared);
   1585 	ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_private);
   1586 	ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_shared);
   1587 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_private);
   1588 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_shared);
   1589 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_cow_private);
   1590 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_cow_shared);
   1591 
   1592 	ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_shared_proc);
   1593 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_shared_proc);
   1594 
   1595 	ATF_TP_ADD_TC(tp, futex_wait_pointless_bitset);
   1596 	ATF_TP_ADD_TC(tp, futex_wait_wake_bitset);
   1597 
   1598 	ATF_TP_ADD_TC(tp, futex_wait_timeout_relative);
   1599 	ATF_TP_ADD_TC(tp, futex_wait_timeout_relative_rt);
   1600 	ATF_TP_ADD_TC(tp, futex_wait_timeout_deadline);
   1601 	ATF_TP_ADD_TC(tp, futex_wait_timeout_deadline_rt);
   1602 
   1603 	ATF_TP_ADD_TC(tp, futex_wait_evil_unmapped_anon);
   1604 
   1605 	ATF_TP_ADD_TC(tp, futex_requeue);
   1606 	ATF_TP_ADD_TC(tp, futex_cmp_requeue);
   1607 	ATF_TP_ADD_TC(tp, futex_cmp_requeue_trivial);
   1608 
   1609 	ATF_TP_ADD_TC(tp, futex_wake_op_op);
   1610 	ATF_TP_ADD_TC(tp, futex_wake_op_cmp);
   1611 
   1612 	ATF_TP_ADD_TC(tp, futex_wake_highest_pri);
   1613 
   1614 	return atf_no_error();
   1615 }
   1616