Sun Nov 1 15:22:58 2020 UTC ()
- Re-factor the code that sets up real-time LWPs for various tests.
- Add tests for the RW_HANDOFF operations.


(thorpej)
diff -r1.5 -r1.5.2.1 src/tests/lib/libc/sys/t_futex_ops.c

cvs diff -r1.5 -r1.5.2.1 src/tests/lib/libc/sys/t_futex_ops.c (expand / switch to unified diff)

--- src/tests/lib/libc/sys/t_futex_ops.c 2020/05/06 05:14:27 1.5
+++ src/tests/lib/libc/sys/t_futex_ops.c 2020/11/01 15:22:58 1.5.2.1
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: t_futex_ops.c,v 1.5 2020/05/06 05:14:27 thorpej Exp $ */ 1/* $NetBSD: t_futex_ops.c,v 1.5.2.1 2020/11/01 15:22:58 thorpej Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2019, 2020 The NetBSD Foundation, Inc. 4 * Copyright (c) 2019, 2020 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -19,27 +19,27 @@ @@ -19,27 +19,27 @@
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__COPYRIGHT("@(#) Copyright (c) 2019, 2020\ 30__COPYRIGHT("@(#) Copyright (c) 2019, 2020\
31 The NetBSD Foundation, inc. All rights reserved."); 31 The NetBSD Foundation, inc. All rights reserved.");
32__RCSID("$NetBSD: t_futex_ops.c,v 1.5 2020/05/06 05:14:27 thorpej Exp $"); 32__RCSID("$NetBSD: t_futex_ops.c,v 1.5.2.1 2020/11/01 15:22:58 thorpej Exp $");
33 33
34#include <sys/fcntl.h> 34#include <sys/fcntl.h>
35#include <sys/mman.h> 35#include <sys/mman.h>
36#include <sys/wait.h> 36#include <sys/wait.h>
37#include <atomic.h> 37#include <atomic.h>
38#include <errno.h> 38#include <errno.h>
39#include <lwp.h> 39#include <lwp.h>
40#include <stdlib.h> 40#include <stdlib.h>
41#include <stdio.h> 41#include <stdio.h>
42#include <signal.h> 42#include <signal.h>
43#include <time.h> 43#include <time.h>
44#include <limits.h> 44#include <limits.h>
45#include <sched.h> 45#include <sched.h>
@@ -68,49 +68,64 @@ static volatile unsigned int nlwps_runni @@ -68,49 +68,64 @@ static volatile unsigned int nlwps_runni
68struct lwp_data { 68struct lwp_data {
69 ucontext_t context; 69 ucontext_t context;
70 void (*func)(void *); 70 void (*func)(void *);
71 void *stack_base; 71 void *stack_base;
72 lwpid_t lwpid; 72 lwpid_t lwpid;
73 pid_t child; 73 pid_t child;
74 lwpid_t threadid; 74 lwpid_t threadid;
75 int wait_op; 75 int wait_op;
76 int op_flags; 76 int op_flags;
77 int bitset; 77 int bitset;
78 volatile int *futex_ptr; 78 volatile int *futex_ptr;
79 volatile int *error_ptr; 79 volatile int *error_ptr;
80 int block_val; 80 int block_val;
 81 pri_t rt_prio;
81 82
82 void (*exit_func)(void); 83 void (*exit_func)(void);
83 84
84 int futex_error; 85 int futex_error;
85}; 86};
86 87
87#define WAITER_LWP0 0 88#define WAITER_LWP0 0
88#define WAITER_LWP1 1 89#define WAITER_LWP1 1
89#define WAITER_LWP2 2 90#define WAITER_LWP2 2
90#define WAITER_LWP3 3 91#define WAITER_LWP3 3
91#define WAITER_LWP4 4 92#define WAITER_LWP4 4
92#define WAITER_LWP5 5 93#define WAITER_LWP5 5
93#define NLWPS 6 94#define NLWPS 6
94 95
95struct lwp_data lwp_data[NLWPS]; 96struct lwp_data lwp_data[NLWPS];
96 97
97static const char *bs_path = "t_futex_ops_backing_store"; 98static const char *bs_path = "t_futex_ops_backing_store";
98static int bs_fd = -1; 99static int bs_fd = -1;
99static int *bs_addr = MAP_FAILED; 100static int *bs_addr = MAP_FAILED;
100static void *bs_source_buffer = NULL; 101static void *bs_source_buffer = NULL;
101static void *bs_verify_buffer = NULL; 102static void *bs_verify_buffer = NULL;
102static long bs_pagesize; 103static long bs_pagesize;
103 104
 105static int pri_min;
 106static int pri_max;
 107
 108static void
 109setup_rt_params(void)
 110{
 111 long pri;
 112
 113 ATF_REQUIRE((pri = sysconf(_SC_SCHED_PRI_MIN)) != -1);
 114 pri_min = (int)pri;
 115 ATF_REQUIRE((pri = sysconf(_SC_SCHED_PRI_MAX)) != -1);
 116 pri_max = (int)pri;
 117}
 118
104static void 119static void
105create_lwp_waiter(struct lwp_data *d) 120create_lwp_waiter(struct lwp_data *d)
106{ 121{
107 ATF_REQUIRE(_lwp_create(&d->context, 0, &d->lwpid) == 0); 122 ATF_REQUIRE(_lwp_create(&d->context, 0, &d->lwpid) == 0);
108} 123}
109 124
110static void 125static void
111exit_lwp_waiter(void) 126exit_lwp_waiter(void)
112{ 127{
113 _lwp_exit(); 128 _lwp_exit();
114} 129}
115 130
116static void 131static void
@@ -178,26 +193,43 @@ simple_test_waiter_lwp(void *arg) @@ -178,26 +193,43 @@ simple_test_waiter_lwp(void *arg)
178 membar_sync(); 193 membar_sync();
179 atomic_dec_uint(&nlwps_running); 194 atomic_dec_uint(&nlwps_running);
180 _lwp_exit(); 195 _lwp_exit();
181 } else { 196 } else {
182 d->futex_error = 0; 197 d->futex_error = 0;
183 } 198 }
184 199
185 membar_sync(); 200 membar_sync();
186 atomic_dec_uint(&nlwps_running); 201 atomic_dec_uint(&nlwps_running);
187 202
188 _lwp_exit(); 203 _lwp_exit();
189} 204}
190 205
 206static void
 207rt_simple_test_waiter_lwp(void *arg)
 208{
 209 struct lwp_data *d = arg;
 210 struct sched_param sp;
 211 int policy;
 212
 213 d->threadid = _lwp_self();
 214
 215 ATF_REQUIRE(_sched_getparam(getpid(), d->threadid, &policy, &sp) == 0);
 216 policy = SCHED_RR;
 217 sp.sched_priority = d->rt_prio;
 218 ATF_REQUIRE(_sched_setparam(getpid(), d->threadid, policy, &sp) == 0);
 219
 220 simple_test_waiter_lwp(arg);
 221}
 222
191static bool 223static bool
192verify_zero_bs(void) 224verify_zero_bs(void)
193{ 225{
194 226
195 if (bs_verify_buffer == NULL) { 227 if (bs_verify_buffer == NULL) {
196 bs_verify_buffer = malloc(bs_pagesize); 228 bs_verify_buffer = malloc(bs_pagesize);
197 ATF_REQUIRE(bs_verify_buffer != NULL); 229 ATF_REQUIRE(bs_verify_buffer != NULL);
198 } 230 }
199 231
200 ATF_REQUIRE(pread(bs_fd, bs_verify_buffer, 232 ATF_REQUIRE(pread(bs_fd, bs_verify_buffer,
201 bs_pagesize, 0) == bs_pagesize); 233 bs_pagesize, 0) == bs_pagesize);
202 234
203 return (memcmp(bs_verify_buffer, bs_source_buffer, bs_pagesize) == 0); 235 return (memcmp(bs_verify_buffer, bs_source_buffer, bs_pagesize) == 0);
@@ -816,48 +848,48 @@ do_futex_requeue_test(int flags, int op) @@ -816,48 +848,48 @@ do_futex_requeue_test(int flags, int op)
816 /* This should fail because the futex_word value is 1. */ 848 /* This should fail because the futex_word value is 1. */
817 ATF_REQUIRE_ERRNO(EAGAIN, 849 ATF_REQUIRE_ERRNO(EAGAIN,
818 __futex(&futex_word, op | flags, 850 __futex(&futex_word, op | flags,
819 0, NULL, &futex_word1, INT_MAX, bad_val3) == -1); 851 0, NULL, &futex_word1, INT_MAX, bad_val3) == -1);
820 } 852 }
821 853
822 /* 854 /*
823 * FUTEX 0: 4 LWPs 855 * FUTEX 0: 4 LWPs
824 * FUTEX 1: 0 LWPs 856 * FUTEX 1: 0 LWPs
825 */ 857 */
826 858
827 /* Move all waiters from 0 to 1. */ 859 /* Move all waiters from 0 to 1. */
828 ATF_REQUIRE(__futex(&futex_word, op | flags, 860 ATF_REQUIRE(__futex(&futex_word, op | flags,
829 0, NULL, &futex_word1, INT_MAX, good_val3) == 0); 861 0, NULL, &futex_word1, INT_MAX, good_val3) == 4);
830 862
831 /* 863 /*
832 * FUTEX 0: 0 LWPs 864 * FUTEX 0: 0 LWPs
833 * FUTEX 1: 4 LWPs 865 * FUTEX 1: 4 LWPs
834 */ 866 */
835 867
836 if (op == FUTEX_CMP_REQUEUE) { 868 if (op == FUTEX_CMP_REQUEUE) {
837 /* This should fail because the futex_word1 value is 1. */ 869 /* This should fail because the futex_word1 value is 1. */
838 ATF_REQUIRE_ERRNO(EAGAIN, 870 ATF_REQUIRE_ERRNO(EAGAIN,
839 __futex(&futex_word1, op | flags, 871 __futex(&futex_word1, op | flags,
840 1, NULL, &futex_word, 1, bad_val3) == -1); 872 1, NULL, &futex_word, 1, bad_val3) == -1);
841 } 873 }
842 874
843 /* 875 /*
844 * FUTEX 0: 0 LWPs 876 * FUTEX 0: 0 LWPs
845 * FUTEX 1: 4 LWPs 877 * FUTEX 1: 4 LWPs
846 */ 878 */
847 879
848 /* Wake one waiter on 1, move one waiter to 0. */ 880 /* Wake one waiter on 1, move one waiter to 0. */
849 ATF_REQUIRE(__futex(&futex_word1, op | flags, 881 ATF_REQUIRE(__futex(&futex_word1, op | flags,
850 1, NULL, &futex_word, 1, good_val3) == 1); 882 1, NULL, &futex_word, 1, good_val3) == 2);
851 883
852 /* 884 /*
853 * FUTEX 0: 1 LWP 885 * FUTEX 0: 1 LWP
854 * FUTEX 1: 2 LWPs 886 * FUTEX 1: 2 LWPs
855 */ 887 */
856 888
857 /* Wake all waiters on 0 (should be 1). */ 889 /* Wake all waiters on 0 (should be 1). */
858 ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE | flags, 890 ATF_REQUIRE(__futex(&futex_word, FUTEX_WAKE | flags,
859 INT_MAX, NULL, NULL, 0, 0) == 1); 891 INT_MAX, NULL, NULL, 0, 0) == 1);
860 892
861 /* Wake all waiters on 1 (should be 2). */ 893 /* Wake all waiters on 1 (should be 2). */
862 ATF_REQUIRE(__futex(&futex_word1, FUTEX_WAKE | flags, 894 ATF_REQUIRE(__futex(&futex_word1, FUTEX_WAKE | flags,
863 INT_MAX, NULL, NULL, 0, 0) == 2); 895 INT_MAX, NULL, NULL, 0, 0) == 2);
@@ -1325,101 +1357,62 @@ ATF_TC_HEAD(futex_wait_evil_unmapped_ano @@ -1325,101 +1357,62 @@ ATF_TC_HEAD(futex_wait_evil_unmapped_ano
1325} 1357}
1326ATF_TC_BODY(futex_wait_evil_unmapped_anon, tc) 1358ATF_TC_BODY(futex_wait_evil_unmapped_anon, tc)
1327{ 1359{
1328 do_futex_wait_evil_unmapped(MAP_ANON); 1360 do_futex_wait_evil_unmapped(MAP_ANON);
1329} 1361}
1330ATF_TC_CLEANUP(futex_wait_evil_unmapped_anon, tc) 1362ATF_TC_CLEANUP(futex_wait_evil_unmapped_anon, tc)
1331{ 1363{
1332 signal(SIGUSR1, old_act); 1364 signal(SIGUSR1, old_act);
1333 do_cleanup(); 1365 do_cleanup();
1334} 1366}
1335 1367
1336/*****************************************************************************/ 1368/*****************************************************************************/
1337 1369
1338static int pri_min; 
1339static int pri_max; 
1340 
1341static void 
1342lowpri_simple_test_waiter_lwp(void *arg) 
1343{ 
1344 struct lwp_data *d = arg; 
1345 struct sched_param sp; 
1346 int policy; 
1347 
1348 d->threadid = _lwp_self(); 
1349 
1350 ATF_REQUIRE(_sched_getparam(getpid(), d->threadid, &policy, &sp) == 0); 
1351 policy = SCHED_RR; 
1352 sp.sched_priority = pri_min; 
1353 ATF_REQUIRE(_sched_setparam(getpid(), d->threadid, policy, &sp) == 0); 
1354 
1355 simple_test_waiter_lwp(arg); 
1356} 
1357 
1358static void 
1359highpri_simple_test_waiter_lwp(void *arg) 
1360{ 
1361 struct lwp_data *d = arg; 
1362 struct sched_param sp; 
1363 int policy; 
1364 
1365 d->threadid = _lwp_self(); 
1366 
1367 ATF_REQUIRE(_sched_getparam(getpid(), d->threadid, &policy, &sp) == 0); 
1368 policy = SCHED_RR; 
1369 sp.sched_priority = pri_max; 
1370 ATF_REQUIRE(_sched_setparam(getpid(), d->threadid, policy, &sp) == 0); 
1371 
1372 simple_test_waiter_lwp(arg); 
1373} 
1374 
1375static void 1370static void
1376do_test_wake_highest_pri(void) 1371do_test_wake_highest_pri(void)
1377{ 1372{
1378 lwpid_t waiter; 1373 lwpid_t waiter;
1379 int tries; 1374 int tries;
1380 long pri; 
1381 1375
1382 ATF_REQUIRE((pri = sysconf(_SC_SCHED_PRI_MIN)) != -1); 1376 setup_rt_params();
1383 pri_min = (int)pri; 
1384 ATF_REQUIRE((pri = sysconf(_SC_SCHED_PRI_MAX)) != -1); 
1385 pri_max = (int)pri; 
1386 1377
1387 futex_word = 0; 1378 futex_word = 0;
1388 membar_sync(); 1379 membar_sync();
1389 1380
1390 setup_lwp_context(&lwp_data[0], lowpri_simple_test_waiter_lwp); 1381 setup_lwp_context(&lwp_data[0], rt_simple_test_waiter_lwp);
 1382 lwp_data[0].rt_prio = pri_min;
1391 lwp_data[0].op_flags = FUTEX_PRIVATE_FLAG; 1383 lwp_data[0].op_flags = FUTEX_PRIVATE_FLAG;
1392 lwp_data[0].futex_error = -1; 1384 lwp_data[0].futex_error = -1;
1393 lwp_data[0].futex_ptr = &futex_word; 1385 lwp_data[0].futex_ptr = &futex_word;
1394 lwp_data[0].block_val = 0; 1386 lwp_data[0].block_val = 0;
1395 lwp_data[0].bitset = 0; 1387 lwp_data[0].bitset = 0;
1396 lwp_data[0].wait_op = FUTEX_WAIT; 1388 lwp_data[0].wait_op = FUTEX_WAIT;
1397 ATF_REQUIRE(_lwp_create(&lwp_data[0].context, 0, 1389 ATF_REQUIRE(_lwp_create(&lwp_data[0].context, 0,
1398 &lwp_data[0].lwpid) == 0); 1390 &lwp_data[0].lwpid) == 0);
1399 1391
1400 for (tries = 0; tries < 5; tries++) { 1392 for (tries = 0; tries < 5; tries++) {
1401 membar_sync(); 1393 membar_sync();
1402 if (nlwps_running == 1) 1394 if (nlwps_running == 1)
1403 break; 1395 break;
1404 sleep(1); 1396 sleep(1);
1405 } 1397 }
1406 membar_sync(); 1398 membar_sync();
1407 ATF_REQUIRE_EQ_MSG(nlwps_running, 1, "lowpri waiter failed to start"); 1399 ATF_REQUIRE_EQ_MSG(nlwps_running, 1, "lowpri waiter failed to start");
1408 1400
1409 /* Ensure it's blocked. */ 1401 /* Ensure it's blocked. */
1410 ATF_REQUIRE(lwp_data[0].futex_error == -1); 1402 ATF_REQUIRE(lwp_data[0].futex_error == -1);
1411 1403
1412 setup_lwp_context(&lwp_data[1], highpri_simple_test_waiter_lwp); 1404 setup_lwp_context(&lwp_data[1], rt_simple_test_waiter_lwp);
 1405 lwp_data[1].rt_prio = pri_max;
1413 lwp_data[1].op_flags = FUTEX_PRIVATE_FLAG; 1406 lwp_data[1].op_flags = FUTEX_PRIVATE_FLAG;
1414 lwp_data[1].futex_error = -1; 1407 lwp_data[1].futex_error = -1;
1415 lwp_data[1].futex_ptr = &futex_word; 1408 lwp_data[1].futex_ptr = &futex_word;
1416 lwp_data[1].block_val = 0; 1409 lwp_data[1].block_val = 0;
1417 lwp_data[1].bitset = 0; 1410 lwp_data[1].bitset = 0;
1418 lwp_data[1].wait_op = FUTEX_WAIT; 1411 lwp_data[1].wait_op = FUTEX_WAIT;
1419 ATF_REQUIRE(_lwp_create(&lwp_data[1].context, 0, 1412 ATF_REQUIRE(_lwp_create(&lwp_data[1].context, 0,
1420 &lwp_data[1].lwpid) == 0); 1413 &lwp_data[1].lwpid) == 0);
1421 1414
1422 for (tries = 0; tries < 5; tries++) { 1415 for (tries = 0; tries < 5; tries++) {
1423 membar_sync(); 1416 membar_sync();
1424 if (nlwps_running == 2) 1417 if (nlwps_running == 2)
1425 break; 1418 break;
@@ -1461,36 +1454,857 @@ do_test_wake_highest_pri(void) @@ -1461,36 +1454,857 @@ do_test_wake_highest_pri(void)
1461 ATF_REQUIRE(_lwp_wait(0, &waiter) == 0); 1454 ATF_REQUIRE(_lwp_wait(0, &waiter) == 0);
1462 ATF_REQUIRE(waiter == lwp_data[0].threadid); 1455 ATF_REQUIRE(waiter == lwp_data[0].threadid);
1463} 1456}
1464 1457
1465ATF_TC_WITH_CLEANUP(futex_wake_highest_pri); 1458ATF_TC_WITH_CLEANUP(futex_wake_highest_pri);
1466ATF_TC_HEAD(futex_wake_highest_pri, tc) 1459ATF_TC_HEAD(futex_wake_highest_pri, tc)
1467{ 1460{
1468 atf_tc_set_md_var(tc, "descr", 1461 atf_tc_set_md_var(tc, "descr",
1469 "tests that futex WAKE wakes the highest priority waiter"); 1462 "tests that futex WAKE wakes the highest priority waiter");
1470 atf_tc_set_md_var(tc, "require.user", "root"); 1463 atf_tc_set_md_var(tc, "require.user", "root");
1471} 1464}
1472ATF_TC_BODY(futex_wake_highest_pri, tc) 1465ATF_TC_BODY(futex_wake_highest_pri, tc)
1473{ 1466{
1474 atf_tc_expect_fail("PR kern/55230"); 
1475 do_test_wake_highest_pri(); 1467 do_test_wake_highest_pri();
1476} 1468}
1477ATF_TC_CLEANUP(futex_wake_highest_pri, tc) 1469ATF_TC_CLEANUP(futex_wake_highest_pri, tc)
1478{ 1470{
1479 do_cleanup(); 1471 do_cleanup();
1480} 1472}
1481 1473
1482/*****************************************************************************/ 1474/*****************************************************************************/
1483 1475
 1476static void
 1477do_test_rw_handoff_read(void)
 1478{
 1479 int i, tries;
 1480 int rv;
 1481
 1482 futex_word = FUTEX_WAITERS;
 1483 membar_sync();
 1484
 1485 for (i = 0; i < 3; i++) {
 1486 setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
 1487 lwp_data[i].op_flags = FUTEX_PRIVATE_FLAG;
 1488 lwp_data[i].futex_error = -1;
 1489 lwp_data[i].futex_ptr = &futex_word;
 1490 lwp_data[i].block_val = futex_word;
 1491 lwp_data[i].bitset = FUTEX_RW_READER;
 1492 lwp_data[i].wait_op = FUTEX_NETBSD_RW_WAIT;
 1493 ATF_REQUIRE(_lwp_create(&lwp_data[i].context, 0,
 1494 &lwp_data[i].lwpid) == 0);
 1495 }
 1496
 1497 for (tries = 0; tries < 5; tries++) {
 1498 membar_sync();
 1499 if (nlwps_running == 3)
 1500 break;
 1501 sleep(1);
 1502 }
 1503 membar_sync();
 1504
 1505 ATF_REQUIRE_EQ_MSG(nlwps_running, 3, "read-waiters failed to start");
 1506
 1507 /* Ensure they're all blocked. */
 1508 ATF_REQUIRE(lwp_data[0].futex_error == -1);
 1509 ATF_REQUIRE(lwp_data[1].futex_error == -1);
 1510 ATF_REQUIRE(lwp_data[2].futex_error == -1);
 1511
 1512 /* Ensure a regular wake errors out. */
 1513 rv = __futex(&futex_word,
 1514 FUTEX_WAKE | FUTEX_PRIVATE_FLAG, INT_MAX, NULL,
 1515 NULL, 0, 0);
 1516 ATF_REQUIRE(rv == -1 && errno == EINVAL);
 1517
 1518 /*
 1519 * Issue a hand-off. It should wake all 3 readers and update
 1520 * the futex word.
 1521 */
 1522 ATF_REQUIRE(__futex(&futex_word,
 1523 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 1524 FUTEX_WAITERS, NULL, NULL, 0, 0) == 3);
 1525 ATF_REQUIRE(futex_word == 3);
 1526
 1527 for (tries = 0; tries < 5; tries++) {
 1528 membar_sync();
 1529 if (nlwps_running == 0)
 1530 break;
 1531 sleep(1);
 1532 }
 1533 membar_sync();
 1534 ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "read-waiters failed to exit");
 1535
 1536 /* Ensure they all exited error-free. */
 1537 ATF_REQUIRE(lwp_data[0].futex_error == 0);
 1538 reap_lwp_waiter(&lwp_data[0]);
 1539
 1540 ATF_REQUIRE(lwp_data[1].futex_error == 0);
 1541 reap_lwp_waiter(&lwp_data[1]);
 1542
 1543 ATF_REQUIRE(lwp_data[2].futex_error == 0);
 1544 reap_lwp_waiter(&lwp_data[2]);
 1545}
 1546
 1547ATF_TC_WITH_CLEANUP(futex_rw_handoff_read);
 1548ATF_TC_HEAD(futex_rw_handoff_read, tc)
 1549{
 1550 atf_tc_set_md_var(tc, "descr",
 1551 "tests rwlock direct hand-off to readers");
 1552}
 1553ATF_TC_BODY(futex_rw_handoff_read, tc)
 1554{
 1555 atf_tc_skip("futex_rw_handoff is currently broken");
 1556 do_test_rw_handoff_read();
 1557}
 1558ATF_TC_CLEANUP(futex_rw_handoff_read, tc)
 1559{
 1560 do_cleanup();
 1561}
 1562
 1563/*****************************************************************************/
 1564
 1565static void
 1566do_test_rw_handoff_write(void)
 1567{
 1568 unsigned int i, tries;
 1569 lwpid_t lid;
 1570
 1571 /*
 1572 * The kernel should not care about the WRITE_WANTED bit, and
 1573 * should use the contents of the sleepqs as the truth.
 1574 */
 1575 futex_word = FUTEX_WAITERS;
 1576 membar_sync();
 1577
 1578 for (i = 0; i < 3; i++) {
 1579 setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
 1580 lwp_data[i].op_flags = FUTEX_PRIVATE_FLAG;
 1581 lwp_data[i].futex_error = -1;
 1582 lwp_data[i].futex_ptr = &futex_word;
 1583 lwp_data[i].block_val = futex_word;
 1584 lwp_data[i].bitset = FUTEX_RW_WRITER;
 1585 lwp_data[i].wait_op = FUTEX_NETBSD_RW_WAIT;
 1586 ATF_REQUIRE(_lwp_create(&lwp_data[i].context, 0,
 1587 &lwp_data[i].lwpid) == 0);
 1588
 1589 /*
 1590 * Wait for each one to start in-turn, because we want
 1591 * to know the order in which the LWPs block on the futex.
 1592 */
 1593 for (tries = 0; tries < 5; tries++) {
 1594 membar_sync();
 1595 if (nlwps_running == i + 1)
 1596 break;
 1597 sleep(1);
 1598 }
 1599 membar_sync();
 1600 }
 1601
 1602 ATF_REQUIRE_EQ_MSG(nlwps_running, 3, "write-waiters failed to start");
 1603
 1604 /* Ensure they're all blocked. */
 1605 ATF_REQUIRE(lwp_data[0].futex_error == -1);
 1606 ATF_REQUIRE(lwp_data[1].futex_error == -1);
 1607 ATF_REQUIRE(lwp_data[2].futex_error == -1);
 1608
 1609 /*
 1610 * Issue a hand-off for each waiter. This should awaken one
 1611 * at a time and update the futex word.
 1612 */
 1613 ATF_REQUIRE(__futex(&futex_word,
 1614 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 1615 FUTEX_WAITERS, NULL, NULL, 0, 0) == 1);
 1616 ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_LOCKED);
 1617 ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_WANTED);
 1618 ATF_REQUIRE(futex_word & FUTEX_WAITERS);
 1619 lid = futex_word & FUTEX_TID_MASK;
 1620 ATF_REQUIRE(lid == lwp_data[0].lwpid);
 1621
 1622 ATF_REQUIRE(__futex(&futex_word,
 1623 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 1624 futex_word, NULL, NULL, 0, 0) == 1);
 1625 ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_LOCKED);
 1626 ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_WANTED);
 1627 ATF_REQUIRE(futex_word & FUTEX_WAITERS);
 1628 lid = futex_word & FUTEX_TID_MASK;
 1629 ATF_REQUIRE(lid == lwp_data[1].lwpid);
 1630
 1631 ATF_REQUIRE(__futex(&futex_word,
 1632 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 1633 futex_word, NULL, NULL, 0, 0) == 1);
 1634 ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_LOCKED);
 1635 ATF_REQUIRE((futex_word & FUTEX_RW_WRITE_WANTED) == 0);
 1636 ATF_REQUIRE((futex_word & FUTEX_WAITERS) == 0);
 1637 lid = futex_word & FUTEX_TID_MASK;
 1638 ATF_REQUIRE(lid == lwp_data[2].lwpid);
 1639
 1640 /*
 1641 * Issue one final hand-off; it should result in a fully
 1642 * released lock word.
 1643 */
 1644 ATF_REQUIRE(__futex(&futex_word,
 1645 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 1646 futex_word, NULL, NULL, 0, 0) == 0);
 1647 ATF_REQUIRE(futex_word == 0);
 1648
 1649 for (tries = 0; tries < 5; tries++) {
 1650 membar_sync();
 1651 if (nlwps_running == 0)
 1652 break;
 1653 sleep(1);
 1654 }
 1655 membar_sync();
 1656 ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "read-waiters failed to exit");
 1657
 1658 /* Ensure they all exited error-free. */
 1659 ATF_REQUIRE(lwp_data[0].futex_error == 0);
 1660 reap_lwp_waiter(&lwp_data[0]);
 1661
 1662 ATF_REQUIRE(lwp_data[1].futex_error == 0);
 1663 reap_lwp_waiter(&lwp_data[1]);
 1664
 1665 ATF_REQUIRE(lwp_data[2].futex_error == 0);
 1666 reap_lwp_waiter(&lwp_data[2]);
 1667}
 1668
 1669ATF_TC_WITH_CLEANUP(futex_rw_handoff_write);
 1670ATF_TC_HEAD(futex_rw_handoff_write, tc)
 1671{
 1672 atf_tc_set_md_var(tc, "descr",
 1673 "tests rwlock direct hand-off to writers");
 1674}
 1675ATF_TC_BODY(futex_rw_handoff_write, tc)
 1676{
 1677 atf_tc_skip("futex_rw_handoff is currently broken");
 1678 do_test_rw_handoff_write();
 1679}
 1680ATF_TC_CLEANUP(futex_rw_handoff_write, tc)
 1681{
 1682 do_cleanup();
 1683}
 1684
 1685/*****************************************************************************/
 1686
 1687static void
 1688do_test_rw_handoff_write_preferred(void)
 1689{
 1690 unsigned int i, tries;
 1691 lwpid_t lid;
 1692
 1693 /*
 1694 * The kernel should not care about the WRITE_WANTED bit, and
 1695 * should use the contents of the sleepqs as the truth.
 1696 */
 1697 futex_word = FUTEX_WAITERS;
 1698 membar_sync();
 1699
 1700 for (i = 0; i < 2; i++) {
 1701 setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
 1702 lwp_data[i].op_flags = FUTEX_PRIVATE_FLAG;
 1703 lwp_data[i].futex_error = -1;
 1704 lwp_data[i].futex_ptr = &futex_word;
 1705 lwp_data[i].block_val = futex_word;
 1706 lwp_data[i].bitset = FUTEX_RW_READER;
 1707 lwp_data[i].wait_op = FUTEX_NETBSD_RW_WAIT;
 1708 ATF_REQUIRE(_lwp_create(&lwp_data[i].context, 0,
 1709 &lwp_data[i].lwpid) == 0);
 1710
 1711 /*
 1712 * Wait for each one to start in-turn, because we want
 1713 * to know the order in which the LWPs block on the futex.
 1714 */
 1715 for (tries = 0; tries < 5; tries++) {
 1716 membar_sync();
 1717 if (nlwps_running == i + 1)
 1718 break;
 1719 sleep(1);
 1720 }
 1721 membar_sync();
 1722 }
 1723
 1724 ATF_REQUIRE_EQ_MSG(nlwps_running, 2, "read-waiters failed to start");
 1725
 1726 setup_lwp_context(&lwp_data[2], simple_test_waiter_lwp);
 1727 lwp_data[2].op_flags = FUTEX_PRIVATE_FLAG;
 1728 lwp_data[2].futex_error = -1;
 1729 lwp_data[2].futex_ptr = &futex_word;
 1730 lwp_data[2].block_val = futex_word;
 1731 lwp_data[2].bitset = FUTEX_RW_WRITER;
 1732 lwp_data[2].wait_op = FUTEX_NETBSD_RW_WAIT;
 1733 ATF_REQUIRE(_lwp_create(&lwp_data[2].context, 0,
 1734 &lwp_data[2].lwpid) == 0);
 1735
 1736 for (tries = 0; tries < 5; tries++) {
 1737 membar_sync();
 1738 if (nlwps_running == 3)
 1739 break;
 1740 sleep(1);
 1741 }
 1742 membar_sync();
 1743
 1744 ATF_REQUIRE_EQ_MSG(nlwps_running, 3, "write-waiter failed to start");
 1745
 1746 /* Ensure they're all blocked. */
 1747 ATF_REQUIRE(lwp_data[0].futex_error == -1);
 1748 ATF_REQUIRE(lwp_data[1].futex_error == -1);
 1749 ATF_REQUIRE(lwp_data[2].futex_error == -1);
 1750
 1751 /*
 1752 * Issue a hand-off. It should select the writer despite
 1753 * the fact that it is the most recent waiter.
 1754 */
 1755 ATF_REQUIRE(__futex(&futex_word,
 1756 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 1757 FUTEX_WAITERS, NULL, NULL, 0, 0) == 1);
 1758 ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_LOCKED);
 1759 ATF_REQUIRE((futex_word & FUTEX_RW_WRITE_WANTED) == 0);
 1760 ATF_REQUIRE(futex_word & FUTEX_WAITERS);
 1761 lid = futex_word & FUTEX_TID_MASK;
 1762 ATF_REQUIRE(lid == lwp_data[2].lwpid);
 1763
 1764 /*
 1765 * Issue another hand-off. It should awaken both waiting
 1766 * readers.
 1767 */
 1768 ATF_REQUIRE(__futex(&futex_word,
 1769 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 1770 futex_word, NULL, NULL, 0, 0) == 2);
 1771 ATF_REQUIRE(futex_word == 2);
 1772
 1773 /*
 1774 * Issue one final hand-off; it should result in a fully
 1775 * released lock word. Note that we don't have any
 1776 * outstaning waiters waiting, and therefore there will
 1777 * not be a kernel futex; this exercises a specific code
 1778 * path in the kernel designed to handle this.
 1779 */
 1780 ATF_REQUIRE(__futex(&futex_word,
 1781 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 1782 futex_word, NULL, NULL, 0, 0) == 0);
 1783 ATF_REQUIRE(futex_word == 0);
 1784
 1785 for (tries = 0; tries < 5; tries++) {
 1786 membar_sync();
 1787 if (nlwps_running == 0)
 1788 break;
 1789 sleep(1);
 1790 }
 1791 membar_sync();
 1792 ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "read-waiters failed to exit");
 1793
 1794 /* Ensure they all exited error-free. */
 1795 ATF_REQUIRE(lwp_data[0].futex_error == 0);
 1796 reap_lwp_waiter(&lwp_data[0]);
 1797
 1798 ATF_REQUIRE(lwp_data[1].futex_error == 0);
 1799 reap_lwp_waiter(&lwp_data[1]);
 1800
 1801 ATF_REQUIRE(lwp_data[2].futex_error == 0);
 1802 reap_lwp_waiter(&lwp_data[2]);
 1803}
 1804
 1805ATF_TC_WITH_CLEANUP(futex_rw_handoff_write_preferred);
 1806ATF_TC_HEAD(futex_rw_handoff_write_preferred, tc)
 1807{
 1808 atf_tc_set_md_var(tc, "descr",
 1809 "tests that rwlock direct hand-off prefers writers");
 1810}
 1811ATF_TC_BODY(futex_rw_handoff_write_preferred, tc)
 1812{
 1813 atf_tc_skip("futex_rw_handoff is currently broken");
 1814 do_test_rw_handoff_write_preferred();
 1815}
 1816ATF_TC_CLEANUP(futex_rw_handoff_write_preferred, tc)
 1817{
 1818 do_cleanup();
 1819}
 1820
 1821/*****************************************************************************/
 1822
 1823static void
 1824do_test_rw_handoff_write_locked_rt_reader_preferred(void)
 1825{
 1826 unsigned int i, tries;
 1827 lwpid_t lid;
 1828
 1829 setup_rt_params();
 1830
 1831 /*
 1832 * We need to show the rwlock as write-locked to ensure
 1833 * the rt read-waiter blocks.
 1834 */
 1835 futex_word =
 1836 FUTEX_WAITERS | FUTEX_RW_WRITE_WANTED | FUTEX_RW_WRITE_LOCKED;
 1837 membar_sync();
 1838
 1839 /*
 1840 * Create LWPs in the following order:
 1841 *
 1842 * 0 - non-RT reader
 1843 * 1 - RT reader
 1844 * 2 - non-RT writer
 1845 *
 1846 * We expect them to be awakened in this order:
 1847 *
 1848 * 1 -> 2 -> 0
 1849 */
 1850 for (i = 0; i < 3; i++) {
 1851 if (i == 1) {
 1852 setup_lwp_context(&lwp_data[i],
 1853 rt_simple_test_waiter_lwp);
 1854 lwp_data[i].rt_prio = pri_min;
 1855 } else {
 1856 setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
 1857 }
 1858 lwp_data[i].op_flags = FUTEX_PRIVATE_FLAG;
 1859 lwp_data[i].futex_error = -1;
 1860 lwp_data[i].futex_ptr = &futex_word;
 1861 lwp_data[i].block_val = futex_word;
 1862 lwp_data[i].bitset = i == 2 ? FUTEX_RW_WRITER : FUTEX_RW_READER;
 1863 lwp_data[i].wait_op = FUTEX_NETBSD_RW_WAIT;
 1864 ATF_REQUIRE(_lwp_create(&lwp_data[i].context, 0,
 1865 &lwp_data[i].lwpid) == 0);
 1866
 1867 /*
 1868 * Wait for each one to start in-turn, because we want
 1869 * to know the order in which the LWPs block on the futex.
 1870 */
 1871 for (tries = 0; tries < 5; tries++) {
 1872 membar_sync();
 1873 if (nlwps_running == i + 1)
 1874 break;
 1875 sleep(1);
 1876 }
 1877 membar_sync();
 1878 }
 1879
 1880 ATF_REQUIRE_EQ_MSG(nlwps_running, 3, "waiters failed to start");
 1881
 1882 /* Ensure they're all blocked. */
 1883 ATF_REQUIRE(lwp_data[0].futex_error == -1);
 1884 ATF_REQUIRE(lwp_data[1].futex_error == -1);
 1885 ATF_REQUIRE(lwp_data[2].futex_error == -1);
 1886
 1887 /*
 1888 * Issue a hand-off. It should select the RT reader, and should
 1889 * indicate that there are still waiters, including a write-waiter.
 1890 */
 1891 ATF_REQUIRE(__futex(&futex_word,
 1892 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 1893 futex_word, NULL, NULL, 0, 0) == 1);
 1894 ATF_REQUIRE((futex_word & FUTEX_RW_WRITE_LOCKED) == 0);
 1895 ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_WANTED);
 1896 ATF_REQUIRE(futex_word & FUTEX_WAITERS);
 1897 lid = futex_word & FUTEX_TID_MASK;
 1898 ATF_REQUIRE(lid == 1);
 1899 ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
 1900 ATF_REQUIRE(lid == lwp_data[1].lwpid);
 1901
 1902 /*
 1903 * Issue another hand-off. It should awaken the writer and
 1904 * indicate only readers waiting.
 1905 */
 1906 ATF_REQUIRE(__futex(&futex_word,
 1907 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 1908 futex_word, NULL, NULL, 0, 0) == 1);
 1909 ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_LOCKED);
 1910 ATF_REQUIRE((futex_word & FUTEX_RW_WRITE_WANTED) == 0);
 1911 ATF_REQUIRE(futex_word & FUTEX_WAITERS);
 1912 lid = futex_word & FUTEX_TID_MASK;
 1913 ATF_REQUIRE(lid == lwp_data[2].lwpid);
 1914 ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
 1915 ATF_REQUIRE(lid == lwp_data[2].lwpid);
 1916
 1917 /*
 1918 * Issue another hand-off. It would awaken the non-rt
 1919 * reader and indicate no waiters waiting.
 1920 */
 1921 ATF_REQUIRE(__futex(&futex_word,
 1922 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 1923 futex_word, NULL, NULL, 0, 0) == 1);
 1924 ATF_REQUIRE(futex_word == 1);
 1925 ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
 1926 ATF_REQUIRE(lid == lwp_data[0].lwpid);
 1927
 1928 /*
 1929 * Issue one final hand-off; it should result in a fully
 1930 * released lock word. Note that we don't have any
 1931 * outstaning waiters waiting, and therefore there will
 1932 * not be a kernel futex; this exercises a specific code
 1933 * path in the kernel designed to handle this.
 1934 */
 1935 ATF_REQUIRE(__futex(&futex_word,
 1936 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 1937 futex_word, NULL, NULL, 0, 0) == 0);
 1938 ATF_REQUIRE(futex_word == 0);
 1939
 1940 for (tries = 0; tries < 5; tries++) {
 1941 membar_sync();
 1942 if (nlwps_running == 0)
 1943 break;
 1944 sleep(1);
 1945 }
 1946 membar_sync();
 1947 ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "threads failed to exit");
 1948
 1949 /* Ensure they all exited error-free. */
 1950 ATF_REQUIRE(lwp_data[0].futex_error == 0);
 1951 ATF_REQUIRE(lwp_data[1].futex_error == 0);
 1952 ATF_REQUIRE(lwp_data[2].futex_error == 0);
 1953}
 1954
 1955ATF_TC_WITH_CLEANUP(futex_rw_handoff_write_locked_rt_reader_preferred);
 1956ATF_TC_HEAD(futex_rw_handoff_write_locked_rt_reader_preferred, tc)
 1957{
 1958 atf_tc_set_md_var(tc, "descr",
 1959 "tests that write-locked rwlock direct hand-off "
 1960 "prefers rt readers over non-rt writers");
 1961 atf_tc_set_md_var(tc, "require.user", "root");
 1962}
 1963ATF_TC_BODY(futex_rw_handoff_write_locked_rt_reader_preferred, tc)
 1964{
 1965 atf_tc_skip("futex_rw_handoff is currently broken");
 1966 do_test_rw_handoff_write_locked_rt_reader_preferred();
 1967}
 1968ATF_TC_CLEANUP(futex_rw_handoff_write_locked_rt_reader_preferred, tc)
 1969{
 1970 do_cleanup();
 1971}
 1972
 1973/*****************************************************************************/
 1974
 1975static void
 1976do_test_rw_wait_write_wanted_rt_reader_preferred(void)
 1977{
 1978 unsigned int i, tries;
 1979 lwpid_t lid;
 1980
 1981 setup_rt_params();
 1982
 1983 /*
 1984 * The kernel should not care about the WRITE_WANTED bit, and
 1985 * should use the contents of the sleepqs as the truth.
 1986 */
 1987 futex_word = FUTEX_WAITERS;
 1988 membar_sync();
 1989
 1990 /*
 1991 * Create LWPs in the following order:
 1992 *
 1993 * 0 - non-RT writer
 1994 * 1 - non-RT reader
 1995 * 2 - RT reader
 1996 *
 1997 * We expect:
 1998 *
 1999 * ==> non-RT reader blocks because WRITE_WANTED.
 2000 * ==> RT reader does not block and acquires the read-lock.
 2001 *
 2002 * We then expect hand-offs to awaken the remaining waiters
 2003 * in this order:
 2004 *
 2005 * 0 -> 1
 2006 */
 2007 for (i = 0; i < 3; i++) {
 2008 if (i == 2) {
 2009 setup_lwp_context(&lwp_data[i],
 2010 rt_simple_test_waiter_lwp);
 2011 lwp_data[i].rt_prio = pri_min;
 2012 } else {
 2013 setup_lwp_context(&lwp_data[i], simple_test_waiter_lwp);
 2014 }
 2015 lwp_data[i].op_flags = FUTEX_PRIVATE_FLAG;
 2016 lwp_data[i].futex_error = -1;
 2017 lwp_data[i].futex_ptr = &futex_word;
 2018 lwp_data[i].block_val = futex_word;
 2019 lwp_data[i].bitset = i == 0 ? FUTEX_RW_WRITER : FUTEX_RW_READER;
 2020 lwp_data[i].wait_op = FUTEX_NETBSD_RW_WAIT;
 2021 ATF_REQUIRE(_lwp_create(&lwp_data[i].context, 0,
 2022 &lwp_data[i].lwpid) == 0);
 2023
 2024 /*
 2025 * Wait for the first 2 to start in-turn, because we want
 2026 * to know the order in which the LWPs block on the futex.
 2027 */
 2028 for (tries = 0; i < 2 && tries < 5; tries++) {
 2029 membar_sync();
 2030 if (nlwps_running == i + 1)
 2031 break;
 2032 sleep(1);
 2033 }
 2034 membar_sync();
 2035 }
 2036
 2037 sleep(2);
 2038
 2039 ATF_REQUIRE_EQ_MSG(nlwps_running, 2, "waiters failed to start");
 2040
 2041 /* Ensure the first two are blocked and the 3rd one succeeded. */
 2042 ATF_REQUIRE(lwp_data[0].futex_error == -1);
 2043 ATF_REQUIRE(lwp_data[1].futex_error == -1);
 2044 ATF_REQUIRE(lwp_data[2].futex_error == 0);
 2045
 2046 /*
 2047 * Verify the locked-ness and waiter-status of the rwlock.
 2048 * Also verify it was the expected LWP that made it through
 2049 * the gate.
 2050 */
 2051 ATF_REQUIRE(futex_word == (FUTEX_WAITERS | FUTEX_RW_WRITE_WANTED | 1));
 2052 ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
 2053 ATF_REQUIRE(lid == lwp_data[2].lwpid);
 2054
 2055 /*
 2056 * Issue a hand-off. It should awaken the writer and indicate only
 2057 * readers waiting.
 2058 */
 2059 ATF_REQUIRE(__futex(&futex_word,
 2060 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 2061 futex_word, NULL, NULL, 0, 0) == 1);
 2062 ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_LOCKED);
 2063 ATF_REQUIRE((futex_word & FUTEX_RW_WRITE_WANTED) == 0);
 2064 ATF_REQUIRE(futex_word & FUTEX_WAITERS);
 2065 lid = futex_word & FUTEX_TID_MASK;
 2066 ATF_REQUIRE(lid == lwp_data[0].lwpid);
 2067 ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
 2068 ATF_REQUIRE(lid == lwp_data[0].lwpid);
 2069
 2070 /*
 2071 * Issue another hand-off. It would awaken the non-rt
 2072 * reader and indicate no waiters waiting.
 2073 */
 2074 ATF_REQUIRE(__futex(&futex_word,
 2075 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 2076 futex_word, NULL, NULL, 0, 0) == 1);
 2077 ATF_REQUIRE(futex_word == 1);
 2078 ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
 2079 ATF_REQUIRE(lid == lwp_data[1].lwpid);
 2080
 2081 /*
 2082 * Issue one final hand-off; it should result in a fully
 2083 * released lock word. Note that we don't have any
 2084 * outstaning waiters waiting, and therefore there will
 2085 * not be a kernel futex; this exercises a specific code
 2086 * path in the kernel designed to handle this.
 2087 */
 2088 ATF_REQUIRE(__futex(&futex_word,
 2089 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 2090 futex_word, NULL, NULL, 0, 0) == 0);
 2091 ATF_REQUIRE(futex_word == 0);
 2092
 2093 for (tries = 0; tries < 5; tries++) {
 2094 membar_sync();
 2095 if (nlwps_running == 0)
 2096 break;
 2097 sleep(1);
 2098 }
 2099 membar_sync();
 2100 ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "threads failed to exit");
 2101
 2102 /* Ensure they all exited error-free. */
 2103 ATF_REQUIRE(lwp_data[0].futex_error == 0);
 2104 ATF_REQUIRE(lwp_data[1].futex_error == 0);
 2105}
 2106
 2107ATF_TC_WITH_CLEANUP(futex_rw_wait_write_wanted_rt_reader_preferred);
 2108ATF_TC_HEAD(futex_rw_wait_write_wanted_rt_reader_preferred, tc)
 2109{
 2110 atf_tc_set_md_var(tc, "descr",
 2111 "tests that a wait by a rt-reader acquires "
 2112 "even if the rwlock is wanted by a non-rt writer");
 2113 atf_tc_set_md_var(tc, "require.user", "root");
 2114}
 2115ATF_TC_BODY(futex_rw_wait_write_wanted_rt_reader_preferred, tc)
 2116{
 2117 atf_tc_skip("futex_rw_handoff is currently broken");
 2118 do_test_rw_wait_write_wanted_rt_reader_preferred();
 2119}
 2120ATF_TC_CLEANUP(futex_rw_wait_write_wanted_rt_reader_preferred, tc)
 2121{
 2122 do_cleanup();
 2123}
 2124
 2125/*****************************************************************************/
 2126
 2127static void
 2128do_test_rw_handoff_rt_prio_order(void)
 2129{
 2130 unsigned int i, tries;
 2131 lwpid_t lid;
 2132
 2133 setup_rt_params();
 2134
 2135 /*
 2136 * We need to show the rwlock as write-locked to ensure
 2137 * the rt read-waiter blocks.
 2138 */
 2139 futex_word =
 2140 FUTEX_WAITERS | FUTEX_RW_WRITE_WANTED | FUTEX_RW_WRITE_LOCKED;
 2141 membar_sync();
 2142
 2143 /*
 2144 * Create LWPs in the following order:
 2145 *
 2146 * 0 - pri_min+0 writer
 2147 * 1 - pri_min+1 reader
 2148 * 2 - pri_min+2 writer
 2149 * 3 - pri_min+3 reader
 2150 *
 2151 * We expect only one to be awakened at each hand-off and for them
 2152 * to be awakened in this order:
 2153 *
 2154 * 3 -> 2 -> 1 -> 0
 2155 */
 2156 for (i = 0; i < 4; i++) {
 2157 setup_lwp_context(&lwp_data[i], rt_simple_test_waiter_lwp);
 2158 lwp_data[i].rt_prio = pri_min + i;
 2159 lwp_data[i].op_flags = FUTEX_PRIVATE_FLAG;
 2160 lwp_data[i].futex_error = -1;
 2161 lwp_data[i].futex_ptr = &futex_word;
 2162 lwp_data[i].block_val = futex_word;
 2163 lwp_data[i].bitset = i & 1 ? FUTEX_RW_READER : FUTEX_RW_WRITER;
 2164 lwp_data[i].wait_op = FUTEX_NETBSD_RW_WAIT;
 2165 ATF_REQUIRE(_lwp_create(&lwp_data[i].context, 0,
 2166 &lwp_data[i].lwpid) == 0);
 2167
 2168 /*
 2169 * Wait for each one to start in-turn, because we want
 2170 * to know the order in which the LWPs block on the futex.
 2171 */
 2172 for (tries = 0; tries < 5; tries++) {
 2173 membar_sync();
 2174 if (nlwps_running == i + 1)
 2175 break;
 2176 sleep(1);
 2177 }
 2178 membar_sync();
 2179 }
 2180
 2181 ATF_REQUIRE_EQ_MSG(nlwps_running, 4, "waiters failed to start");
 2182
 2183 /* Ensure they're all blocked. */
 2184 ATF_REQUIRE(lwp_data[0].futex_error == -1);
 2185 ATF_REQUIRE(lwp_data[1].futex_error == -1);
 2186 ATF_REQUIRE(lwp_data[2].futex_error == -1);
 2187 ATF_REQUIRE(lwp_data[3].futex_error == -1);
 2188
 2189 /*
 2190 * Issue a hand-off. It should select the pri_min+3 reader, and should
 2191 * indicate that there are still waiters, including a write-waiter.
 2192 */
 2193 ATF_REQUIRE(__futex(&futex_word,
 2194 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 2195 futex_word, NULL, NULL, 0, 0) == 1);
 2196 ATF_REQUIRE((futex_word & FUTEX_RW_WRITE_LOCKED) == 0);
 2197 ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_WANTED);
 2198 ATF_REQUIRE(futex_word & FUTEX_WAITERS);
 2199 lid = futex_word & FUTEX_TID_MASK;
 2200 ATF_REQUIRE(lid == 1);
 2201 ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
 2202 ATF_REQUIRE(lid == lwp_data[3].lwpid);
 2203
 2204 /*
 2205 * Issue another hand-off. It should awaken the pri_min+2 writer and
 2206 * indicate that there are still waiters, including a write-waiter.
 2207 */
 2208 ATF_REQUIRE(__futex(&futex_word,
 2209 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 2210 futex_word, NULL, NULL, 0, 0) == 1);
 2211 ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_LOCKED);
 2212 ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_WANTED);
 2213 ATF_REQUIRE(futex_word & FUTEX_WAITERS);
 2214 lid = futex_word & FUTEX_TID_MASK;
 2215 ATF_REQUIRE(lid == lwp_data[2].lwpid);
 2216 ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
 2217 ATF_REQUIRE(lid == lwp_data[2].lwpid);
 2218
 2219 /*
 2220 * Issue another a hand-off. It should select the pri_min+1 reader,
 2221 * and should indicate that there are still waiters, including a
 2222 * write-waiter.
 2223 */
 2224 ATF_REQUIRE(__futex(&futex_word,
 2225 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 2226 futex_word, NULL, NULL, 0, 0) == 1);
 2227 ATF_REQUIRE((futex_word & FUTEX_RW_WRITE_LOCKED) == 0);
 2228 ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_WANTED);
 2229 ATF_REQUIRE(futex_word & FUTEX_WAITERS);
 2230 lid = futex_word & FUTEX_TID_MASK;
 2231 ATF_REQUIRE(lid == 1);
 2232 ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
 2233 ATF_REQUIRE(lid == lwp_data[1].lwpid);
 2234
 2235 /*
 2236 * Issue another hand-off. It should awaken the pri_min+0 writer and
 2237 * indicate that there are no more waiters.
 2238 */
 2239 ATF_REQUIRE(__futex(&futex_word,
 2240 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 2241 futex_word, NULL, NULL, 0, 0) == 1);
 2242 ATF_REQUIRE(futex_word & FUTEX_RW_WRITE_LOCKED);
 2243 ATF_REQUIRE((futex_word & FUTEX_RW_WRITE_WANTED) == 0);
 2244 ATF_REQUIRE((futex_word & FUTEX_WAITERS) == 0);
 2245 lid = futex_word & FUTEX_TID_MASK;
 2246 ATF_REQUIRE(lid == lwp_data[0].lwpid);
 2247 ATF_REQUIRE(_lwp_wait(0, &lid) == 0);
 2248 ATF_REQUIRE(lid == lwp_data[0].lwpid);
 2249
 2250 /*
 2251 * Issue one final hand-off; it should result in a fully
 2252 * released lock word. Note that we don't have any
 2253 * outstaning waiters waiting, and therefore there will
 2254 * not be a kernel futex; this exercises a specific code
 2255 * path in the kernel designed to handle this.
 2256 */
 2257 ATF_REQUIRE(__futex(&futex_word,
 2258 FUTEX_NETBSD_RW_HANDOFF | FUTEX_PRIVATE_FLAG,
 2259 futex_word, NULL, NULL, 0, 0) == 0);
 2260 ATF_REQUIRE(futex_word == 0);
 2261
 2262 for (tries = 0; tries < 5; tries++) {
 2263 membar_sync();
 2264 if (nlwps_running == 0)
 2265 break;
 2266 sleep(1);
 2267 }
 2268 membar_sync();
 2269 ATF_REQUIRE_EQ_MSG(nlwps_running, 0, "threads failed to exit");
 2270
 2271 /* Ensure they all exited error-free. */
 2272 ATF_REQUIRE(lwp_data[0].futex_error == 0);
 2273 ATF_REQUIRE(lwp_data[1].futex_error == 0);
 2274 ATF_REQUIRE(lwp_data[2].futex_error == 0);
 2275 ATF_REQUIRE(lwp_data[3].futex_error == 0);
 2276}
 2277
 2278ATF_TC_WITH_CLEANUP(futex_rw_handoff_rt_prio_order);
 2279ATF_TC_HEAD(futex_rw_handoff_rt_prio_order, tc)
 2280{
 2281 atf_tc_set_md_var(tc, "descr",
 2282 "tests that hand-off to mixed readers/writer occurs "
 2283 "in strict priority order");
 2284 atf_tc_set_md_var(tc, "require.user", "root");
 2285}
 2286ATF_TC_BODY(futex_rw_handoff_rt_prio_order, tc)
 2287{
 2288 atf_tc_skip("futex_rw_handoff is currently broken");
 2289 do_test_rw_handoff_rt_prio_order();
 2290}
 2291ATF_TC_CLEANUP(futex_rw_handoff_rt_prio_order, tc)
 2292{
 2293 do_cleanup();
 2294}
 2295
 2296/*****************************************************************************/
 2297
