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