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