1*25da2beaSAndroid Build Coastguard Worker /* SPDX-License-Identifier: MIT */
2*25da2beaSAndroid Build Coastguard Worker /*
3*25da2beaSAndroid Build Coastguard Worker * Test MSG_WAITALL for recv/recvmsg and include normal sync versions just
4*25da2beaSAndroid Build Coastguard Worker * for comparison.
5*25da2beaSAndroid Build Coastguard Worker */
6*25da2beaSAndroid Build Coastguard Worker #include <errno.h>
7*25da2beaSAndroid Build Coastguard Worker #include <stdio.h>
8*25da2beaSAndroid Build Coastguard Worker #include <stdlib.h>
9*25da2beaSAndroid Build Coastguard Worker #include <string.h>
10*25da2beaSAndroid Build Coastguard Worker #include <unistd.h>
11*25da2beaSAndroid Build Coastguard Worker #include <fcntl.h>
12*25da2beaSAndroid Build Coastguard Worker #include <arpa/inet.h>
13*25da2beaSAndroid Build Coastguard Worker #include <sys/types.h>
14*25da2beaSAndroid Build Coastguard Worker #include <sys/socket.h>
15*25da2beaSAndroid Build Coastguard Worker #include <pthread.h>
16*25da2beaSAndroid Build Coastguard Worker
17*25da2beaSAndroid Build Coastguard Worker #include "liburing.h"
18*25da2beaSAndroid Build Coastguard Worker #include "helpers.h"
19*25da2beaSAndroid Build Coastguard Worker
20*25da2beaSAndroid Build Coastguard Worker #define MAX_MSG 128
21*25da2beaSAndroid Build Coastguard Worker
22*25da2beaSAndroid Build Coastguard Worker static int port = 31200;
23*25da2beaSAndroid Build Coastguard Worker
24*25da2beaSAndroid Build Coastguard Worker struct recv_data {
25*25da2beaSAndroid Build Coastguard Worker pthread_mutex_t mutex;
26*25da2beaSAndroid Build Coastguard Worker int use_recvmsg;
27*25da2beaSAndroid Build Coastguard Worker int use_sync;
28*25da2beaSAndroid Build Coastguard Worker int port;
29*25da2beaSAndroid Build Coastguard Worker };
30*25da2beaSAndroid Build Coastguard Worker
get_conn_sock(struct recv_data * rd,int * sockout)31*25da2beaSAndroid Build Coastguard Worker static int get_conn_sock(struct recv_data *rd, int *sockout)
32*25da2beaSAndroid Build Coastguard Worker {
33*25da2beaSAndroid Build Coastguard Worker struct sockaddr_in saddr;
34*25da2beaSAndroid Build Coastguard Worker int sockfd, ret, val;
35*25da2beaSAndroid Build Coastguard Worker
36*25da2beaSAndroid Build Coastguard Worker memset(&saddr, 0, sizeof(saddr));
37*25da2beaSAndroid Build Coastguard Worker saddr.sin_family = AF_INET;
38*25da2beaSAndroid Build Coastguard Worker saddr.sin_addr.s_addr = htonl(INADDR_ANY);
39*25da2beaSAndroid Build Coastguard Worker saddr.sin_port = htons(rd->port);
40*25da2beaSAndroid Build Coastguard Worker
41*25da2beaSAndroid Build Coastguard Worker sockfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
42*25da2beaSAndroid Build Coastguard Worker if (sockfd < 0) {
43*25da2beaSAndroid Build Coastguard Worker perror("socket");
44*25da2beaSAndroid Build Coastguard Worker goto err;
45*25da2beaSAndroid Build Coastguard Worker }
46*25da2beaSAndroid Build Coastguard Worker
47*25da2beaSAndroid Build Coastguard Worker val = 1;
48*25da2beaSAndroid Build Coastguard Worker setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
49*25da2beaSAndroid Build Coastguard Worker setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
50*25da2beaSAndroid Build Coastguard Worker
51*25da2beaSAndroid Build Coastguard Worker ret = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));
52*25da2beaSAndroid Build Coastguard Worker if (ret < 0) {
53*25da2beaSAndroid Build Coastguard Worker perror("bind");
54*25da2beaSAndroid Build Coastguard Worker goto err;
55*25da2beaSAndroid Build Coastguard Worker }
56*25da2beaSAndroid Build Coastguard Worker
57*25da2beaSAndroid Build Coastguard Worker ret = listen(sockfd, 16);
58*25da2beaSAndroid Build Coastguard Worker if (ret < 0) {
59*25da2beaSAndroid Build Coastguard Worker perror("listen");
60*25da2beaSAndroid Build Coastguard Worker goto err;
61*25da2beaSAndroid Build Coastguard Worker }
62*25da2beaSAndroid Build Coastguard Worker
63*25da2beaSAndroid Build Coastguard Worker pthread_mutex_unlock(&rd->mutex);
64*25da2beaSAndroid Build Coastguard Worker
65*25da2beaSAndroid Build Coastguard Worker ret = accept(sockfd, NULL, NULL);
66*25da2beaSAndroid Build Coastguard Worker if (ret < 0) {
67*25da2beaSAndroid Build Coastguard Worker perror("accept");
68*25da2beaSAndroid Build Coastguard Worker return -1;
69*25da2beaSAndroid Build Coastguard Worker }
70*25da2beaSAndroid Build Coastguard Worker
71*25da2beaSAndroid Build Coastguard Worker *sockout = sockfd;
72*25da2beaSAndroid Build Coastguard Worker return ret;
73*25da2beaSAndroid Build Coastguard Worker err:
74*25da2beaSAndroid Build Coastguard Worker pthread_mutex_unlock(&rd->mutex);
75*25da2beaSAndroid Build Coastguard Worker return -1;
76*25da2beaSAndroid Build Coastguard Worker }
77*25da2beaSAndroid Build Coastguard Worker
recv_prep(struct io_uring * ring,struct iovec * iov,int * sock,struct recv_data * rd)78*25da2beaSAndroid Build Coastguard Worker static int recv_prep(struct io_uring *ring, struct iovec *iov, int *sock,
79*25da2beaSAndroid Build Coastguard Worker struct recv_data *rd)
80*25da2beaSAndroid Build Coastguard Worker {
81*25da2beaSAndroid Build Coastguard Worker struct io_uring_sqe *sqe;
82*25da2beaSAndroid Build Coastguard Worker struct msghdr msg = { };
83*25da2beaSAndroid Build Coastguard Worker int sockfd, sockout = -1, ret;
84*25da2beaSAndroid Build Coastguard Worker
85*25da2beaSAndroid Build Coastguard Worker sockfd = get_conn_sock(rd, &sockout);
86*25da2beaSAndroid Build Coastguard Worker if (sockfd < 0)
87*25da2beaSAndroid Build Coastguard Worker goto err;
88*25da2beaSAndroid Build Coastguard Worker
89*25da2beaSAndroid Build Coastguard Worker sqe = io_uring_get_sqe(ring);
90*25da2beaSAndroid Build Coastguard Worker if (!rd->use_recvmsg) {
91*25da2beaSAndroid Build Coastguard Worker io_uring_prep_recv(sqe, sockfd, iov->iov_base, iov->iov_len,
92*25da2beaSAndroid Build Coastguard Worker MSG_WAITALL);
93*25da2beaSAndroid Build Coastguard Worker } else {
94*25da2beaSAndroid Build Coastguard Worker msg.msg_namelen = sizeof(struct sockaddr_in);
95*25da2beaSAndroid Build Coastguard Worker msg.msg_iov = iov;
96*25da2beaSAndroid Build Coastguard Worker msg.msg_iovlen = 1;
97*25da2beaSAndroid Build Coastguard Worker io_uring_prep_recvmsg(sqe, sockfd, &msg, MSG_WAITALL);
98*25da2beaSAndroid Build Coastguard Worker }
99*25da2beaSAndroid Build Coastguard Worker
100*25da2beaSAndroid Build Coastguard Worker sqe->user_data = 2;
101*25da2beaSAndroid Build Coastguard Worker
102*25da2beaSAndroid Build Coastguard Worker ret = io_uring_submit(ring);
103*25da2beaSAndroid Build Coastguard Worker if (ret <= 0) {
104*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "submit failed: %d\n", ret);
105*25da2beaSAndroid Build Coastguard Worker goto err;
106*25da2beaSAndroid Build Coastguard Worker }
107*25da2beaSAndroid Build Coastguard Worker
108*25da2beaSAndroid Build Coastguard Worker *sock = sockfd;
109*25da2beaSAndroid Build Coastguard Worker return 0;
110*25da2beaSAndroid Build Coastguard Worker err:
111*25da2beaSAndroid Build Coastguard Worker if (sockout != -1) {
112*25da2beaSAndroid Build Coastguard Worker shutdown(sockout, SHUT_RDWR);
113*25da2beaSAndroid Build Coastguard Worker close(sockout);
114*25da2beaSAndroid Build Coastguard Worker }
115*25da2beaSAndroid Build Coastguard Worker if (sockfd != -1) {
116*25da2beaSAndroid Build Coastguard Worker shutdown(sockfd, SHUT_RDWR);
117*25da2beaSAndroid Build Coastguard Worker close(sockfd);
118*25da2beaSAndroid Build Coastguard Worker }
119*25da2beaSAndroid Build Coastguard Worker return 1;
120*25da2beaSAndroid Build Coastguard Worker }
121*25da2beaSAndroid Build Coastguard Worker
do_recv(struct io_uring * ring)122*25da2beaSAndroid Build Coastguard Worker static int do_recv(struct io_uring *ring)
123*25da2beaSAndroid Build Coastguard Worker {
124*25da2beaSAndroid Build Coastguard Worker struct io_uring_cqe *cqe;
125*25da2beaSAndroid Build Coastguard Worker int ret;
126*25da2beaSAndroid Build Coastguard Worker
127*25da2beaSAndroid Build Coastguard Worker ret = io_uring_wait_cqe(ring, &cqe);
128*25da2beaSAndroid Build Coastguard Worker if (ret) {
129*25da2beaSAndroid Build Coastguard Worker fprintf(stdout, "wait_cqe: %d\n", ret);
130*25da2beaSAndroid Build Coastguard Worker goto err;
131*25da2beaSAndroid Build Coastguard Worker }
132*25da2beaSAndroid Build Coastguard Worker if (cqe->res == -EINVAL) {
133*25da2beaSAndroid Build Coastguard Worker fprintf(stdout, "recv not supported, skipping\n");
134*25da2beaSAndroid Build Coastguard Worker return 0;
135*25da2beaSAndroid Build Coastguard Worker }
136*25da2beaSAndroid Build Coastguard Worker if (cqe->res < 0) {
137*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "failed cqe: %d\n", cqe->res);
138*25da2beaSAndroid Build Coastguard Worker goto err;
139*25da2beaSAndroid Build Coastguard Worker }
140*25da2beaSAndroid Build Coastguard Worker if (cqe->res != MAX_MSG * sizeof(int)) {
141*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "got wrong length: %d\n", cqe->res);
142*25da2beaSAndroid Build Coastguard Worker goto err;
143*25da2beaSAndroid Build Coastguard Worker }
144*25da2beaSAndroid Build Coastguard Worker
145*25da2beaSAndroid Build Coastguard Worker io_uring_cqe_seen(ring, cqe);
146*25da2beaSAndroid Build Coastguard Worker return 0;
147*25da2beaSAndroid Build Coastguard Worker err:
148*25da2beaSAndroid Build Coastguard Worker return 1;
149*25da2beaSAndroid Build Coastguard Worker }
150*25da2beaSAndroid Build Coastguard Worker
recv_sync(struct recv_data * rd)151*25da2beaSAndroid Build Coastguard Worker static int recv_sync(struct recv_data *rd)
152*25da2beaSAndroid Build Coastguard Worker {
153*25da2beaSAndroid Build Coastguard Worker int buf[MAX_MSG];
154*25da2beaSAndroid Build Coastguard Worker struct iovec iov = {
155*25da2beaSAndroid Build Coastguard Worker .iov_base = buf,
156*25da2beaSAndroid Build Coastguard Worker .iov_len = sizeof(buf),
157*25da2beaSAndroid Build Coastguard Worker };
158*25da2beaSAndroid Build Coastguard Worker int i, ret, sockfd, sockout = -1;
159*25da2beaSAndroid Build Coastguard Worker
160*25da2beaSAndroid Build Coastguard Worker sockfd = get_conn_sock(rd, &sockout);
161*25da2beaSAndroid Build Coastguard Worker
162*25da2beaSAndroid Build Coastguard Worker if (rd->use_recvmsg) {
163*25da2beaSAndroid Build Coastguard Worker struct msghdr msg = { };
164*25da2beaSAndroid Build Coastguard Worker
165*25da2beaSAndroid Build Coastguard Worker msg.msg_namelen = sizeof(struct sockaddr_in);
166*25da2beaSAndroid Build Coastguard Worker msg.msg_iov = &iov;
167*25da2beaSAndroid Build Coastguard Worker msg.msg_iovlen = 1;
168*25da2beaSAndroid Build Coastguard Worker ret = recvmsg(sockfd, &msg, MSG_WAITALL);
169*25da2beaSAndroid Build Coastguard Worker } else {
170*25da2beaSAndroid Build Coastguard Worker ret = recv(sockfd, buf, sizeof(buf), MSG_WAITALL);
171*25da2beaSAndroid Build Coastguard Worker }
172*25da2beaSAndroid Build Coastguard Worker
173*25da2beaSAndroid Build Coastguard Worker if (ret < 0) {
174*25da2beaSAndroid Build Coastguard Worker perror("receive");
175*25da2beaSAndroid Build Coastguard Worker goto err;
176*25da2beaSAndroid Build Coastguard Worker }
177*25da2beaSAndroid Build Coastguard Worker
178*25da2beaSAndroid Build Coastguard Worker if (ret != sizeof(buf)) {
179*25da2beaSAndroid Build Coastguard Worker ret = -1;
180*25da2beaSAndroid Build Coastguard Worker goto err;
181*25da2beaSAndroid Build Coastguard Worker }
182*25da2beaSAndroid Build Coastguard Worker
183*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < MAX_MSG; i++) {
184*25da2beaSAndroid Build Coastguard Worker if (buf[i] != i)
185*25da2beaSAndroid Build Coastguard Worker goto err;
186*25da2beaSAndroid Build Coastguard Worker }
187*25da2beaSAndroid Build Coastguard Worker ret = 0;
188*25da2beaSAndroid Build Coastguard Worker err:
189*25da2beaSAndroid Build Coastguard Worker shutdown(sockout, SHUT_RDWR);
190*25da2beaSAndroid Build Coastguard Worker shutdown(sockfd, SHUT_RDWR);
191*25da2beaSAndroid Build Coastguard Worker close(sockout);
192*25da2beaSAndroid Build Coastguard Worker close(sockfd);
193*25da2beaSAndroid Build Coastguard Worker return ret;
194*25da2beaSAndroid Build Coastguard Worker }
195*25da2beaSAndroid Build Coastguard Worker
recv_uring(struct recv_data * rd)196*25da2beaSAndroid Build Coastguard Worker static int recv_uring(struct recv_data *rd)
197*25da2beaSAndroid Build Coastguard Worker {
198*25da2beaSAndroid Build Coastguard Worker int buf[MAX_MSG];
199*25da2beaSAndroid Build Coastguard Worker struct iovec iov = {
200*25da2beaSAndroid Build Coastguard Worker .iov_base = buf,
201*25da2beaSAndroid Build Coastguard Worker .iov_len = sizeof(buf),
202*25da2beaSAndroid Build Coastguard Worker };
203*25da2beaSAndroid Build Coastguard Worker struct io_uring_params p = { };
204*25da2beaSAndroid Build Coastguard Worker struct io_uring ring;
205*25da2beaSAndroid Build Coastguard Worker int ret, sock = -1, sockout = -1;
206*25da2beaSAndroid Build Coastguard Worker
207*25da2beaSAndroid Build Coastguard Worker ret = t_create_ring_params(1, &ring, &p);
208*25da2beaSAndroid Build Coastguard Worker if (ret == T_SETUP_SKIP) {
209*25da2beaSAndroid Build Coastguard Worker pthread_mutex_unlock(&rd->mutex);
210*25da2beaSAndroid Build Coastguard Worker ret = 0;
211*25da2beaSAndroid Build Coastguard Worker goto err;
212*25da2beaSAndroid Build Coastguard Worker } else if (ret < 0) {
213*25da2beaSAndroid Build Coastguard Worker pthread_mutex_unlock(&rd->mutex);
214*25da2beaSAndroid Build Coastguard Worker goto err;
215*25da2beaSAndroid Build Coastguard Worker }
216*25da2beaSAndroid Build Coastguard Worker
217*25da2beaSAndroid Build Coastguard Worker sock = recv_prep(&ring, &iov, &sockout, rd);
218*25da2beaSAndroid Build Coastguard Worker if (ret) {
219*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "recv_prep failed: %d\n", ret);
220*25da2beaSAndroid Build Coastguard Worker goto err;
221*25da2beaSAndroid Build Coastguard Worker }
222*25da2beaSAndroid Build Coastguard Worker ret = do_recv(&ring);
223*25da2beaSAndroid Build Coastguard Worker if (!ret) {
224*25da2beaSAndroid Build Coastguard Worker int i;
225*25da2beaSAndroid Build Coastguard Worker
226*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < MAX_MSG; i++) {
227*25da2beaSAndroid Build Coastguard Worker if (buf[i] != i) {
228*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "found %d at %d\n", buf[i], i);
229*25da2beaSAndroid Build Coastguard Worker ret = 1;
230*25da2beaSAndroid Build Coastguard Worker break;
231*25da2beaSAndroid Build Coastguard Worker }
232*25da2beaSAndroid Build Coastguard Worker }
233*25da2beaSAndroid Build Coastguard Worker }
234*25da2beaSAndroid Build Coastguard Worker
235*25da2beaSAndroid Build Coastguard Worker shutdown(sockout, SHUT_RDWR);
236*25da2beaSAndroid Build Coastguard Worker shutdown(sock, SHUT_RDWR);
237*25da2beaSAndroid Build Coastguard Worker close(sock);
238*25da2beaSAndroid Build Coastguard Worker close(sockout);
239*25da2beaSAndroid Build Coastguard Worker io_uring_queue_exit(&ring);
240*25da2beaSAndroid Build Coastguard Worker err:
241*25da2beaSAndroid Build Coastguard Worker if (sock != -1) {
242*25da2beaSAndroid Build Coastguard Worker shutdown(sock, SHUT_RDWR);
243*25da2beaSAndroid Build Coastguard Worker close(sock);
244*25da2beaSAndroid Build Coastguard Worker }
245*25da2beaSAndroid Build Coastguard Worker if (sockout != -1) {
246*25da2beaSAndroid Build Coastguard Worker shutdown(sockout, SHUT_RDWR);
247*25da2beaSAndroid Build Coastguard Worker close(sockout);
248*25da2beaSAndroid Build Coastguard Worker }
249*25da2beaSAndroid Build Coastguard Worker return ret;
250*25da2beaSAndroid Build Coastguard Worker }
251*25da2beaSAndroid Build Coastguard Worker
recv_fn(void * data)252*25da2beaSAndroid Build Coastguard Worker static void *recv_fn(void *data)
253*25da2beaSAndroid Build Coastguard Worker {
254*25da2beaSAndroid Build Coastguard Worker struct recv_data *rd = data;
255*25da2beaSAndroid Build Coastguard Worker
256*25da2beaSAndroid Build Coastguard Worker if (rd->use_sync)
257*25da2beaSAndroid Build Coastguard Worker return (void *) (uintptr_t) recv_sync(rd);
258*25da2beaSAndroid Build Coastguard Worker
259*25da2beaSAndroid Build Coastguard Worker return (void *) (uintptr_t) recv_uring(rd);
260*25da2beaSAndroid Build Coastguard Worker }
261*25da2beaSAndroid Build Coastguard Worker
do_send(struct recv_data * rd)262*25da2beaSAndroid Build Coastguard Worker static int do_send(struct recv_data *rd)
263*25da2beaSAndroid Build Coastguard Worker {
264*25da2beaSAndroid Build Coastguard Worker struct sockaddr_in saddr;
265*25da2beaSAndroid Build Coastguard Worker struct io_uring ring;
266*25da2beaSAndroid Build Coastguard Worker struct io_uring_cqe *cqe;
267*25da2beaSAndroid Build Coastguard Worker struct io_uring_sqe *sqe;
268*25da2beaSAndroid Build Coastguard Worker int sockfd, ret, i;
269*25da2beaSAndroid Build Coastguard Worker struct iovec iov;
270*25da2beaSAndroid Build Coastguard Worker int *buf;
271*25da2beaSAndroid Build Coastguard Worker
272*25da2beaSAndroid Build Coastguard Worker ret = io_uring_queue_init(2, &ring, 0);
273*25da2beaSAndroid Build Coastguard Worker if (ret) {
274*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "queue init failed: %d\n", ret);
275*25da2beaSAndroid Build Coastguard Worker return 1;
276*25da2beaSAndroid Build Coastguard Worker }
277*25da2beaSAndroid Build Coastguard Worker
278*25da2beaSAndroid Build Coastguard Worker buf = malloc(MAX_MSG * sizeof(int));
279*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < MAX_MSG; i++)
280*25da2beaSAndroid Build Coastguard Worker buf[i] = i;
281*25da2beaSAndroid Build Coastguard Worker
282*25da2beaSAndroid Build Coastguard Worker memset(&saddr, 0, sizeof(saddr));
283*25da2beaSAndroid Build Coastguard Worker saddr.sin_family = AF_INET;
284*25da2beaSAndroid Build Coastguard Worker saddr.sin_port = htons(rd->port);
285*25da2beaSAndroid Build Coastguard Worker inet_pton(AF_INET, "127.0.0.1", &saddr.sin_addr);
286*25da2beaSAndroid Build Coastguard Worker
287*25da2beaSAndroid Build Coastguard Worker sockfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
288*25da2beaSAndroid Build Coastguard Worker if (sockfd < 0) {
289*25da2beaSAndroid Build Coastguard Worker perror("socket");
290*25da2beaSAndroid Build Coastguard Worker return 1;
291*25da2beaSAndroid Build Coastguard Worker }
292*25da2beaSAndroid Build Coastguard Worker
293*25da2beaSAndroid Build Coastguard Worker pthread_mutex_lock(&rd->mutex);
294*25da2beaSAndroid Build Coastguard Worker
295*25da2beaSAndroid Build Coastguard Worker ret = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));
296*25da2beaSAndroid Build Coastguard Worker if (ret < 0) {
297*25da2beaSAndroid Build Coastguard Worker perror("connect");
298*25da2beaSAndroid Build Coastguard Worker return 1;
299*25da2beaSAndroid Build Coastguard Worker }
300*25da2beaSAndroid Build Coastguard Worker
301*25da2beaSAndroid Build Coastguard Worker iov.iov_base = buf;
302*25da2beaSAndroid Build Coastguard Worker iov.iov_len = MAX_MSG * sizeof(int) / 2;
303*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < 2; i++) {
304*25da2beaSAndroid Build Coastguard Worker sqe = io_uring_get_sqe(&ring);
305*25da2beaSAndroid Build Coastguard Worker io_uring_prep_send(sqe, sockfd, iov.iov_base, iov.iov_len, 0);
306*25da2beaSAndroid Build Coastguard Worker sqe->user_data = 1;
307*25da2beaSAndroid Build Coastguard Worker
308*25da2beaSAndroid Build Coastguard Worker ret = io_uring_submit(&ring);
309*25da2beaSAndroid Build Coastguard Worker if (ret <= 0) {
310*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "submit failed: %d\n", ret);
311*25da2beaSAndroid Build Coastguard Worker goto err;
312*25da2beaSAndroid Build Coastguard Worker }
313*25da2beaSAndroid Build Coastguard Worker usleep(10000);
314*25da2beaSAndroid Build Coastguard Worker iov.iov_base += iov.iov_len;
315*25da2beaSAndroid Build Coastguard Worker }
316*25da2beaSAndroid Build Coastguard Worker
317*25da2beaSAndroid Build Coastguard Worker for (i = 0; i < 2; i++) {
318*25da2beaSAndroid Build Coastguard Worker ret = io_uring_wait_cqe(&ring, &cqe);
319*25da2beaSAndroid Build Coastguard Worker if (cqe->res == -EINVAL) {
320*25da2beaSAndroid Build Coastguard Worker fprintf(stdout, "send not supported, skipping\n");
321*25da2beaSAndroid Build Coastguard Worker close(sockfd);
322*25da2beaSAndroid Build Coastguard Worker return 0;
323*25da2beaSAndroid Build Coastguard Worker }
324*25da2beaSAndroid Build Coastguard Worker if (cqe->res != iov.iov_len) {
325*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "failed cqe: %d\n", cqe->res);
326*25da2beaSAndroid Build Coastguard Worker goto err;
327*25da2beaSAndroid Build Coastguard Worker }
328*25da2beaSAndroid Build Coastguard Worker io_uring_cqe_seen(&ring, cqe);
329*25da2beaSAndroid Build Coastguard Worker }
330*25da2beaSAndroid Build Coastguard Worker
331*25da2beaSAndroid Build Coastguard Worker shutdown(sockfd, SHUT_RDWR);
332*25da2beaSAndroid Build Coastguard Worker close(sockfd);
333*25da2beaSAndroid Build Coastguard Worker return 0;
334*25da2beaSAndroid Build Coastguard Worker err:
335*25da2beaSAndroid Build Coastguard Worker shutdown(sockfd, SHUT_RDWR);
336*25da2beaSAndroid Build Coastguard Worker close(sockfd);
337*25da2beaSAndroid Build Coastguard Worker return 1;
338*25da2beaSAndroid Build Coastguard Worker }
339*25da2beaSAndroid Build Coastguard Worker
test(int use_recvmsg,int use_sync)340*25da2beaSAndroid Build Coastguard Worker static int test(int use_recvmsg, int use_sync)
341*25da2beaSAndroid Build Coastguard Worker {
342*25da2beaSAndroid Build Coastguard Worker pthread_mutexattr_t attr;
343*25da2beaSAndroid Build Coastguard Worker pthread_t recv_thread;
344*25da2beaSAndroid Build Coastguard Worker struct recv_data rd;
345*25da2beaSAndroid Build Coastguard Worker int ret;
346*25da2beaSAndroid Build Coastguard Worker void *retval;
347*25da2beaSAndroid Build Coastguard Worker
348*25da2beaSAndroid Build Coastguard Worker pthread_mutexattr_init(&attr);
349*25da2beaSAndroid Build Coastguard Worker pthread_mutexattr_setpshared(&attr, 1);
350*25da2beaSAndroid Build Coastguard Worker pthread_mutex_init(&rd.mutex, &attr);
351*25da2beaSAndroid Build Coastguard Worker pthread_mutex_lock(&rd.mutex);
352*25da2beaSAndroid Build Coastguard Worker rd.use_recvmsg = use_recvmsg;
353*25da2beaSAndroid Build Coastguard Worker rd.use_sync = use_sync;
354*25da2beaSAndroid Build Coastguard Worker rd.port = port++;
355*25da2beaSAndroid Build Coastguard Worker
356*25da2beaSAndroid Build Coastguard Worker ret = pthread_create(&recv_thread, NULL, recv_fn, &rd);
357*25da2beaSAndroid Build Coastguard Worker if (ret) {
358*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "Thread create failed: %d\n", ret);
359*25da2beaSAndroid Build Coastguard Worker pthread_mutex_unlock(&rd.mutex);
360*25da2beaSAndroid Build Coastguard Worker return 1;
361*25da2beaSAndroid Build Coastguard Worker }
362*25da2beaSAndroid Build Coastguard Worker
363*25da2beaSAndroid Build Coastguard Worker do_send(&rd);
364*25da2beaSAndroid Build Coastguard Worker pthread_join(recv_thread, &retval);
365*25da2beaSAndroid Build Coastguard Worker return (intptr_t)retval;
366*25da2beaSAndroid Build Coastguard Worker }
367*25da2beaSAndroid Build Coastguard Worker
main(int argc,char * argv[])368*25da2beaSAndroid Build Coastguard Worker int main(int argc, char *argv[])
369*25da2beaSAndroid Build Coastguard Worker {
370*25da2beaSAndroid Build Coastguard Worker int ret;
371*25da2beaSAndroid Build Coastguard Worker
372*25da2beaSAndroid Build Coastguard Worker if (argc > 1)
373*25da2beaSAndroid Build Coastguard Worker return 0;
374*25da2beaSAndroid Build Coastguard Worker
375*25da2beaSAndroid Build Coastguard Worker ret = test(0, 0);
376*25da2beaSAndroid Build Coastguard Worker if (ret) {
377*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "test recv failed\n");
378*25da2beaSAndroid Build Coastguard Worker return ret;
379*25da2beaSAndroid Build Coastguard Worker }
380*25da2beaSAndroid Build Coastguard Worker
381*25da2beaSAndroid Build Coastguard Worker ret = test(1, 0);
382*25da2beaSAndroid Build Coastguard Worker if (ret) {
383*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "test recvmsg failed\n");
384*25da2beaSAndroid Build Coastguard Worker return ret;
385*25da2beaSAndroid Build Coastguard Worker }
386*25da2beaSAndroid Build Coastguard Worker
387*25da2beaSAndroid Build Coastguard Worker ret = test(0, 1);
388*25da2beaSAndroid Build Coastguard Worker if (ret) {
389*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "test sync recv failed\n");
390*25da2beaSAndroid Build Coastguard Worker return ret;
391*25da2beaSAndroid Build Coastguard Worker }
392*25da2beaSAndroid Build Coastguard Worker
393*25da2beaSAndroid Build Coastguard Worker ret = test(1, 1);
394*25da2beaSAndroid Build Coastguard Worker if (ret) {
395*25da2beaSAndroid Build Coastguard Worker fprintf(stderr, "test sync recvmsg failed\n");
396*25da2beaSAndroid Build Coastguard Worker return ret;
397*25da2beaSAndroid Build Coastguard Worker }
398*25da2beaSAndroid Build Coastguard Worker
399*25da2beaSAndroid Build Coastguard Worker return 0;
400*25da2beaSAndroid Build Coastguard Worker }
401