1484ATF_TP_ADD_TCS(tp) 2298ATF_TP_ADD_TCS(tp)
1485{ 2299{
1486 ATF_TP_ADD_TC(tp, futex_basic_wait_wake_private); 2300 ATF_TP_ADD_TC(tp, futex_basic_wait_wake_private);
1487 ATF_TP_ADD_TC(tp, futex_basic_wait_wake_shared); 2301 ATF_TP_ADD_TC(tp, futex_basic_wait_wake_shared);
1488 ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_private); 2302 ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_private);
1489 ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_shared); 2303 ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_shared);
1490 ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_private); 2304 ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_private);
1491 ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_shared); 2305 ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_shared);
1492 ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_cow_private); 2306 ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_cow_private);
1493 ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_cow_shared); 2307 ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_cow_shared);
1494 2308
1495 ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_shared_proc); 2309 ATF_TP_ADD_TC(tp, futex_wait_wake_anon_bs_shared_proc);
1496 ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_shared_proc); 2310 ATF_TP_ADD_TC(tp, futex_wait_wake_file_bs_shared_proc);
@@ -1503,15 +2317,22 @@ ATF_TP_ADD_TCS(tp) @@ -1503,15 +2317,22 @@ ATF_TP_ADD_TCS(tp)
1503 ATF_TP_ADD_TC(tp, futex_wait_timeout_deadline); 2317 ATF_TP_ADD_TC(tp, futex_wait_timeout_deadline);
1504 ATF_TP_ADD_TC(tp, futex_wait_timeout_deadline_rt); 2318 ATF_TP_ADD_TC(tp, futex_wait_timeout_deadline_rt);
1505 2319
1506 ATF_TP_ADD_TC(tp, futex_wait_evil_unmapped_anon); 2320 ATF_TP_ADD_TC(tp, futex_wait_evil_unmapped_anon);
1507 2321
1508 ATF_TP_ADD_TC(tp, futex_requeue); 2322 ATF_TP_ADD_TC(tp, futex_requeue);
1509 ATF_TP_ADD_TC(tp, futex_cmp_requeue); 2323 ATF_TP_ADD_TC(tp, futex_cmp_requeue);
1510 2324
1511 ATF_TP_ADD_TC(tp, futex_wake_op_op); 2325 ATF_TP_ADD_TC(tp, futex_wake_op_op);
1512 ATF_TP_ADD_TC(tp, futex_wake_op_cmp); 2326 ATF_TP_ADD_TC(tp, futex_wake_op_cmp);
1513 2327
1514 ATF_TP_ADD_TC(tp, futex_wake_highest_pri); 2328 ATF_TP_ADD_TC(tp, futex_wake_highest_pri);
1515 2329
 2330 ATF_TP_ADD_TC(tp, futex_rw_handoff_read);
 2331 ATF_TP_ADD_TC(tp, futex_rw_handoff_write);
 2332 ATF_TP_ADD_TC(tp, futex_rw_handoff_write_preferred);
 2333 ATF_TP_ADD_TC(tp, futex_rw_handoff_write_locked_rt_reader_preferred);
 2334 ATF_TP_ADD_TC(tp, futex_rw_wait_write_wanted_rt_reader_preferred);
 2335 ATF_TP_ADD_TC(tp, futex_rw_handoff_rt_prio_order);
 2336
1516 return atf_no_error(); 2337 return atf_no_error();
1517} 2338}