xref: /xnu-11215.61.5/tests/kqueue_fifo_18776047.c (revision 4f1223e81cd707a65cc109d0b8ad6653699da3c4)
1*4f1223e8SApple OSS Distributions /*
2*4f1223e8SApple OSS Distributions  * testname: kqueue_fifo
3*4f1223e8SApple OSS Distributions  */
4*4f1223e8SApple OSS Distributions 
5*4f1223e8SApple OSS Distributions #include <darwintest.h>
6*4f1223e8SApple OSS Distributions #include <fcntl.h>
7*4f1223e8SApple OSS Distributions #include <sys/event.h>
8*4f1223e8SApple OSS Distributions #include <sys/types.h>
9*4f1223e8SApple OSS Distributions #include <sys/stat.h>
10*4f1223e8SApple OSS Distributions #include <unistd.h>
11*4f1223e8SApple OSS Distributions #include <stdlib.h>
12*4f1223e8SApple OSS Distributions #include <errno.h>
13*4f1223e8SApple OSS Distributions 
14*4f1223e8SApple OSS Distributions #include <TargetConditionals.h>
15*4f1223e8SApple OSS Distributions 
16*4f1223e8SApple OSS Distributions T_GLOBAL_META(T_META_RUN_CONCURRENTLY(false));  // rdar://79464597
17*4f1223e8SApple OSS Distributions 
18*4f1223e8SApple OSS Distributions #define TMP_FILE_PATH "/tmp/test_kqueue_fifo_18776047"
19*4f1223e8SApple OSS Distributions 
20*4f1223e8SApple OSS Distributions #define READ_BUFFER_LEN 256
21*4f1223e8SApple OSS Distributions 
22*4f1223e8SApple OSS Distributions #if TARGET_OS_WATCH
23*4f1223e8SApple OSS Distributions #define TOTAL_ITERATIONS 5000
24*4f1223e8SApple OSS Distributions #else
25*4f1223e8SApple OSS Distributions #define TOTAL_ITERATIONS 10000
26*4f1223e8SApple OSS Distributions #endif
27*4f1223e8SApple OSS Distributions 
28*4f1223e8SApple OSS Distributions /* prototypes */
29*4f1223e8SApple OSS Distributions int write_some_data(int fd);
30*4f1223e8SApple OSS Distributions int read_data(int fd);
31*4f1223e8SApple OSS Distributions void create_fifo(const char * filepath);
32*4f1223e8SApple OSS Distributions void kevent_one_shot(int kq, int fd, int filter);
33*4f1223e8SApple OSS Distributions 
34*4f1223e8SApple OSS Distributions int
write_some_data(int fd)35*4f1223e8SApple OSS Distributions write_some_data(int fd)
36*4f1223e8SApple OSS Distributions {
37*4f1223e8SApple OSS Distributions 	int retval  = 0;
38*4f1223e8SApple OSS Distributions 	int count   = 0;
39*4f1223e8SApple OSS Distributions 	int len     = 5;
40*4f1223e8SApple OSS Distributions 	char * data = "ABCDE";
41*4f1223e8SApple OSS Distributions 	while (true) {
42*4f1223e8SApple OSS Distributions 		errno  = 0;
43*4f1223e8SApple OSS Distributions 		retval = (int)write(fd, data, (size_t)len);
44*4f1223e8SApple OSS Distributions 		if (retval < 0) {
45*4f1223e8SApple OSS Distributions 			if (errno == EAGAIN) {
46*4f1223e8SApple OSS Distributions 				if (len == 1) {
47*4f1223e8SApple OSS Distributions 					return count;
48*4f1223e8SApple OSS Distributions 				} else {
49*4f1223e8SApple OSS Distributions 					len--;
50*4f1223e8SApple OSS Distributions 				}
51*4f1223e8SApple OSS Distributions 			} else {
52*4f1223e8SApple OSS Distributions 				T_ASSERT_FAIL("write to fd %d of %s of len %d failed.", fd, data, len);
53*4f1223e8SApple OSS Distributions 				abort();
54*4f1223e8SApple OSS Distributions 			}
55*4f1223e8SApple OSS Distributions 		} else {
56*4f1223e8SApple OSS Distributions 			count += retval;
57*4f1223e8SApple OSS Distributions 		}
58*4f1223e8SApple OSS Distributions 	}
59*4f1223e8SApple OSS Distributions }
60*4f1223e8SApple OSS Distributions 
61*4f1223e8SApple OSS Distributions int
read_data(int fd)62*4f1223e8SApple OSS Distributions read_data(int fd)
63*4f1223e8SApple OSS Distributions {
64*4f1223e8SApple OSS Distributions 	int retval, count = 0;
65*4f1223e8SApple OSS Distributions 	char databuffer[READ_BUFFER_LEN];
66*4f1223e8SApple OSS Distributions 	while (true) {
67*4f1223e8SApple OSS Distributions 		errno  = 0;
68*4f1223e8SApple OSS Distributions 		retval = (int)read(fd, databuffer, READ_BUFFER_LEN);
69*4f1223e8SApple OSS Distributions 		if (retval < 0) {
70*4f1223e8SApple OSS Distributions 			if (errno == EAGAIN) {
71*4f1223e8SApple OSS Distributions 				return count;
72*4f1223e8SApple OSS Distributions 			} else {
73*4f1223e8SApple OSS Distributions 				T_ASSERT_FAIL("read from fd %d failed.", fd);
74*4f1223e8SApple OSS Distributions 				abort();
75*4f1223e8SApple OSS Distributions 			}
76*4f1223e8SApple OSS Distributions 		}
77*4f1223e8SApple OSS Distributions 		count += retval;
78*4f1223e8SApple OSS Distributions 	}
79*4f1223e8SApple OSS Distributions }
80*4f1223e8SApple OSS Distributions 
81*4f1223e8SApple OSS Distributions void
create_fifo(const char * filepath)82*4f1223e8SApple OSS Distributions create_fifo(const char * filepath)
83*4f1223e8SApple OSS Distributions {
84*4f1223e8SApple OSS Distributions 	struct stat f_stat;
85*4f1223e8SApple OSS Distributions 	int ret = 0;
86*4f1223e8SApple OSS Distributions 	errno   = 0;
87*4f1223e8SApple OSS Distributions 	ret = stat(filepath, &f_stat);
88*4f1223e8SApple OSS Distributions 	if (ret == 0) {
89*4f1223e8SApple OSS Distributions 		/* if file exists, make sure its a fifo */
90*4f1223e8SApple OSS Distributions 		T_ASSERT_TRUE(S_ISFIFO(f_stat.st_mode), "ensure %s is a fifo", filepath);
91*4f1223e8SApple OSS Distributions 	} else if (errno == ENOENT) {
92*4f1223e8SApple OSS Distributions 		ret = mkfifo(filepath, 0777);
93*4f1223e8SApple OSS Distributions 		T_ASSERT_POSIX_ZERO(ret, "creating a fifo at path %s", filepath);
94*4f1223e8SApple OSS Distributions 	} else {
95*4f1223e8SApple OSS Distributions 		T_ASSERT_FAIL("stat operation on %s", filepath);
96*4f1223e8SApple OSS Distributions 	}
97*4f1223e8SApple OSS Distributions }
98*4f1223e8SApple OSS Distributions 
99*4f1223e8SApple OSS Distributions void
kevent_one_shot(int kq,int fd,int filter)100*4f1223e8SApple OSS Distributions kevent_one_shot(int kq, int fd, int filter)
101*4f1223e8SApple OSS Distributions {
102*4f1223e8SApple OSS Distributions 	int retval             = 0;
103*4f1223e8SApple OSS Distributions 	struct timespec t_zero = {0, 0};
104*4f1223e8SApple OSS Distributions 	struct kevent kev[1];
105*4f1223e8SApple OSS Distributions 
106*4f1223e8SApple OSS Distributions 	T_QUIET;
107*4f1223e8SApple OSS Distributions 	T_ASSERT_GE(kq, 0, "ensure kq is valid");
108*4f1223e8SApple OSS Distributions 	T_LOG("kevent doing ONESHOT %s", filter == EVFILT_READ ? "read" : "write");
109*4f1223e8SApple OSS Distributions 
110*4f1223e8SApple OSS Distributions 	EV_SET(kev, fd, filter, EV_ADD | EV_ONESHOT, 0, 0, NULL);
111*4f1223e8SApple OSS Distributions 	retval = kevent(kq, kev, 1, NULL, 0, &t_zero);
112*4f1223e8SApple OSS Distributions 	T_QUIET;
113*4f1223e8SApple OSS Distributions 	T_ASSERT_POSIX_ZERO(retval, "ONESHOT kevent for fd %d, filter %d", fd, filter);
114*4f1223e8SApple OSS Distributions }
115*4f1223e8SApple OSS Distributions 
116*4f1223e8SApple OSS Distributions T_DECL(kqueue_fifo_18776047, "Tests kqueue, kevent for watching a fifo.", T_META_LTEPHASE(LTE_POSTINIT), T_META_TAG_VM_PREFERRED)
117*4f1223e8SApple OSS Distributions {
118*4f1223e8SApple OSS Distributions 	struct kevent kev[1];
119*4f1223e8SApple OSS Distributions 	int read_fd, write_fd, kq;
120*4f1223e8SApple OSS Distributions 	int retval         = 0;
121*4f1223e8SApple OSS Distributions 	int iter           = 0;
122*4f1223e8SApple OSS Distributions 	const char * fpath = TMP_FILE_PATH;
123*4f1223e8SApple OSS Distributions 	T_SETUPBEGIN;
124*4f1223e8SApple OSS Distributions 	create_fifo(fpath);
125*4f1223e8SApple OSS Distributions 
126*4f1223e8SApple OSS Distributions 	kq = kqueue();
127*4f1223e8SApple OSS Distributions 	T_ASSERT_GE(kq, 0, "create a kqueue");
128*4f1223e8SApple OSS Distributions 
129*4f1223e8SApple OSS Distributions 	read_fd = open(fpath, O_RDONLY | O_APPEND | O_NONBLOCK);
130*4f1223e8SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(read_fd, "opening read fd on fifo.");
131*4f1223e8SApple OSS Distributions 
132*4f1223e8SApple OSS Distributions 	write_fd = open(fpath, O_WRONLY | O_APPEND | O_NONBLOCK);
133*4f1223e8SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(write_fd, "opening write fd on fifo.");
134*4f1223e8SApple OSS Distributions 
135*4f1223e8SApple OSS Distributions 	T_SETUPEND;
136*4f1223e8SApple OSS Distributions 
137*4f1223e8SApple OSS Distributions 	kevent_one_shot(kq, write_fd, EVFILT_WRITE);
138*4f1223e8SApple OSS Distributions 	kevent_one_shot(kq, read_fd, EVFILT_READ);
139*4f1223e8SApple OSS Distributions 
140*4f1223e8SApple OSS Distributions 	while (iter++ < TOTAL_ITERATIONS) {
141*4f1223e8SApple OSS Distributions 		retval = kevent(kq, NULL, 0, kev, 1, NULL);
142*4f1223e8SApple OSS Distributions 		T_QUIET;
143*4f1223e8SApple OSS Distributions 		T_ASSERT_GE(retval, 0, "kevent on kq %d", kq);
144*4f1223e8SApple OSS Distributions 
145*4f1223e8SApple OSS Distributions 		if (kev[0].ident == (uintptr_t)write_fd) {
146*4f1223e8SApple OSS Distributions 			retval = write_some_data(write_fd);
147*4f1223e8SApple OSS Distributions 			T_LOG("writer ready iter: %d wrote %d bytes", iter, retval);
148*4f1223e8SApple OSS Distributions 			kevent_one_shot(kq, write_fd, EVFILT_WRITE);
149*4f1223e8SApple OSS Distributions 		} else if (kev[0].ident == (uintptr_t)read_fd) {
150*4f1223e8SApple OSS Distributions 			retval = read_data(read_fd);
151*4f1223e8SApple OSS Distributions 			T_LOG("reader ready iter: %d read %d bytes", iter, retval);
152*4f1223e8SApple OSS Distributions 			kevent_one_shot(kq, read_fd, EVFILT_READ);
153*4f1223e8SApple OSS Distributions 		}
154*4f1223e8SApple OSS Distributions 	}
155*4f1223e8SApple OSS Distributions 	T_PASS("kqueue_fifo_18776047 PASSED");
156*4f1223e8SApple OSS Distributions }
157