blob: 723a353cd63f158f88d9ea3c350463fa4dbc006c [file] [log] [blame]
Jens Axboee5024352020-02-11 20:34:12 -07001/* SPDX-License-Identifier: MIT */
Jens Axboe3e4deca2019-11-22 07:23:56 -07002/*
3 * Description: test many files being polled for
4 *
5 */
6#include <errno.h>
7#include <stdio.h>
8#include <unistd.h>
9#include <stdlib.h>
10#include <string.h>
11#include <signal.h>
12#include <sys/poll.h>
13#include <sys/resource.h>
14#include <fcntl.h>
15
16#include "liburing.h"
17
18#define NFILES 5000
19#define BATCH 500
20#define NLOOPS 1000
21
22#define RING_SIZE 512
23
24struct p {
25 int fd[2];
26 int triggered;
27};
28
29static struct p p[NFILES];
30
31static int arm_poll(struct io_uring *ring, int off)
32{
33 struct io_uring_sqe *sqe;
34
35 sqe = io_uring_get_sqe(ring);
36 if (!sqe) {
37 fprintf(stderr, "failed getting sqe\n");
38 return 1;
39 }
40
41 io_uring_prep_poll_add(sqe, p[off].fd[0], POLLIN);
42 sqe->user_data = off;
43 return 0;
44}
45
46static int reap_polls(struct io_uring *ring)
47{
48 struct io_uring_cqe *cqe;
49 int i, ret, off;
50 char c;
51
52 for (i = 0; i < BATCH; i++) {
53 ret = io_uring_wait_cqe(ring, &cqe);
54 if (ret) {
55 fprintf(stderr, "wait cqe %d\n", ret);
56 return ret;
57 }
58 off = cqe->user_data;
59 p[off].triggered = 0;
60 ret = read(p[off].fd[0], &c, 1);
61 if (ret != 1) {
62 fprintf(stderr, "read got %d/%d\n", ret, errno);
63 break;
64 }
65 if (arm_poll(ring, off))
66 break;
67 io_uring_cqe_seen(ring, cqe);
68 }
69
70 if (i != BATCH) {
71 fprintf(stderr, "gave up at %d\n", i);
72 return 1;
73 }
74
75 ret = io_uring_submit(ring);
76 if (ret != BATCH) {
77 fprintf(stderr, "submitted %d, %d\n", ret, BATCH);
78 return 1;
79 }
80
81 return 0;
82}
83
84static int trigger_polls(void)
85{
86 char c = 89;
87 int i, ret;
88
89 for (i = 0; i < BATCH; i++) {
90 int off;
91
92 do {
93 off = rand() % NFILES;
94 if (!p[off].triggered)
95 break;
96 } while (1);
97
98 p[off].triggered = 1;
99 ret = write(p[off].fd[1], &c, 1);
100 if (ret != 1) {
101 fprintf(stderr, "write got %d/%d\n", ret, errno);
102 return 1;
103 }
104 }
105
106 return 0;
107}
108
109static int arm_polls(struct io_uring *ring)
110{
111 int ret, to_arm = NFILES, i, off;
112
113 off = 0;
114 while (to_arm) {
115 int this_arm;
116
117 this_arm = to_arm;
118 if (this_arm > RING_SIZE)
119 this_arm = RING_SIZE;
120
121 for (i = 0; i < this_arm; i++) {
122 if (arm_poll(ring, off)) {
Jens Axboea8dc4972020-02-01 09:58:07 -0700123 fprintf(stderr, "arm failed at %d\n", off);
Jens Axboe3e4deca2019-11-22 07:23:56 -0700124 return 1;
125 }
126 off++;
127 }
128
129 ret = io_uring_submit(ring);
130 if (ret != this_arm) {
Jens Axboea8dc4972020-02-01 09:58:07 -0700131 fprintf(stderr, "submitted %d, %d\n", ret, this_arm);
Jens Axboe3e4deca2019-11-22 07:23:56 -0700132 return 1;
133 }
134 to_arm -= this_arm;
135 }
136
137 return 0;
138}
139
140int main(int argc, char *argv[])
141{
142 struct io_uring ring;
143 struct rlimit rlim;
144 int i, ret;
145
Jens Axboea2141fc2020-05-19 17:36:19 -0600146 if (argc > 1)
147 return 0;
148
Jens Axboe3e4deca2019-11-22 07:23:56 -0700149 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
150 perror("getrlimit");
151 goto err_noring;
152 }
153
154 if (rlim.rlim_cur < (2 * NFILES + 5)) {
155 rlim.rlim_cur = (2 * NFILES + 5);
156 rlim.rlim_max = rlim.rlim_cur;
157 if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
158 if (errno == EPERM)
159 goto err_nofail;
160 perror("setrlimit");
161 goto err_noring;
162 }
163 }
164
165 for (i = 0; i < NFILES; i++) {
166 if (pipe(p[i].fd) < 0) {
167 perror("pipe");
168 goto err_noring;
169 }
170 }
171
172 if (io_uring_queue_init(RING_SIZE, &ring, 0)) {
173 fprintf(stderr, "failed ring init\n");
174 goto err_noring;
175 }
176
177 if (arm_polls(&ring))
178 goto err;
179
180 for (i = 0; i < NLOOPS; i++) {
181 trigger_polls();
182 ret = reap_polls(&ring);
183 if (ret)
184 goto err;
185 }
186
187 io_uring_queue_exit(&ring);
188 return 0;
189err:
190 io_uring_queue_exit(&ring);
191err_noring:
192 fprintf(stderr, "poll-many failed\n");
193 return 1;
194err_nofail:
195 fprintf(stderr, "poll-many: not enough files available (and not root), "
196 "skipped\n");
197 return 0;
198}