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