• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Description: test massive amounts of poll with cancel
4  *
5  */
6 #include <errno.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <inttypes.h>
12 #include <sys/poll.h>
13 #include <sys/wait.h>
14 #include <sys/signal.h>
15 
16 #include "liburing.h"
17 
18 #define POLL_COUNT	30000
19 
20 static void *sqe_index[POLL_COUNT];
21 
reap_events(struct io_uring * ring,unsigned nr_events,int nowait)22 static int reap_events(struct io_uring *ring, unsigned nr_events, int nowait)
23 {
24 	struct io_uring_cqe *cqe;
25 	int i, ret = 0;
26 
27 	for (i = 0; i < nr_events; i++) {
28 		if (!i && !nowait)
29 			ret = io_uring_wait_cqe(ring, &cqe);
30 		else
31 			ret = io_uring_peek_cqe(ring, &cqe);
32 		if (ret) {
33 			if (ret != -EAGAIN)
34 				fprintf(stderr, "cqe peek failed: %d\n", ret);
35 			break;
36 		}
37 		io_uring_cqe_seen(ring, cqe);
38 	}
39 
40 	return i ? i : ret;
41 }
42 
del_polls(struct io_uring * ring,int fd,int nr)43 static int del_polls(struct io_uring *ring, int fd, int nr)
44 {
45 	int batch, i, ret;
46 	struct io_uring_sqe *sqe;
47 
48 	while (nr) {
49 		batch = 1024;
50 		if (batch > nr)
51 			batch = nr;
52 
53 		for (i = 0; i < batch; i++) {
54 			void *data;
55 
56 			sqe = io_uring_get_sqe(ring);
57 			data = sqe_index[lrand48() % nr];
58 			io_uring_prep_poll_remove(sqe, data);
59 		}
60 
61 		ret = io_uring_submit(ring);
62 		if (ret != batch) {
63 			fprintf(stderr, "%s: failed submit, %d\n", __FUNCTION__, ret);
64 			return 1;
65 		}
66 		nr -= batch;
67 		ret = reap_events(ring, 2 * batch, 0);
68 	}
69 	return 0;
70 }
71 
add_polls(struct io_uring * ring,int fd,int nr)72 static int add_polls(struct io_uring *ring, int fd, int nr)
73 {
74 	int pending, batch, i, count, ret;
75 	struct io_uring_sqe *sqe;
76 
77 	pending = count = 0;
78 	while (nr) {
79 		batch = 1024;
80 		if (batch > nr)
81 			batch = nr;
82 
83 		for (i = 0; i < batch; i++) {
84 			sqe = io_uring_get_sqe(ring);
85 			io_uring_prep_poll_add(sqe, fd, POLLIN);
86 			sqe_index[count++] = sqe;
87 			sqe->user_data = (unsigned long) sqe;
88 		}
89 
90 		ret = io_uring_submit(ring);
91 		if (ret != batch) {
92 			fprintf(stderr, "%s: failed submit, %d\n", __FUNCTION__, ret);
93 			return 1;
94 		}
95 		nr -= batch;
96 		pending += batch;
97 		reap_events(ring, batch, 1);
98 	}
99 	return 0;
100 }
101 
main(int argc,char * argv[])102 int main(int argc, char *argv[])
103 {
104 	struct io_uring ring;
105 	struct io_uring_params p = { };
106 	int pipe1[2];
107 	int ret;
108 
109 	if (argc > 1)
110 		return 0;
111 
112 	if (pipe(pipe1) != 0) {
113 		perror("pipe");
114 		return 1;
115 	}
116 
117 	p.flags = IORING_SETUP_CQSIZE;
118 	p.cq_entries = 16384;
119 	ret = io_uring_queue_init_params(1024, &ring, &p);
120 	if (ret) {
121 		if (ret == -EINVAL) {
122 			fprintf(stdout, "No CQSIZE, trying without\n");
123 			ret = io_uring_queue_init(1024, &ring, 0);
124 			if (ret) {
125 				fprintf(stderr, "ring setup failed: %d\n", ret);
126 				return 1;
127 			}
128 		}
129 	}
130 
131 	add_polls(&ring, pipe1[0], 30000);
132 #if 0
133 	usleep(1000);
134 #endif
135 	del_polls(&ring, pipe1[0], 30000);
136 
137 	io_uring_queue_exit(&ring);
138 	return 0;
139 }
140