1 /* SPDX-License-Identifier: MIT */
2 /*
3 * Description: test pollfree wakeups
4 */
5 #include <fcntl.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <sys/stat.h>
9 #include <sys/types.h>
10 #include <sys/signalfd.h>
11 #include <unistd.h>
12 #include <stdlib.h>
13
14 #include "liburing.h"
15 #include "helpers.h"
16
17 static int no_signalfd;
18
child(int flags)19 static int child(int flags)
20 {
21 struct io_uring_sqe *sqe;
22 struct io_uring ring;
23 struct signalfd_siginfo si;
24 static unsigned long index;
25 sigset_t mask;
26 int ret, fd;
27
28 ret = io_uring_queue_init(4, &ring, flags);
29 if (ret) {
30 if (ret == -EINVAL)
31 return 0;
32 fprintf(stderr, "queue init failed %d\n", ret);
33 return ret;
34 }
35
36 sigemptyset(&mask);
37 sigaddset(&mask, SIGINT);
38
39 fd = signalfd(-1, &mask, SFD_NONBLOCK);
40 if (fd < 0) {
41 no_signalfd = 1;
42 perror("signalfd");
43 return 1;
44 }
45
46 sqe = io_uring_get_sqe(&ring);
47 io_uring_prep_read(sqe, fd, &si, sizeof(si), 0);
48 sqe->user_data = 1;
49 io_uring_submit(&ring);
50
51 sqe = io_uring_get_sqe(&ring);
52 io_uring_prep_read(sqe, fd, &si, sizeof(si), 0);
53 sqe->user_data = 2;
54 sqe->flags |= IOSQE_ASYNC;
55 io_uring_submit(&ring);
56
57 sqe = io_uring_get_sqe(&ring);
58 io_uring_prep_read(sqe, fd, &si, sizeof(si), 0);
59 sqe->user_data = 3;
60 io_uring_submit(&ring);
61
62 if (!(++index & 7))
63 usleep(100);
64
65 return 0;
66 }
67
run_test(int flags)68 static int run_test(int flags)
69 {
70 pid_t pid;
71 int ret;
72
73 pid = fork();
74 if (pid < 0) {
75 perror("fork");
76 return 1;
77 } else if (!pid) {
78 ret = child(flags);
79 _exit(ret);
80 } else {
81 int wstatus;
82 pid_t childpid;
83
84 do {
85 childpid = waitpid(pid, &wstatus, 0);
86 } while (childpid == (pid_t) -1 && (errno == EINTR));
87
88 if (errno == ECHILD)
89 wstatus = 0;
90 return wstatus;
91 }
92 }
93
test(int flags)94 static int test(int flags)
95 {
96 struct timeval start;
97 int ret;
98
99 gettimeofday(&start, NULL);
100 do {
101 ret = run_test(flags);
102 if (ret) {
103 fprintf(stderr, "test failed with flags %x\n", flags);
104 return 1;
105 }
106 if (no_signalfd)
107 break;
108 } while (mtime_since_now(&start) < 2500);
109
110 return 0;
111 }
112
main(int argc,char * argv[])113 int main(int argc, char *argv[])
114 {
115 int ret;
116
117 if (argc > 1)
118 return T_EXIT_SKIP;
119
120 ret = test(0);
121 if (ret) {
122 fprintf(stderr, "test 0 failed: %d\n", ret);
123 return ret;
124 }
125
126 if (no_signalfd)
127 return T_EXIT_SKIP;
128
129 ret = test(IORING_SETUP_SQPOLL);
130 if (ret) {
131 fprintf(stderr, "test SQPOLL failed: %d\n", ret);
132 return ret;
133 }
134
135 ret = test(IORING_SETUP_COOP_TASKRUN);
136 if (ret) {
137 fprintf(stderr, "test COOP failed: %d\n", ret);
138 return ret;
139 }
140
141 ret = test(IORING_SETUP_DEFER_TASKRUN|IORING_SETUP_SINGLE_ISSUER);
142 if (ret) {
143 fprintf(stderr, "test DEFER failed: %d\n", ret);
144 return ret;
145 }
146
147 return T_EXIT_PASS;
148 }
149