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