• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Description: test disable/enable notifications through eventfd
4  *
5  */
6 #include <errno.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <fcntl.h>
12 #include <poll.h>
13 #include <sys/eventfd.h>
14 
15 #include "liburing.h"
16 #include "helpers.h"
17 
test(bool defer)18 static int test(bool defer)
19 {
20 	struct io_uring_params p = {};
21 	struct io_uring_sqe *sqe;
22 	struct io_uring_cqe *cqe;
23 	struct io_uring ring;
24 	uint64_t ptr;
25 	struct iovec vec = {
26 		.iov_base = &ptr,
27 		.iov_len = sizeof(ptr)
28 	};
29 	int ret, evfd, i;
30 
31 	if (defer)
32 		p.flags |= IORING_SETUP_SINGLE_ISSUER |
33 			   IORING_SETUP_DEFER_TASKRUN;
34 
35 	ret = io_uring_queue_init_params(64, &ring, &p);
36 	if (ret) {
37 		fprintf(stderr, "ring setup failed: %d\n", ret);
38 		return T_EXIT_FAIL;
39 	}
40 
41 	evfd = eventfd(0, EFD_CLOEXEC);
42 	if (evfd < 0) {
43 		perror("eventfd");
44 		return T_EXIT_FAIL;
45 	}
46 
47 	ret = io_uring_register_eventfd(&ring, evfd);
48 	if (ret) {
49 		fprintf(stderr, "failed to register evfd: %d\n", ret);
50 		return T_EXIT_FAIL;
51 	}
52 
53 	if (!io_uring_cq_eventfd_enabled(&ring)) {
54 		fprintf(stderr, "eventfd disabled\n");
55 		return T_EXIT_FAIL;
56 	}
57 
58 	ret = io_uring_cq_eventfd_toggle(&ring, false);
59 	if (ret) {
60 		fprintf(stdout, "Skipping, CQ flags not available!\n");
61 		return T_EXIT_SKIP;
62 	}
63 
64 	sqe = io_uring_get_sqe(&ring);
65 	io_uring_prep_readv(sqe, evfd, &vec, 1, 0);
66 	sqe->user_data = 1;
67 
68 	ret = io_uring_submit(&ring);
69 	if (ret != 1) {
70 		fprintf(stderr, "submit: %d\n", ret);
71 		return T_EXIT_FAIL;
72 	}
73 
74 	for (i = 0; i < 63; i++) {
75 		sqe = io_uring_get_sqe(&ring);
76 		io_uring_prep_nop(sqe);
77 		sqe->user_data = 2;
78 	}
79 
80 	ret = io_uring_submit(&ring);
81 	if (ret != 63) {
82 		fprintf(stderr, "submit: %d\n", ret);
83 		return T_EXIT_FAIL;
84 	}
85 
86 	for (i = 0; i < 63; i++) {
87 		ret = io_uring_wait_cqe(&ring, &cqe);
88 		if (ret) {
89 			fprintf(stderr, "wait: %d\n", ret);
90 			return T_EXIT_FAIL;
91 		}
92 
93 		switch (cqe->user_data) {
94 		case 1: /* eventfd */
95 			fprintf(stderr, "eventfd unexpected: %d\n", (int)ptr);
96 			return T_EXIT_FAIL;
97 		case 2:
98 			if (cqe->res) {
99 				fprintf(stderr, "nop: %d\n", cqe->res);
100 				return T_EXIT_FAIL;
101 			}
102 			break;
103 		}
104 		io_uring_cqe_seen(&ring, cqe);
105 	}
106 
107 	ret = io_uring_cq_eventfd_toggle(&ring, true);
108 	if (ret) {
109 		fprintf(stderr, "io_uring_cq_eventfd_toggle: %d\n", ret);
110 		return T_EXIT_FAIL;
111 	}
112 
113 	sqe = io_uring_get_sqe(&ring);
114 	io_uring_prep_nop(sqe);
115 	sqe->user_data = 2;
116 
117 	ret = io_uring_submit(&ring);
118 	if (ret != 1) {
119 		fprintf(stderr, "submit: %d\n", ret);
120 		return T_EXIT_FAIL;
121 	}
122 
123 	for (i = 0; i < 2; i++) {
124 		ret = io_uring_wait_cqe(&ring, &cqe);
125 		if (ret) {
126 			fprintf(stderr, "wait: %d\n", ret);
127 			return T_EXIT_FAIL;
128 		}
129 
130 		switch (cqe->user_data) {
131 		case 1: /* eventfd */
132 			if (cqe->res != sizeof(ptr)) {
133 				fprintf(stderr, "read res: %d\n", cqe->res);
134 				return T_EXIT_FAIL;
135 			}
136 
137 			if (ptr != 1) {
138 				fprintf(stderr, "eventfd: %d\n", (int)ptr);
139 				return T_EXIT_FAIL;
140 			}
141 			break;
142 		case 2:
143 			if (cqe->res) {
144 				fprintf(stderr, "nop: %d\n", cqe->res);
145 				return T_EXIT_FAIL;
146 			}
147 			break;
148 		}
149 		io_uring_cqe_seen(&ring, cqe);
150 	}
151 
152 	io_uring_queue_exit(&ring);
153 	close(evfd);
154 	return T_EXIT_PASS;
155 }
156 
main(int argc,char * argv[])157 int main(int argc, char *argv[])
158 {
159 	int ret;
160 
161 	if (argc > 1)
162 		return T_EXIT_SKIP;
163 
164 	ret = test(false);
165 	if (ret != T_EXIT_PASS) {
166 		fprintf(stderr, "%s: test(false) failed\n", argv[0]);
167 		return ret;
168 	}
169 
170 	if (t_probe_defer_taskrun()) {
171 		ret = test(true);
172 		if (ret != T_EXIT_PASS) {
173 			fprintf(stderr, "%s: test(true) failed\n", argv[0]);
174 			return ret;
175 		}
176 	}
177 
178 	return ret;
179 }
180