| @@ -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 |
68 | struct lwp_data { | | 68 | struct 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 | |
95 | struct lwp_data lwp_data[NLWPS]; | | 96 | struct lwp_data lwp_data[NLWPS]; |
96 | | | 97 | |
97 | static const char *bs_path = "t_futex_ops_backing_store"; | | 98 | static const char *bs_path = "t_futex_ops_backing_store"; |
98 | static int bs_fd = -1; | | 99 | static int bs_fd = -1; |
99 | static int *bs_addr = MAP_FAILED; | | 100 | static int *bs_addr = MAP_FAILED; |
100 | static void *bs_source_buffer = NULL; | | 101 | static void *bs_source_buffer = NULL; |
101 | static void *bs_verify_buffer = NULL; | | 102 | static void *bs_verify_buffer = NULL; |
102 | static long bs_pagesize; | | 103 | static long bs_pagesize; |
103 | | | 104 | |
| | | 105 | static int pri_min; |
| | | 106 | static int pri_max; |
| | | 107 | |
| | | 108 | static void |
| | | 109 | setup_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 | |
104 | static void | | 119 | static void |
105 | create_lwp_waiter(struct lwp_data *d) | | 120 | create_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 | |
110 | static void | | 125 | static void |
111 | exit_lwp_waiter(void) | | 126 | exit_lwp_waiter(void) |
112 | { | | 127 | { |
113 | _lwp_exit(); | | 128 | _lwp_exit(); |
114 | } | | 129 | } |
115 | | | 130 | |
116 | static void | | 131 | static 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 | |
| | | 206 | static void |
| | | 207 | rt_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 | |
191 | static bool | | 223 | static bool |
192 | verify_zero_bs(void) | | 224 | verify_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 | } |
1326 | ATF_TC_BODY(futex_wait_evil_unmapped_anon, tc) | | 1358 | ATF_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 | } |
1330 | ATF_TC_CLEANUP(futex_wait_evil_unmapped_anon, tc) | | 1362 | ATF_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 | |
1338 | static int pri_min; | | | |
1339 | static int pri_max; | | | |
1340 | | | | |
1341 | static void | | | |
1342 | lowpri_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 | | | | |
1358 | static void | | | |
1359 | highpri_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 | | | | |
1375 | static void | | 1370 | static void |
1376 | do_test_wake_highest_pri(void) | | 1371 | do_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 | |
1465 | ATF_TC_WITH_CLEANUP(futex_wake_highest_pri); | | 1458 | ATF_TC_WITH_CLEANUP(futex_wake_highest_pri); |
1466 | ATF_TC_HEAD(futex_wake_highest_pri, tc) | | 1459 | ATF_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 | } |
1472 | ATF_TC_BODY(futex_wake_highest_pri, tc) | | 1465 | ATF_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 | } |
1477 | ATF_TC_CLEANUP(futex_wake_highest_pri, tc) | | 1469 | ATF_TC_CLEANUP(futex_wake_highest_pri, tc) |
1478 | { | | 1470 | { |
1479 | do_cleanup(); | | 1471 | do_cleanup(); |
1480 | } | | 1472 | } |
1481 | | | 1473 | |
1482 | /*****************************************************************************/ | | 1474 | /*****************************************************************************/ |
1483 | | | 1475 | |
| | | 1476 | static void |
| | | 1477 | do_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 | |
| | | 1547 | ATF_TC_WITH_CLEANUP(futex_rw_handoff_read); |
| | | 1548 | ATF_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 | } |
| | | 1553 | ATF_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 | } |
| | | 1558 | ATF_TC_CLEANUP(futex_rw_handoff_read, tc) |
| | | 1559 | { |
| | | 1560 | do_cleanup(); |
| | | 1561 | } |
| | | 1562 | |
| | | 1563 | /*****************************************************************************/ |
| | | 1564 | |
| | | 1565 | static void |
| | | 1566 | do_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 | |
| | | 1669 | ATF_TC_WITH_CLEANUP(futex_rw_handoff_write); |
| | | 1670 | ATF_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 | } |
| | | 1675 | ATF_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 | } |
| | | 1680 | ATF_TC_CLEANUP(futex_rw_handoff_write, tc) |
| | | 1681 | { |
| | | 1682 | do_cleanup(); |
| | | 1683 | } |
| | | 1684 | |
| | | 1685 | /*****************************************************************************/ |
| | | 1686 | |
| | | 1687 | static void |
| | | 1688 | do_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 | |
| | | 1805 | ATF_TC_WITH_CLEANUP(futex_rw_handoff_write_preferred); |
| | | 1806 | ATF_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 | } |
| | | 1811 | ATF_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 | } |
| | | 1816 | ATF_TC_CLEANUP(futex_rw_handoff_write_preferred, tc) |
| | | 1817 | { |
| | | 1818 | do_cleanup(); |
| | | 1819 | } |
| | | 1820 | |
| | | 1821 | /*****************************************************************************/ |
| | | 1822 | |
| | | 1823 | static void |
| | | 1824 | do_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 | |
| | | 1955 | ATF_TC_WITH_CLEANUP(futex_rw_handoff_write_locked_rt_reader_preferred); |
| | | 1956 | ATF_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 | } |
| | | 1963 | ATF_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 | } |
| | | 1968 | ATF_TC_CLEANUP(futex_rw_handoff_write_locked_rt_reader_preferred, tc) |
| | | 1969 | { |
| | | 1970 | do_cleanup(); |
| | | 1971 | } |
| | | 1972 | |
| | | 1973 | /*****************************************************************************/ |
| | | 1974 | |
| | | 1975 | static void |
| | | 1976 | do_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 | |
| | | 2107 | ATF_TC_WITH_CLEANUP(futex_rw_wait_write_wanted_rt_reader_preferred); |
| | | 2108 | ATF_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 | } |
| | | 2115 | ATF_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 | } |
| | | 2120 | ATF_TC_CLEANUP(futex_rw_wait_write_wanted_rt_reader_preferred, tc) |
| | | 2121 | { |
| | | 2122 | do_cleanup(); |
| | | 2123 | } |
| | | 2124 | |
| | | 2125 | /*****************************************************************************/ |
| | | 2126 | |
| | | 2127 | static void |
| | | 2128 | do_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 | |
| | | 2278 | ATF_TC_WITH_CLEANUP(futex_rw_handoff_rt_prio_order); |
| | | 2279 | ATF_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 | } |
| | | 2286 | ATF_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 | } |
| | | 2291 | ATF_TC_CLEANUP(futex_rw_handoff_rt_prio_order, tc) |
| | | 2292 | { |
| | | 2293 | do_cleanup(); |
| | | 2294 | } |
| | | 2295 | |
| | | 2296 | /*****************************************************************************/ |
| | | 2297 | |
1484 | ATF_TP_ADD_TCS(tp) | | 2298 | ATF_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 | } |