xref: /openbmc/linux/tools/testing/selftests/futex/functional/futex_wait.c (revision 762f99f4f3cb41a775b5157dd761217beba65873)
1*c3d12858SAndré Almeida // SPDX-License-Identifier: GPL-2.0-or-later
2*c3d12858SAndré Almeida /*
3*c3d12858SAndré Almeida  * Copyright Collabora Ltd., 2021
4*c3d12858SAndré Almeida  *
5*c3d12858SAndré Almeida  * futex cmp requeue test by André Almeida <andrealmeid@collabora.com>
6*c3d12858SAndré Almeida  */
7*c3d12858SAndré Almeida 
8*c3d12858SAndré Almeida #include <pthread.h>
9*c3d12858SAndré Almeida #include <sys/shm.h>
10*c3d12858SAndré Almeida #include <sys/mman.h>
11*c3d12858SAndré Almeida #include <fcntl.h>
12*c3d12858SAndré Almeida #include "logging.h"
13*c3d12858SAndré Almeida #include "futextest.h"
14*c3d12858SAndré Almeida 
15*c3d12858SAndré Almeida #define TEST_NAME "futex-wait"
16*c3d12858SAndré Almeida #define timeout_ns  30000000
17*c3d12858SAndré Almeida #define WAKE_WAIT_US 10000
18*c3d12858SAndré Almeida #define SHM_PATH "futex_shm_file"
19*c3d12858SAndré Almeida 
20*c3d12858SAndré Almeida void *futex;
21*c3d12858SAndré Almeida 
usage(char * prog)22*c3d12858SAndré Almeida void usage(char *prog)
23*c3d12858SAndré Almeida {
24*c3d12858SAndré Almeida 	printf("Usage: %s\n", prog);
25*c3d12858SAndré Almeida 	printf("  -c	Use color\n");
26*c3d12858SAndré Almeida 	printf("  -h	Display this help message\n");
27*c3d12858SAndré Almeida 	printf("  -v L	Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n",
28*c3d12858SAndré Almeida 	       VQUIET, VCRITICAL, VINFO);
29*c3d12858SAndré Almeida }
30*c3d12858SAndré Almeida 
waiterfn(void * arg)31*c3d12858SAndré Almeida static void *waiterfn(void *arg)
32*c3d12858SAndré Almeida {
33*c3d12858SAndré Almeida 	struct timespec to;
34*c3d12858SAndré Almeida 	unsigned int flags = 0;
35*c3d12858SAndré Almeida 
36*c3d12858SAndré Almeida 	if (arg)
37*c3d12858SAndré Almeida 		flags = *((unsigned int *) arg);
38*c3d12858SAndré Almeida 
39*c3d12858SAndré Almeida 	to.tv_sec = 0;
40*c3d12858SAndré Almeida 	to.tv_nsec = timeout_ns;
41*c3d12858SAndré Almeida 
42*c3d12858SAndré Almeida 	if (futex_wait(futex, 0, &to, flags))
43*c3d12858SAndré Almeida 		printf("waiter failed errno %d\n", errno);
44*c3d12858SAndré Almeida 
45*c3d12858SAndré Almeida 	return NULL;
46*c3d12858SAndré Almeida }
47*c3d12858SAndré Almeida 
main(int argc,char * argv[])48*c3d12858SAndré Almeida int main(int argc, char *argv[])
49*c3d12858SAndré Almeida {
50*c3d12858SAndré Almeida 	int res, ret = RET_PASS, fd, c, shm_id;
51*c3d12858SAndré Almeida 	u_int32_t f_private = 0, *shared_data;
52*c3d12858SAndré Almeida 	unsigned int flags = FUTEX_PRIVATE_FLAG;
53*c3d12858SAndré Almeida 	pthread_t waiter;
54*c3d12858SAndré Almeida 	void *shm;
55*c3d12858SAndré Almeida 
56*c3d12858SAndré Almeida 	futex = &f_private;
57*c3d12858SAndré Almeida 
58*c3d12858SAndré Almeida 	while ((c = getopt(argc, argv, "cht:v:")) != -1) {
59*c3d12858SAndré Almeida 		switch (c) {
60*c3d12858SAndré Almeida 		case 'c':
61*c3d12858SAndré Almeida 			log_color(1);
62*c3d12858SAndré Almeida 			break;
63*c3d12858SAndré Almeida 		case 'h':
64*c3d12858SAndré Almeida 			usage(basename(argv[0]));
65*c3d12858SAndré Almeida 			exit(0);
66*c3d12858SAndré Almeida 		case 'v':
67*c3d12858SAndré Almeida 			log_verbosity(atoi(optarg));
68*c3d12858SAndré Almeida 			break;
69*c3d12858SAndré Almeida 		default:
70*c3d12858SAndré Almeida 			usage(basename(argv[0]));
71*c3d12858SAndré Almeida 			exit(1);
72*c3d12858SAndré Almeida 		}
73*c3d12858SAndré Almeida 	}
74*c3d12858SAndré Almeida 
75*c3d12858SAndré Almeida 	ksft_print_header();
76*c3d12858SAndré Almeida 	ksft_set_plan(3);
77*c3d12858SAndré Almeida 	ksft_print_msg("%s: Test futex_wait\n", basename(argv[0]));
78*c3d12858SAndré Almeida 
79*c3d12858SAndré Almeida 	/* Testing a private futex */
80*c3d12858SAndré Almeida 	info("Calling private futex_wait on futex: %p\n", futex);
81*c3d12858SAndré Almeida 	if (pthread_create(&waiter, NULL, waiterfn, (void *) &flags))
82*c3d12858SAndré Almeida 		error("pthread_create failed\n", errno);
83*c3d12858SAndré Almeida 
84*c3d12858SAndré Almeida 	usleep(WAKE_WAIT_US);
85*c3d12858SAndré Almeida 
86*c3d12858SAndré Almeida 	info("Calling private futex_wake on futex: %p\n", futex);
87*c3d12858SAndré Almeida 	res = futex_wake(futex, 1, FUTEX_PRIVATE_FLAG);
88*c3d12858SAndré Almeida 	if (res != 1) {
89*c3d12858SAndré Almeida 		ksft_test_result_fail("futex_wake private returned: %d %s\n",
90*c3d12858SAndré Almeida 				      errno, strerror(errno));
91*c3d12858SAndré Almeida 		ret = RET_FAIL;
92*c3d12858SAndré Almeida 	} else {
93*c3d12858SAndré Almeida 		ksft_test_result_pass("futex_wake private succeeds\n");
94*c3d12858SAndré Almeida 	}
95*c3d12858SAndré Almeida 
96*c3d12858SAndré Almeida 	/* Testing an anon page shared memory */
97*c3d12858SAndré Almeida 	shm_id = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0666);
98*c3d12858SAndré Almeida 	if (shm_id < 0) {
99*c3d12858SAndré Almeida 		perror("shmget");
100*c3d12858SAndré Almeida 		exit(1);
101*c3d12858SAndré Almeida 	}
102*c3d12858SAndré Almeida 
103*c3d12858SAndré Almeida 	shared_data = shmat(shm_id, NULL, 0);
104*c3d12858SAndré Almeida 
105*c3d12858SAndré Almeida 	*shared_data = 0;
106*c3d12858SAndré Almeida 	futex = shared_data;
107*c3d12858SAndré Almeida 
108*c3d12858SAndré Almeida 	info("Calling shared (page anon) futex_wait on futex: %p\n", futex);
109*c3d12858SAndré Almeida 	if (pthread_create(&waiter, NULL, waiterfn, NULL))
110*c3d12858SAndré Almeida 		error("pthread_create failed\n", errno);
111*c3d12858SAndré Almeida 
112*c3d12858SAndré Almeida 	usleep(WAKE_WAIT_US);
113*c3d12858SAndré Almeida 
114*c3d12858SAndré Almeida 	info("Calling shared (page anon) futex_wake on futex: %p\n", futex);
115*c3d12858SAndré Almeida 	res = futex_wake(futex, 1, 0);
116*c3d12858SAndré Almeida 	if (res != 1) {
117*c3d12858SAndré Almeida 		ksft_test_result_fail("futex_wake shared (page anon) returned: %d %s\n",
118*c3d12858SAndré Almeida 				      errno, strerror(errno));
119*c3d12858SAndré Almeida 		ret = RET_FAIL;
120*c3d12858SAndré Almeida 	} else {
121*c3d12858SAndré Almeida 		ksft_test_result_pass("futex_wake shared (page anon) succeeds\n");
122*c3d12858SAndré Almeida 	}
123*c3d12858SAndré Almeida 
124*c3d12858SAndré Almeida 
125*c3d12858SAndré Almeida 	/* Testing a file backed shared memory */
126*c3d12858SAndré Almeida 	fd = open(SHM_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
127*c3d12858SAndré Almeida 	if (fd < 0) {
128*c3d12858SAndré Almeida 		perror("open");
129*c3d12858SAndré Almeida 		exit(1);
130*c3d12858SAndré Almeida 	}
131*c3d12858SAndré Almeida 
132*c3d12858SAndré Almeida 	if (ftruncate(fd, sizeof(f_private))) {
133*c3d12858SAndré Almeida 		perror("ftruncate");
134*c3d12858SAndré Almeida 		exit(1);
135*c3d12858SAndré Almeida 	}
136*c3d12858SAndré Almeida 
137*c3d12858SAndré Almeida 	shm = mmap(NULL, sizeof(f_private), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
138*c3d12858SAndré Almeida 	if (shm == MAP_FAILED) {
139*c3d12858SAndré Almeida 		perror("mmap");
140*c3d12858SAndré Almeida 		exit(1);
141*c3d12858SAndré Almeida 	}
142*c3d12858SAndré Almeida 
143*c3d12858SAndré Almeida 	memcpy(shm, &f_private, sizeof(f_private));
144*c3d12858SAndré Almeida 
145*c3d12858SAndré Almeida 	futex = shm;
146*c3d12858SAndré Almeida 
147*c3d12858SAndré Almeida 	info("Calling shared (file backed) futex_wait on futex: %p\n", futex);
148*c3d12858SAndré Almeida 	if (pthread_create(&waiter, NULL, waiterfn, NULL))
149*c3d12858SAndré Almeida 		error("pthread_create failed\n", errno);
150*c3d12858SAndré Almeida 
151*c3d12858SAndré Almeida 	usleep(WAKE_WAIT_US);
152*c3d12858SAndré Almeida 
153*c3d12858SAndré Almeida 	info("Calling shared (file backed) futex_wake on futex: %p\n", futex);
154*c3d12858SAndré Almeida 	res = futex_wake(shm, 1, 0);
155*c3d12858SAndré Almeida 	if (res != 1) {
156*c3d12858SAndré Almeida 		ksft_test_result_fail("futex_wake shared (file backed) returned: %d %s\n",
157*c3d12858SAndré Almeida 				      errno, strerror(errno));
158*c3d12858SAndré Almeida 		ret = RET_FAIL;
159*c3d12858SAndré Almeida 	} else {
160*c3d12858SAndré Almeida 		ksft_test_result_pass("futex_wake shared (file backed) succeeds\n");
161*c3d12858SAndré Almeida 	}
162*c3d12858SAndré Almeida 
163*c3d12858SAndré Almeida 	/* Freeing resources */
164*c3d12858SAndré Almeida 	shmdt(shared_data);
165*c3d12858SAndré Almeida 	munmap(shm, sizeof(f_private));
166*c3d12858SAndré Almeida 	remove(SHM_PATH);
167*c3d12858SAndré Almeida 	close(fd);
168*c3d12858SAndré Almeida 
169*c3d12858SAndré Almeida 	ksft_print_cnts();
170*c3d12858SAndré Almeida 	return ret;
171*c3d12858SAndré Almeida }
172