• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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