xref: /linux/tools/testing/selftests/futex/functional/futex_requeue.c (revision e2683c8868d03382da7e1ce8453b543a043066d1)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright Collabora Ltd., 2021
4  *
5  * futex cmp requeue test by André Almeida <andrealmeid@collabora.com>
6  */
7 
8 #include <pthread.h>
9 #include <limits.h>
10 
11 #include "futextest.h"
12 #include "kselftest_harness.h"
13 
14 #define timeout_ns  30000000
15 #define WAKE_WAIT_US 10000
16 
17 volatile futex_t *f1;
18 
19 void *waiterfn(void *arg)
20 {
21 	struct timespec to;
22 
23 	to.tv_sec = 0;
24 	to.tv_nsec = timeout_ns;
25 
26 	if (futex_wait(f1, *f1, &to, 0))
27 		printf("waiter failed errno %d\n", errno);
28 
29 	return NULL;
30 }
31 
32 TEST(requeue_single)
33 {
34 	volatile futex_t _f1 = 0;
35 	volatile futex_t f2 = 0;
36 	pthread_t waiter[10];
37 
38 	f1 = &_f1;
39 
40 	/*
41 	 * Requeue a waiter from f1 to f2, and wake f2.
42 	 */
43 	ASSERT_EQ(0, pthread_create(&waiter[0], NULL, waiterfn, NULL));
44 
45 	usleep(WAKE_WAIT_US);
46 
47 	EXPECT_EQ(1, futex_cmp_requeue(f1, 0, &f2, 0, 1, 0));
48 	EXPECT_EQ(1, futex_wake(&f2, 1, 0));
49 }
50 
51 TEST(requeue_multiple)
52 {
53 	volatile futex_t _f1 = 0;
54 	volatile futex_t f2 = 0;
55 	pthread_t waiter[10];
56 	int i;
57 
58 	f1 = &_f1;
59 
60 	/*
61 	 * Create 10 waiters at f1. At futex_requeue, wake 3 and requeue 7.
62 	 * At futex_wake, wake INT_MAX (should be exactly 7).
63 	 */
64 	for (i = 0; i < 10; i++)
65 		ASSERT_EQ(0, pthread_create(&waiter[i], NULL, waiterfn, NULL));
66 
67 	usleep(WAKE_WAIT_US);
68 
69 	EXPECT_EQ(10, futex_cmp_requeue(f1, 0, &f2, 3, 7, 0));
70 	EXPECT_EQ(7, futex_wake(&f2, INT_MAX, 0));
71 }
72 
73 TEST_HARNESS_MAIN
74