Home | History | Annotate | Line # | Download | only in sys
t_futex_ops.c revision 1.6
      1 /* $NetBSD: t_futex_ops.c,v 1.6 2025/01/18 06:22:35 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.6 2025/01/18 06:22:35 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_REQUIRE(__futex(&futex_word, op | flags,
    829 			    0, NULL, &futex_word1, INT_MAX, good_val3) == 0);
    830 
    831 	/*
    832 	 * FUTEX 0: 0 LWPs
    833 	 * FUTEX 1: 4 LWPs
    834 	 */
    835 
    836 	if (op == FUTEX_CMP_REQUEUE) {
    837 		/* This should fail because the futex_word1 value is 1. */
    838 		ATF_REQUIRE_ERRNO(EAGAIN,
    839 		    __futex(&futex_word1, op | flags,
    840 			    1, NULL, &futex_word, 1, bad_val3) == -1);
    841 	}
    842 
    843 	/*
    844 	 * FUTEX 0: 0 LWPs
    845 	 * FUTEX 1: 4 LWPs
    846 	 */
    847 
    848 	/* Wake one waiter on 1, move one waiter to 0. */
    849 	ATF_REQUIRE(__futex(&futex_word1, op | flags,
    850 			    1, NULL, &futex_word, 1, good_val3) == 1);
    851 
    852 	/*
    853 	 * FUTEX 0: 1 LWP
    854 	 * FUTEX 1: 2 LWPs
    855 	 */
    856 
    857 	/* Wake all waiters on 0 (should be 1). */
    858 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE | flags,
    859 			    INT_MAX, NULL, NULL, 0, 0) == 1);
    860 
    861 	/* Wake all waiters on 1 (should be 2). */
    862 	ATF_REQUIRE(__futex(&futex_word1, FUTEX_WAKE | flags,
    863 			    INT_MAX, NULL, NULL, 0, 0) == 2);
    864 
    865 	/* Trust, but verify. */
    866 	sleep(1);
    867 	for (tries = 0; tries < 5; tries++) {
    868 		membar_sync();
    869 		if (nlwps_running == 0)
    870 			break;
    871 		sleep(1);
    872 	}
    873 	membar_sync();
    874 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "waiters failed to exit");
    875 
    876 	ATF_REQUIRE(_lwp_wait(wlwp0->lwpid, NULL) == 0);
    877 	ATF_REQUIRE(_lwp_wait(wlwp1->lwpid, NULL) == 0);
    878 	ATF_REQUIRE(_lwp_wait(wlwp2->lwpid, NULL) == 0);
    879 	ATF_REQUIRE(_lwp_wait(wlwp3->lwpid, NULL) == 0);
    880 }
    881 
    882 ATF_TC_WITH_CLEANUP(futex_requeue);
    883 ATF_TC_HEAD(futex_requeue, tc)
    884 {
    885 	atf_tc_set_md_var(tc, "descr",
    886 	    "tests futex REQUEUE operations");
    887 }
    888 ATF_TC_BODY(futex_requeue, tc)
    889 {
    890 	do_futex_requeue_test(FUTEX_PRIVATE_FLAG, FUTEX_REQUEUE);
    891 }
    892 ATF_TC_CLEANUP(futex_requeue, tc)
    893 {
    894 	do_cleanup();
    895 }
    896 
    897 ATF_TC_WITH_CLEANUP(futex_cmp_requeue);
    898 ATF_TC_HEAD(futex_cmp_requeue, tc)
    899 {
    900 	atf_tc_set_md_var(tc, "descr",
    901 	    "tests futex CMP_REQUEUE operations");
    902 }
    903 ATF_TC_BODY(futex_cmp_requeue, tc)
    904 {
    905 	do_futex_requeue_test(FUTEX_PRIVATE_FLAG, FUTEX_CMP_REQUEUE);
    906 }
    907 ATF_TC_CLEANUP(futex_cmp_requeue, tc)
    908 {
    909 	do_cleanup();
    910 }
    911 
    912 ATF_TC(futex_cmp_requeue_trivial);
    913 ATF_TC_HEAD(futex_cmp_requeue_trivial, tc)
    914 {
    915 	atf_tc_set_md_var(tc, "descr",
    916 	    "tests trivial cases of futex CMP_REQUEUE operations");
    917 }
    918 ATF_TC_BODY(futex_cmp_requeue_trivial, tc)
    919 {
    920 	int nwoken;
    921 
    922 	futex_word = 123;
    923 	futex_word1 = 456;	/* should be ignored */
    924 	atf_tc_expect_fail("PR kern/56828:"
    925 	    " futex calls in Linux emulation sometimes hang");
    926 	ATF_CHECK_ERRNO(EAGAIN, __futex(&futex_word, FUTEX_CMP_REQUEUE,
    927 		/*nwake*/1, NULL, &futex_word1, /*nrequeue*/1, 0) == -1);
    928 	ATF_CHECK_ERRNO(EAGAIN, __futex(&futex_word, FUTEX_CMP_REQUEUE,
    929 		/*nwake*/1, NULL, &futex_word1, /*nrequeue*/1, 122) == -1);
    930 	atf_tc_expect_pass();
    931 	nwoken = __futex(&futex_word, FUTEX_CMP_REQUEUE,
    932 	    /*nwake*/1, NULL, &futex_word1, /*nrequeue*/1, 123);
    933 	ATF_CHECK_MSG(nwoken != -1, "errno=%d (%s)", errno, strerror(errno));
    934 	ATF_CHECK_EQ_MSG(nwoken, 0, "nwoken=%d", nwoken);
    935 	ATF_CHECK_EQ_MSG(futex_word, 123, "futex_word=%d", futex_word);
    936 	ATF_CHECK_EQ_MSG(futex_word1, 456, "futex_word1=%d", futex_word1);
    937 }
    938 
    939 /*****************************************************************************/
    940 
    941 static void
    942 do_futex_wake_op_op_test(int flags)
    943 {
    944 	int op;
    945 
    946 	futex_word = 0;
    947 	futex_word1 = 0;
    948 
    949 	/*
    950 	 * The op= operations should work even if there are no waiters.
    951 	 */
    952 
    953 	/*
    954 	 * Because these operations use both futex addresses, exercise
    955 	 * rejecting unaligned futex addresses here.
    956 	 */
    957 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_EQ, 0);
    958 	ATF_REQUIRE_ERRNO(EINVAL,
    959 	    __futex((int *)1, FUTEX_WAKE_OP | flags,
    960 		    0, NULL, &futex_word1, 0, op) == -1);
    961 	ATF_REQUIRE(futex_word1 == 0);
    962 
    963 	ATF_REQUIRE_ERRNO(EINVAL,
    964 	    __futex(&futex_word, FUTEX_WAKE_OP | flags,
    965 		    0, NULL, (int *)1, 0, op) == -1);
    966 	ATF_REQUIRE(futex_word == 0);
    967 
    968 	/* Check unmapped uaddr2 handling, too. */
    969 	ATF_REQUIRE_ERRNO(EFAULT,
    970 	    __futex(&futex_word, FUTEX_WAKE_OP | flags,
    971 		    0, NULL, NULL, 0, op) == -1);
    972 	ATF_REQUIRE(futex_word == 0);
    973 
    974 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_EQ, 0);
    975 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
    976 			    0, NULL, &futex_word1, 0, op) == 0);
    977 	ATF_REQUIRE(futex_word1 == 1);
    978 
    979 	op = FUTEX_OP(FUTEX_OP_ADD, 1, FUTEX_OP_CMP_EQ, 0);
    980 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
    981 			    0, NULL, &futex_word1, 0, op) == 0);
    982 	ATF_REQUIRE(futex_word1 == 2);
    983 
    984 	op = FUTEX_OP(FUTEX_OP_OR, 2, FUTEX_OP_CMP_EQ, 0);
    985 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
    986 			    0, NULL, &futex_word1, 0, op) == 0);
    987 	ATF_REQUIRE(futex_word1 == 2);
    988 
    989 	/* This should fail because of invalid shift value 32. */
    990 	op = FUTEX_OP(FUTEX_OP_OR | FUTEX_OP_OPARG_SHIFT, 32,
    991 		      FUTEX_OP_CMP_EQ, 0);
    992 	ATF_REQUIRE_ERRNO(EINVAL,
    993 	    __futex(&futex_word, FUTEX_WAKE_OP | flags,
    994 		    0, NULL, &futex_word1, 0, op) == -1);
    995 	ATF_REQUIRE(futex_word1 == 2);
    996 
    997 	op = FUTEX_OP(FUTEX_OP_OR | FUTEX_OP_OPARG_SHIFT, 31,
    998 		      FUTEX_OP_CMP_EQ, 0);
    999 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1000 			    0, NULL, &futex_word1, 0, op) == 0);
   1001 	ATF_REQUIRE(futex_word1 == (int)0x80000002);
   1002 
   1003 	op = FUTEX_OP(FUTEX_OP_ANDN | FUTEX_OP_OPARG_SHIFT, 31,
   1004 		      FUTEX_OP_CMP_EQ, 0);
   1005 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1006 			    0, NULL, &futex_word1, 0, op) == 0);
   1007 	ATF_REQUIRE(futex_word1 == 2);
   1008 
   1009 	op = FUTEX_OP(FUTEX_OP_XOR, 2, FUTEX_OP_CMP_EQ, 0);
   1010 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1011 			    0, NULL, &futex_word1, 0, op) == 0);
   1012 	ATF_REQUIRE(futex_word1 == 0);
   1013 }
   1014 
   1015 ATF_TC_WITH_CLEANUP(futex_wake_op_op);
   1016 ATF_TC_HEAD(futex_wake_op_op, tc)
   1017 {
   1018 	atf_tc_set_md_var(tc, "descr",
   1019 	    "tests futex WAKE_OP OP operations");
   1020 }
   1021 ATF_TC_BODY(futex_wake_op_op, tc)
   1022 {
   1023 	do_futex_wake_op_op_test(FUTEX_PRIVATE_FLAG);
   1024 }
   1025 ATF_TC_CLEANUP(futex_wake_op_op, tc)
   1026 {
   1027 	do_cleanup();
   1028 }
   1029 
   1030 static void
   1031 create_wake_op_test_lwps(int flags)
   1032 {
   1033 	int i;
   1034 
   1035 	futex_word1 = 0;
   1036 	membar_sync();
   1037 
   1038 	for (i = WAITER_LWP0; i <= WAITER_LWP5; i++) {
   1039 		setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
   1040 		lwp_data[i].op_flags = flags;
   1041 		lwp_data[i].futex_error = -1;
   1042 		lwp_data[i].futex_ptr = &futex_word1;
   1043 		lwp_data[i].block_val = 0;
   1044 		lwp_data[i].bitset = 0;
   1045 		lwp_data[i].wait_op = FUTEX_WAIT;
   1046 		ATF_REQUIRE(_lwp_create(&lwp_data[i].context, 0,
   1047 					&lwp_data[i].lwpid) == 0);
   1048 	}
   1049 
   1050 	for (i = 0; i < 5; i++) {
   1051 		membar_sync();
   1052 		if (nlwps_running == 6)
   1053 			break;
   1054 		sleep(1);
   1055 	}
   1056 	membar_sync();
   1057 	ATF_REQUIRE_EQ_MSG(nlwps_running, 6, "waiters failed to start");
   1058 
   1059 	/* Ensure they're blocked. */
   1060 	for (i = WAITER_LWP0; i <= WAITER_LWP5; i++) {
   1061 		ATF_REQUIRE(lwp_data[i].futex_error == -1);
   1062 	}
   1063 }
   1064 
   1065 static void
   1066 reap_wake_op_test_lwps(void)
   1067 {
   1068 	int i;
   1069 
   1070 	for (i = WAITER_LWP0; i <= WAITER_LWP5; i++) {
   1071 		ATF_REQUIRE(_lwp_wait(lwp_data[i].lwpid, NULL) == 0);
   1072 	}
   1073 }
   1074 
   1075 static void
   1076 do_futex_wake_op_cmp_test(int flags)
   1077 {
   1078 	int tries, op;
   1079 
   1080 	futex_word = 0;
   1081 	membar_sync();
   1082 
   1083 	/*
   1084 	 * Verify and negative and positive for each individual
   1085 	 * compare.
   1086 	 */
   1087 
   1088 	create_wake_op_test_lwps(flags);
   1089 
   1090 	/* #LWPs = 6 */
   1091 	op = FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 1);
   1092 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1093 			    0, NULL, &futex_word1, 1, op) == 0);
   1094 	ATF_REQUIRE(futex_word1 == 0);
   1095 
   1096 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_EQ, 0);
   1097 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1098 			    0, NULL, &futex_word1, 1, op) == 1);
   1099 	ATF_REQUIRE(futex_word1 == 1);
   1100 
   1101 	/* #LWPs = 5 */
   1102 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_NE, 1);
   1103 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1104 			    0, NULL, &futex_word1, 1, op) == 0);
   1105 	ATF_REQUIRE(futex_word1 == 1);
   1106 
   1107 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_NE, 2);
   1108 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1109 			    0, NULL, &futex_word1, 1, op) == 1);
   1110 	ATF_REQUIRE(futex_word1 == 2);
   1111 
   1112 	/* #LWPs = 4 */
   1113 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_LT, 2);
   1114 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1115 			    0, NULL, &futex_word1, 1, op) == 0);
   1116 	ATF_REQUIRE(futex_word1 == 2);
   1117 
   1118 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_LT, 3);
   1119 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1120 			    0, NULL, &futex_word1, 1, op) == 1);
   1121 	ATF_REQUIRE(futex_word1 == 2);
   1122 
   1123 	/* #LWPs = 3 */
   1124 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_LE, 1);
   1125 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1126 			    0, NULL, &futex_word1, 1, op) == 0);
   1127 	ATF_REQUIRE(futex_word1 == 1);
   1128 
   1129 	op = FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_LE, 1);
   1130 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1131 			    0, NULL, &futex_word1, 1, op) == 1);
   1132 	ATF_REQUIRE(futex_word1 == 1);
   1133 
   1134 	/* #LWPs = 2 */
   1135 	op = FUTEX_OP(FUTEX_OP_SET, 3, FUTEX_OP_CMP_GT, 3);
   1136 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1137 			    0, NULL, &futex_word1, 1, op) == 0);
   1138 	ATF_REQUIRE(futex_word1 == 3);
   1139 
   1140 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_GT, 2);
   1141 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1142 			    0, NULL, &futex_word1, 1, op) == 1);
   1143 	ATF_REQUIRE(futex_word1 == 2);
   1144 
   1145 	/* #LWPs = 1 */
   1146 	op = FUTEX_OP(FUTEX_OP_SET, 3, FUTEX_OP_CMP_GE, 4);
   1147 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1148 			    0, NULL, &futex_word1, 1, op) == 0);
   1149 	ATF_REQUIRE(futex_word1 == 3);
   1150 
   1151 	op = FUTEX_OP(FUTEX_OP_SET, 2, FUTEX_OP_CMP_GE, 3);
   1152 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE_OP | flags,
   1153 			    0, NULL, &futex_word1, 1, op) == 1);
   1154 	ATF_REQUIRE(futex_word1 == 2);
   1155 
   1156 	/* #LWPs = 0 */
   1157 
   1158 	/* Trust, but verify. */
   1159 	sleep(1);
   1160 	for (tries = 0; tries < 5; tries++) {
   1161 		membar_sync();
   1162 		if (nlwps_running == 0)
   1163 			break;
   1164 		sleep(1);
   1165 	}
   1166 	membar_sync();
   1167 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "waiters failed to exit");
   1168 
   1169 	reap_wake_op_test_lwps();
   1170 
   1171 	/*
   1172 	 * Verify wakes on uaddr work even if the uaddr2 comparison
   1173 	 * fails.
   1174 	 */
   1175 
   1176 	create_wake_op_test_lwps(flags);
   1177 
   1178 	/* #LWPs = 6 */
   1179 	ATF_REQUIRE(futex_word == 0);
   1180 	op = FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 666);
   1181 	ATF_REQUIRE(__futex(&futex_word1, FUTEX_WAKE_OP | flags,
   1182 			    INT_MAX, NULL, &futex_word, 0, op) == 6);
   1183 	ATF_REQUIRE(futex_word == 0);
   1184 
   1185 	/* #LWPs = 0 */
   1186 
   1187 	/* Trust, but verify. */
   1188 	sleep(1);
   1189 	for (tries = 0; tries < 5; tries++) {
   1190 		membar_sync();
   1191 		if (nlwps_running == 0)
   1192 			break;
   1193 		sleep(1);
   1194 	}
   1195 	membar_sync();
   1196 	ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "waiters failed to exit");
   1197 
   1198 	reap_wake_op_test_lwps();
   1199 }
   1200 
   1201 ATF_TC_WITH_CLEANUP(futex_wake_op_cmp);
   1202 ATF_TC_HEAD(futex_wake_op_cmp, tc)
   1203 {
   1204 	atf_tc_set_md_var(tc, "descr",
   1205 	    "tests futex WAKE_OP CMP operations");
   1206 }
   1207 ATF_TC_BODY(futex_wake_op_cmp, tc)
   1208 {
   1209 	do_futex_wake_op_cmp_test(FUTEX_PRIVATE_FLAG);
   1210 }
   1211 ATF_TC_CLEANUP(futex_wake_op_cmp, tc)
   1212 {
   1213 	do_cleanup();
   1214 }
   1215 
   1216 /*****************************************************************************/
   1217 
   1218 static void
   1219 do_futex_wait_timeout(bool relative, clockid_t clock)
   1220 {
   1221 	struct timespec ts;
   1222 	struct timespec deadline;
   1223 	int op = relative ? FUTEX_WAIT : FUTEX_WAIT_BITSET;
   1224 
   1225 	if (clock == CLOCK_REALTIME)
   1226 		op |= FUTEX_CLOCK_REALTIME;
   1227 
   1228 	ATF_REQUIRE(clock_gettime(clock, &deadline) == 0);
   1229 	deadline.tv_sec += 2;
   1230 	if (relative) {
   1231 		ts.tv_sec = 2;
   1232 		ts.tv_nsec = 0;
   1233 	} else {
   1234 		ts = deadline;
   1235 	}
   1236 
   1237 	futex_word = 1;
   1238 	ATF_REQUIRE_ERRNO(ETIMEDOUT,
   1239 	    __futex(&futex_word, op | FUTEX_PRIVATE_FLAG,
   1240 		    1, &ts, NULL, 0, FUTEX_BITSET_MATCH_ANY) == -1);
   1241 
   1242 	/* Can't reliably check CLOCK_REALTIME in the presence of NTP. */
   1243 	if (clock != CLOCK_REALTIME) {
   1244 		ATF_REQUIRE(clock_gettime(clock, &ts) == 0);
   1245 		ATF_REQUIRE(ts.tv_sec >= deadline.tv_sec);
   1246 		ATF_REQUIRE(ts.tv_sec > deadline.tv_sec ||
   1247 			    ts.tv_nsec >= deadline.tv_nsec);
   1248 	}
   1249 }
   1250 
   1251 ATF_TC(futex_wait_timeout_relative);
   1252 ATF_TC_HEAD(futex_wait_timeout_relative, tc)
   1253 {
   1254 	atf_tc_set_md_var(tc, "descr",
   1255 	    "tests futex WAIT with relative timeout");
   1256 }
   1257 ATF_TC_BODY(futex_wait_timeout_relative, tc)
   1258 {
   1259 	do_futex_wait_timeout(true, CLOCK_MONOTONIC);
   1260 }
   1261 
   1262 ATF_TC(futex_wait_timeout_relative_rt);
   1263 ATF_TC_HEAD(futex_wait_timeout_relative_rt, tc)
   1264 {
   1265 	atf_tc_set_md_var(tc, "descr",
   1266 	    "tests futex WAIT with relative timeout (REALTIME)");
   1267 }
   1268 ATF_TC_BODY(futex_wait_timeout_relative_rt, tc)
   1269 {
   1270 	do_futex_wait_timeout(true, CLOCK_REALTIME);
   1271 }
   1272 
   1273 ATF_TC(futex_wait_timeout_deadline);
   1274 ATF_TC_HEAD(futex_wait_timeout_deadline, tc)
   1275 {
   1276 	atf_tc_set_md_var(tc, "descr",
   1277 	    "tests futex WAIT with absolute deadline");
   1278 }
   1279 ATF_TC_BODY(futex_wait_timeout_deadline, tc)
   1280 {
   1281 	do_futex_wait_timeout(false, CLOCK_MONOTONIC);
   1282 }
   1283 
   1284 ATF_TC(futex_wait_timeout_deadline_rt);
   1285 ATF_TC_HEAD(futex_wait_timeout_deadline_rt, tc)
   1286 {
   1287 	atf_tc_set_md_var(tc, "descr",
   1288 	    "tests futex WAIT with absolute deadline (REALTIME)");
   1289 }
   1290 ATF_TC_BODY(futex_wait_timeout_deadline_rt, tc)
   1291 {
   1292 	do_futex_wait_timeout(false, CLOCK_REALTIME);
   1293 }
   1294 
   1295 /*****************************************************************************/
   1296 
   1297 static void
   1298 sig_noop(int sig __unused)
   1299 {
   1300 }
   1301 
   1302 static void (*old_act)(int) = SIG_DFL;
   1303 
   1304 static void
   1305 do_futex_wait_evil_unmapped(int map_flags)
   1306 {
   1307 	int i;
   1308 
   1309 	create_bs(map_flags);
   1310 
   1311 	old_act = signal(SIGUSR1, sig_noop);
   1312 	ATF_REQUIRE(old_act != SIG_ERR);
   1313 
   1314 	setup_lwp_context(&lwp_data[0], simple_test_waiter_lwp);
   1315 	lwp_data[0].op_flags = 0;
   1316 	lwp_data[0].futex_error = -1;
   1317 	lwp_data[0].futex_ptr = &bs_addr[0];
   1318 	lwp_data[0].block_val = 0;
   1319 	lwp_data[0].bitset = 0;
   1320 	lwp_data[0].wait_op = FUTEX_WAIT;
   1321 	ATF_REQUIRE(_lwp_create(&lwp_data[0].context, 0,
   1322 				&lwp_data[0].lwpid) == 0);
   1323 
   1324 	for (i = 0; i < 5; i++) {
   1325 		membar_sync();
   1326 		if (nlwps_running == 1)
   1327 			break;
   1328 		sleep(1);
   1329 	}
   1330 	membar_sync();
   1331 	ATF_REQUIRE_EQ_MSG(nlwps_running, 1, "waiters failed to start");
   1332 
   1333 	/* Ensure it's blocked. */
   1334 	ATF_REQUIRE(lwp_data[0].futex_error == -1);
   1335 
   1336 	/* Rudely unmap the backing store. */
   1337 	cleanup_bs();
   1338 
   1339 	/* Signal the waiter so that it leaves the futex. */
   1340 	ATF_REQUIRE(_lwp_kill(lwp_data[0].threadid, SIGUSR1) == 0);
   1341 
   1342 	/* Yay! No panic! */
   1343 
   1344 	reap_lwp_waiter(&lwp_data[0]);
   1345 }
   1346 
   1347 ATF_TC_WITH_CLEANUP(futex_wait_evil_unmapped_anon);
   1348 ATF_TC_HEAD(futex_wait_evil_unmapped_anon, tc)
   1349 {
   1350 	atf_tc_set_md_var(tc, "descr",
   1351 	    "tests futex WAIT while futex is unmapped - anon memory");
   1352 }
   1353 ATF_TC_BODY(futex_wait_evil_unmapped_anon, tc)
   1354 {
   1355 	do_futex_wait_evil_unmapped(MAP_ANON);
   1356 }
   1357 ATF_TC_CLEANUP(futex_wait_evil_unmapped_anon, tc)
   1358 {
   1359 	signal(SIGUSR1, old_act);
   1360 	do_cleanup();
   1361 }
   1362 
   1363 /*****************************************************************************/
   1364 
   1365 static int pri_min;
   1366 static int pri_max;
   1367 
   1368 static void
   1369 lowpri_simple_test_waiter_lwp(void *arg)
   1370 {
   1371 	struct lwp_data *d = arg;
   1372 	struct sched_param sp;
   1373 	int policy;
   1374 
   1375 	d->threadid = _lwp_self();
   1376 
   1377 	ATF_REQUIRE(_sched_getparam(getpid(), d->threadid, &policy, &sp) == 0);
   1378 	policy = SCHED_RR;
   1379 	sp.sched_priority = pri_min;
   1380 	ATF_REQUIRE(_sched_setparam(getpid(), d->threadid, policy, &sp) == 0);
   1381 
   1382 	simple_test_waiter_lwp(arg);
   1383 }
   1384 
   1385 static void
   1386 highpri_simple_test_waiter_lwp(void *arg)
   1387 {
   1388 	struct lwp_data *d = arg;
   1389 	struct sched_param sp;
   1390 	int policy;
   1391 
   1392 	d->threadid = _lwp_self();
   1393 
   1394 	ATF_REQUIRE(_sched_getparam(getpid(), d->threadid, &policy, &sp) == 0);
   1395 	policy = SCHED_RR;
   1396 	sp.sched_priority = pri_max;
   1397 	ATF_REQUIRE(_sched_setparam(getpid(), d->threadid, policy, &sp) == 0);
   1398 
   1399 	simple_test_waiter_lwp(arg);
   1400 }
   1401 
   1402 static void
   1403 do_test_wake_highest_pri(void)
   1404 {
   1405 	lwpid_t waiter;
   1406 	int tries;
   1407 	long pri;
   1408 
   1409 	ATF_REQUIRE((pri = sysconf(_SC_SCHED_PRI_MIN)) != -1);
   1410 	pri_min = (int)pri;
   1411 	ATF_REQUIRE((pri = sysconf(_SC_SCHED_PRI_MAX)) != -1);
   1412 	pri_max = (int)pri;
   1413 
   1414 	futex_word = 0;
   1415 	membar_sync();
   1416 
   1417 	setup_lwp_context(&lwp_data[0], lowpri_simple_test_waiter_lwp);
   1418 	lwp_data[0].op_flags = FUTEX_PRIVATE_FLAG;
   1419 	lwp_data[0].futex_error = -1;
   1420 	lwp_data[0].futex_ptr = &futex_word;
   1421 	lwp_data[0].block_val = 0;
   1422 	lwp_data[0].bitset = 0;
   1423 	lwp_data[0].wait_op = FUTEX_WAIT;
   1424 	ATF_REQUIRE(_lwp_create(&lwp_data[0].context, 0,
   1425 				&lwp_data[0].lwpid) == 0);
   1426 
   1427 	for (tries = 0; tries < 5; tries++) {
   1428 		membar_sync();
   1429 		if (nlwps_running == 1)
   1430 			break;
   1431 		sleep(1);
   1432 	}
   1433 	membar_sync();
   1434 	ATF_REQUIRE_EQ_MSG(nlwps_running, 1, "lowpri waiter failed to start");
   1435 
   1436 	/* Ensure it's blocked. */
   1437 	ATF_REQUIRE(lwp_data[0].futex_error == -1);
   1438 
   1439 	setup_lwp_context(&lwp_data[1], highpri_simple_test_waiter_lwp);
   1440 	lwp_data[1].op_flags = FUTEX_PRIVATE_FLAG;
   1441 	lwp_data[1].futex_error = -1;
   1442 	lwp_data[1].futex_ptr = &futex_word;
   1443 	lwp_data[1].block_val = 0;
   1444 	lwp_data[1].bitset = 0;
   1445 	lwp_data[1].wait_op = FUTEX_WAIT;
   1446 	ATF_REQUIRE(_lwp_create(&lwp_data[1].context, 0,
   1447 				&lwp_data[1].lwpid) == 0);
   1448 
   1449 	for (tries = 0; tries < 5; tries++) {
   1450 		membar_sync();
   1451 		if (nlwps_running == 2)
   1452 			break;
   1453 		sleep(1);
   1454 	}
   1455 	membar_sync();
   1456 	ATF_REQUIRE_EQ_MSG(nlwps_running, 2, "highpri waiter failed to start");
   1457 
   1458 	/* Ensure it's blocked. */
   1459 	ATF_REQUIRE(lwp_data[1].futex_error == -1);
   1460 
   1461 	/* Wake the first LWP.  We should get the highpri thread. */
   1462 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE | FUTEX_PRIVATE_FLAG,
   1463 			    1, NULL, NULL, 0, 0) == 1);
   1464 	sleep(1);
   1465 	for (tries = 0; tries < 5; tries++) {
   1466 		membar_sync();
   1467 		if (nlwps_running == 1)
   1468 			break;
   1469 		sleep(1);
   1470 	}
   1471 	membar_sync();
   1472 	ATF_REQUIRE(nlwps_running == 1);
   1473 	ATF_REQUIRE(_lwp_wait(0, &waiter) == 0);
   1474 	ATF_REQUIRE(waiter == lwp_data[1].threadid);
   1475 
   1476 	/* Wake the second LWP.  We should get the lowpri thread. */
   1477 	ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE | FUTEX_PRIVATE_FLAG,
   1478 			    1, NULL, NULL, 0, 0) == 1);
   1479 	sleep(1);
   1480 	for (tries = 0; tries < 5; tries++) {
   1481 		membar_sync();
   1482 		if (nlwps_running == 0)
   1483 			break;
   1484 		sleep(1);
   1485 	}
   1486 	membar_sync();
   1487 	ATF_REQUIRE(nlwps_running == 0);
   1488 	ATF_REQUIRE(_lwp_wait(0, &waiter) == 0);
   1489 	ATF_REQUIRE(waiter == lwp_data[0].threadid);
   1490 }
   1491 
   1492 ATF_TC_WITH_CLEANUP(futex_wake_highest_pri);
   1493 ATF_TC_HEAD(futex_wake_highest_pri, tc)
   1494 {
   1495 	atf_tc_set_md_var(tc, "descr",
   1496 	    "tests that futex WAKE wakes the highest priority waiter");
   1497 	atf_tc_set_md_var(tc, "require.user", "root");
   1498 }
   1499 ATF_TC_BODY(futex_wake_highest_pri, tc)
   1500 {
   1501 	atf_tc_expect_fail("PR kern/55230");
   1502 	do_test_wake_highest_pri();
   1503 }
   1504 ATF_TC_CLEANUP(futex_wake_highest_pri, tc)
   1505 {
   1506 	do_cleanup();
   1507 }
   1508 
   1509 /*****************************************************************************/
   1510 
   1511 ATF_TP_ADD_TCS(tp)
   1512 {
   1513 	ATF_TP_ADD_TC(tp, futex_basic_wait_wake_private);
   1514 	ATF_TP_ADD_TC(tp, futex_basic_wait_wake_shared);
   1515 	ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_private);
   1516 	ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_shared);
   1517 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_private);
   1518 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_shared);
   1519 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_cow_private);
   1520 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_cow_shared);
   1521 
   1522 	ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_shared_proc);
   1523 	ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_shared_proc);
   1524 
   1525 	ATF_TP_ADD_TC(tp, futex_wait_pointless_bitset);
   1526 	ATF_TP_ADD_TC(tp, futex_wait_wake_bitset);
   1527 
   1528 	ATF_TP_ADD_TC(tp, futex_wait_timeout_relative);
   1529 	ATF_TP_ADD_TC(tp, futex_wait_timeout_relative_rt);
   1530 	ATF_TP_ADD_TC(tp, futex_wait_timeout_deadline);
   1531 	ATF_TP_ADD_TC(tp, futex_wait_timeout_deadline_rt);
   1532 
   1533 	ATF_TP_ADD_TC(tp, futex_wait_evil_unmapped_anon);
   1534 
   1535 	ATF_TP_ADD_TC(tp, futex_requeue);
   1536 	ATF_TP_ADD_TC(tp, futex_cmp_requeue);
   1537 	ATF_TP_ADD_TC(tp, futex_cmp_requeue_trivial);
   1538 
   1539 	ATF_TP_ADD_TC(tp, futex_wake_op_op);
   1540 	ATF_TP_ADD_TC(tp, futex_wake_op_cmp);
   1541 
   1542 	ATF_TP_ADD_TC(tp, futex_wake_highest_pri);
   1543 
   1544 	return atf_no_error();
   1545 }
   1546