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