xref: /aosp_15_r20/external/liburing/test/wakeup-hang.c (revision 25da2bea747f3a93b4c30fd9708b0618ef55a0e6)
1 /* SPDX-License-Identifier: MIT */
2 #include <sys/eventfd.h>
3 #include <unistd.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <pthread.h>
8 #include <liburing.h>
9 #include <fcntl.h>
10 #include <poll.h>
11 #include <sys/time.h>
12 
13 struct thread_data {
14 	struct io_uring *ring;
15 	int write_fd;
16 };
17 
error_exit(char * message)18 static void error_exit(char *message)
19 {
20 	perror(message);
21 	exit(1);
22 }
23 
listener_thread(void * data)24 static void *listener_thread(void *data)
25 {
26 	struct thread_data *td = data;
27 	struct io_uring_cqe *cqe;
28 	int ret;
29 
30         ret = io_uring_wait_cqe(td->ring, &cqe);
31         if (ret < 0) {
32         	fprintf(stderr, "Error waiting for completion: %s\n",
33                 	strerror(-ret));
34 		goto err;
35         }
36 	if (cqe->res < 0) {
37 		fprintf(stderr, "Error in async operation: %s\n", strerror(-cqe->res));
38 		goto err;
39         }
40 	io_uring_cqe_seen(td->ring, cqe);
41 	return NULL;
42 err:
43 	return (void *) 1;
44 }
45 
wakeup_io_uring(void * data)46 static void *wakeup_io_uring(void *data)
47 {
48 	struct thread_data *td = data;
49 	int res;
50 
51 	res = eventfd_write(td->write_fd, (eventfd_t) 1L);
52 	if (res < 0) {
53 		perror("eventfd_write");
54 		return (void *) 1;
55 	}
56 	return NULL;
57 }
58 
test_pipes(void)59 static int test_pipes(void)
60 {
61 	struct io_uring_sqe *sqe;
62 	struct thread_data td;
63 	struct io_uring ring;
64 	pthread_t t1, t2;
65 	int ret, fds[2];
66 	void *pret;
67 
68 	if (pipe(fds) < 0)
69 		error_exit("eventfd");
70 
71 	ret = io_uring_queue_init(8, &ring, 0);
72 	if (ret) {
73 		fprintf(stderr, "Unable to setup io_uring: %s\n", strerror(-ret));
74 		return 1;
75 	}
76 
77 	td.write_fd = fds[1];
78 	td.ring = &ring;
79 
80 	sqe = io_uring_get_sqe(&ring);
81 	io_uring_prep_poll_add(sqe, fds[0], POLLIN);
82 	sqe->user_data = 2;
83 	ret = io_uring_submit(&ring);
84 	if (ret != 1) {
85 		fprintf(stderr, "ring_submit=%d\n", ret);
86 		return 1;
87 	}
88 
89 	pthread_create(&t1, NULL, listener_thread, &td);
90 
91 	sleep(1);
92 
93 	pthread_create(&t2, NULL, wakeup_io_uring, &td);
94 	pthread_join(t1, &pret);
95 
96 	io_uring_queue_exit(&ring);
97 	return pret != NULL;
98 }
99 
test_eventfd(void)100 static int test_eventfd(void)
101 {
102 	struct io_uring_sqe *sqe;
103 	struct thread_data td;
104 	struct io_uring ring;
105 	pthread_t t1, t2;
106 	int efd, ret;
107 	void *pret;
108 
109 	efd = eventfd(0, 0);
110 	if (efd < 0)
111 		error_exit("eventfd");
112 
113 	ret = io_uring_queue_init(8, &ring, 0);
114 	if (ret) {
115 		fprintf(stderr, "Unable to setup io_uring: %s\n", strerror(-ret));
116 		return 1;
117 	}
118 
119 	td.write_fd = efd;
120 	td.ring = &ring;
121 
122 	sqe = io_uring_get_sqe(&ring);
123 	io_uring_prep_poll_add(sqe, efd, POLLIN);
124 	sqe->user_data = 2;
125 	ret = io_uring_submit(&ring);
126 	if (ret != 1) {
127 		fprintf(stderr, "ring_submit=%d\n", ret);
128 		return 1;
129 	}
130 
131 	pthread_create(&t1, NULL, listener_thread, &td);
132 
133 	sleep(1);
134 
135 	pthread_create(&t2, NULL, wakeup_io_uring, &td);
136 	pthread_join(t1, &pret);
137 
138 	io_uring_queue_exit(&ring);
139 	return pret != NULL;
140 }
141 
main(int argc,char * argv[])142 int main(int argc, char *argv[])
143 {
144 	int ret;
145 
146 	if (argc > 1)
147 		return 0;
148 
149 	ret = test_pipes();
150 	if (ret) {
151 		fprintf(stderr, "test_pipe failed\n");
152 		return ret;
153 	}
154 
155 	ret = test_eventfd();
156 	if (ret) {
157 		fprintf(stderr, "test_eventfd failed\n");
158 		return ret;
159 	}
160 
161 	return 0;
162 }
163