xref: /titanic_52/usr/src/lib/libc/port/sys/epoll.c (revision a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6)
1*a5eb7107SBryan Cantrill /*
2*a5eb7107SBryan Cantrill  * This file and its contents are supplied under the terms of the
3*a5eb7107SBryan Cantrill  * Common Development and Distribution License ("CDDL"), version 1.0.
4*a5eb7107SBryan Cantrill  * You may only use this file in accordance with the terms of version
5*a5eb7107SBryan Cantrill  * 1.0 of the CDDL.
6*a5eb7107SBryan Cantrill  *
7*a5eb7107SBryan Cantrill  * A full copy of the text of the CDDL should have accompanied this
8*a5eb7107SBryan Cantrill  * source.  A copy of the CDDL is also available via the Internet at
9*a5eb7107SBryan Cantrill  * http://www.illumos.org/license/CDDL.
10*a5eb7107SBryan Cantrill  */
11*a5eb7107SBryan Cantrill 
12*a5eb7107SBryan Cantrill /*
13*a5eb7107SBryan Cantrill  * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
14*a5eb7107SBryan Cantrill  */
15*a5eb7107SBryan Cantrill 
16*a5eb7107SBryan Cantrill #include <sys/types.h>
17*a5eb7107SBryan Cantrill #include <sys/epoll.h>
18*a5eb7107SBryan Cantrill #include <sys/devpoll.h>
19*a5eb7107SBryan Cantrill #include <unistd.h>
20*a5eb7107SBryan Cantrill #include <errno.h>
21*a5eb7107SBryan Cantrill #include <fcntl.h>
22*a5eb7107SBryan Cantrill #include <poll.h>
23*a5eb7107SBryan Cantrill 
24*a5eb7107SBryan Cantrill /*
25*a5eb7107SBryan Cantrill  * Events that match their epoll(7) equivalents.
26*a5eb7107SBryan Cantrill  */
27*a5eb7107SBryan Cantrill #if EPOLLIN != POLLIN
28*a5eb7107SBryan Cantrill #error value of EPOLLIN does not match value of POLLIN
29*a5eb7107SBryan Cantrill #endif
30*a5eb7107SBryan Cantrill 
31*a5eb7107SBryan Cantrill #if EPOLLPRI != POLLPRI
32*a5eb7107SBryan Cantrill #error value of EPOLLPRI does not match value of POLLPRI
33*a5eb7107SBryan Cantrill #endif
34*a5eb7107SBryan Cantrill 
35*a5eb7107SBryan Cantrill #if EPOLLOUT != POLLOUT
36*a5eb7107SBryan Cantrill #error value of EPOLLOUT does not match value of POLLOUT
37*a5eb7107SBryan Cantrill #endif
38*a5eb7107SBryan Cantrill 
39*a5eb7107SBryan Cantrill #if EPOLLRDNORM != POLLRDNORM
40*a5eb7107SBryan Cantrill #error value of EPOLLRDNORM does not match value of POLLRDNORM
41*a5eb7107SBryan Cantrill #endif
42*a5eb7107SBryan Cantrill 
43*a5eb7107SBryan Cantrill #if EPOLLRDBAND != POLLRDBAND
44*a5eb7107SBryan Cantrill #error value of EPOLLRDBAND does not match value of POLLRDBAND
45*a5eb7107SBryan Cantrill #endif
46*a5eb7107SBryan Cantrill 
47*a5eb7107SBryan Cantrill #if EPOLLERR != POLLERR
48*a5eb7107SBryan Cantrill #error value of EPOLLERR does not match value of POLLERR
49*a5eb7107SBryan Cantrill #endif
50*a5eb7107SBryan Cantrill 
51*a5eb7107SBryan Cantrill #if EPOLLHUP != POLLHUP
52*a5eb7107SBryan Cantrill #error value of EPOLLHUP does not match value of POLLHUP
53*a5eb7107SBryan Cantrill #endif
54*a5eb7107SBryan Cantrill 
55*a5eb7107SBryan Cantrill /*
56*a5eb7107SBryan Cantrill  * Events that we ignore entirely.  They can be set in events, but they will
57*a5eb7107SBryan Cantrill  * never be returned.
58*a5eb7107SBryan Cantrill  */
59*a5eb7107SBryan Cantrill #define	EPOLLIGNORED 	(EPOLLMSG | EPOLLWAKEUP)
60*a5eb7107SBryan Cantrill 
61*a5eb7107SBryan Cantrill /*
62*a5eb7107SBryan Cantrill  * Events that we swizzle into other bit positions.
63*a5eb7107SBryan Cantrill  */
64*a5eb7107SBryan Cantrill #define	EPOLLSWIZZLED	\
65*a5eb7107SBryan Cantrill 	(EPOLLRDHUP | EPOLLONESHOT | EPOLLET | EPOLLWRBAND | EPOLLWRNORM)
66*a5eb7107SBryan Cantrill 
67*a5eb7107SBryan Cantrill int
68*a5eb7107SBryan Cantrill epoll_create(int size)
69*a5eb7107SBryan Cantrill {
70*a5eb7107SBryan Cantrill 	int fd;
71*a5eb7107SBryan Cantrill 
72*a5eb7107SBryan Cantrill 	/*
73*a5eb7107SBryan Cantrill 	 * From the epoll_create() man page:  "Since Linux 2.6.8, the size
74*a5eb7107SBryan Cantrill 	 * argument is ignored, but must be greater than zero."  You keep using
75*a5eb7107SBryan Cantrill 	 * that word "ignored"...
76*a5eb7107SBryan Cantrill 	 */
77*a5eb7107SBryan Cantrill 	if (size <= 0) {
78*a5eb7107SBryan Cantrill 		errno = EINVAL;
79*a5eb7107SBryan Cantrill 		return (-1);
80*a5eb7107SBryan Cantrill 	}
81*a5eb7107SBryan Cantrill 
82*a5eb7107SBryan Cantrill 	if ((fd = open("/dev/poll", O_RDWR)) == -1)
83*a5eb7107SBryan Cantrill 		return (-1);
84*a5eb7107SBryan Cantrill 
85*a5eb7107SBryan Cantrill 	if (ioctl(fd, DP_EPOLLCOMPAT, 0) == -1) {
86*a5eb7107SBryan Cantrill 		(void) close(fd);
87*a5eb7107SBryan Cantrill 		return (-1);
88*a5eb7107SBryan Cantrill 	}
89*a5eb7107SBryan Cantrill 
90*a5eb7107SBryan Cantrill 	return (fd);
91*a5eb7107SBryan Cantrill }
92*a5eb7107SBryan Cantrill 
93*a5eb7107SBryan Cantrill int
94*a5eb7107SBryan Cantrill epoll_create1(int flags)
95*a5eb7107SBryan Cantrill {
96*a5eb7107SBryan Cantrill 	int fd, oflags = O_RDWR;
97*a5eb7107SBryan Cantrill 
98*a5eb7107SBryan Cantrill 	if (flags & EPOLL_CLOEXEC)
99*a5eb7107SBryan Cantrill 		oflags |= O_CLOEXEC;
100*a5eb7107SBryan Cantrill 
101*a5eb7107SBryan Cantrill 	if ((fd = open("/dev/poll", oflags)) == -1)
102*a5eb7107SBryan Cantrill 		return (-1);
103*a5eb7107SBryan Cantrill 
104*a5eb7107SBryan Cantrill 	if (ioctl(fd, DP_EPOLLCOMPAT, 0) == -1) {
105*a5eb7107SBryan Cantrill 		(void) close(fd);
106*a5eb7107SBryan Cantrill 		return (-1);
107*a5eb7107SBryan Cantrill 	}
108*a5eb7107SBryan Cantrill 
109*a5eb7107SBryan Cantrill 	return (fd);
110*a5eb7107SBryan Cantrill }
111*a5eb7107SBryan Cantrill 
112*a5eb7107SBryan Cantrill int
113*a5eb7107SBryan Cantrill epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
114*a5eb7107SBryan Cantrill {
115*a5eb7107SBryan Cantrill 	dvpoll_epollfd_t epoll[2];
116*a5eb7107SBryan Cantrill 	uint32_t events, ev = 0;
117*a5eb7107SBryan Cantrill 	int i = 0;
118*a5eb7107SBryan Cantrill 
119*a5eb7107SBryan Cantrill 	epoll[i].dpep_pollfd.fd = fd;
120*a5eb7107SBryan Cantrill 
121*a5eb7107SBryan Cantrill 	switch (op) {
122*a5eb7107SBryan Cantrill 	case EPOLL_CTL_DEL:
123*a5eb7107SBryan Cantrill 		ev = POLLREMOVE;
124*a5eb7107SBryan Cantrill 		break;
125*a5eb7107SBryan Cantrill 
126*a5eb7107SBryan Cantrill 	case EPOLL_CTL_MOD:
127*a5eb7107SBryan Cantrill 		/*
128*a5eb7107SBryan Cantrill 		 * In the modify case, we pass down two events:  one to
129*a5eb7107SBryan Cantrill 		 * remove the event and another to add it back.
130*a5eb7107SBryan Cantrill 		 */
131*a5eb7107SBryan Cantrill 		epoll[i++].dpep_pollfd.events = POLLREMOVE;
132*a5eb7107SBryan Cantrill 		epoll[i].dpep_pollfd.fd = fd;
133*a5eb7107SBryan Cantrill 		/* FALLTHROUGH */
134*a5eb7107SBryan Cantrill 
135*a5eb7107SBryan Cantrill 	case EPOLL_CTL_ADD:
136*a5eb7107SBryan Cantrill 		/*
137*a5eb7107SBryan Cantrill 		 * Mask off the events that we ignore, and then swizzle the
138*a5eb7107SBryan Cantrill 		 * events for which our values differ from their epoll(7)
139*a5eb7107SBryan Cantrill 		 * equivalents.
140*a5eb7107SBryan Cantrill 		 */
141*a5eb7107SBryan Cantrill 		events = event->events;
142*a5eb7107SBryan Cantrill 		ev = events & ~(EPOLLIGNORED | EPOLLSWIZZLED);
143*a5eb7107SBryan Cantrill 
144*a5eb7107SBryan Cantrill 		if (events & EPOLLRDHUP)
145*a5eb7107SBryan Cantrill 			ev |= POLLRDHUP;
146*a5eb7107SBryan Cantrill 
147*a5eb7107SBryan Cantrill 		if (events & EPOLLET)
148*a5eb7107SBryan Cantrill 			ev |= POLLET;
149*a5eb7107SBryan Cantrill 
150*a5eb7107SBryan Cantrill 		if (events & EPOLLONESHOT)
151*a5eb7107SBryan Cantrill 			ev |= POLLONESHOT;
152*a5eb7107SBryan Cantrill 
153*a5eb7107SBryan Cantrill 		if (events & EPOLLWRNORM)
154*a5eb7107SBryan Cantrill 			ev |= POLLWRNORM;
155*a5eb7107SBryan Cantrill 
156*a5eb7107SBryan Cantrill 		if (events & EPOLLWRBAND)
157*a5eb7107SBryan Cantrill 			ev |= POLLWRBAND;
158*a5eb7107SBryan Cantrill 
159*a5eb7107SBryan Cantrill 		epoll[i].dpep_data = event->data.u64;
160*a5eb7107SBryan Cantrill 		break;
161*a5eb7107SBryan Cantrill 
162*a5eb7107SBryan Cantrill 	default:
163*a5eb7107SBryan Cantrill 		errno = EOPNOTSUPP;
164*a5eb7107SBryan Cantrill 		return (-1);
165*a5eb7107SBryan Cantrill 	}
166*a5eb7107SBryan Cantrill 
167*a5eb7107SBryan Cantrill 	epoll[i].dpep_pollfd.events = ev;
168*a5eb7107SBryan Cantrill 
169*a5eb7107SBryan Cantrill 	return (write(epfd, epoll, sizeof (epoll[0]) * (i + 1)) == -1 ? -1 : 0);
170*a5eb7107SBryan Cantrill }
171*a5eb7107SBryan Cantrill 
172*a5eb7107SBryan Cantrill int
173*a5eb7107SBryan Cantrill epoll_wait(int epfd, struct epoll_event *events,
174*a5eb7107SBryan Cantrill     int maxevents, int timeout)
175*a5eb7107SBryan Cantrill {
176*a5eb7107SBryan Cantrill 	struct dvpoll arg;
177*a5eb7107SBryan Cantrill 
178*a5eb7107SBryan Cantrill 	if (maxevents <= 0) {
179*a5eb7107SBryan Cantrill 		errno = EINVAL;
180*a5eb7107SBryan Cantrill 		return (-1);
181*a5eb7107SBryan Cantrill 	}
182*a5eb7107SBryan Cantrill 
183*a5eb7107SBryan Cantrill 	arg.dp_nfds = maxevents;
184*a5eb7107SBryan Cantrill 	arg.dp_timeout = timeout;
185*a5eb7107SBryan Cantrill 	arg.dp_fds = (pollfd_t *)events;
186*a5eb7107SBryan Cantrill 
187*a5eb7107SBryan Cantrill 	return (ioctl(epfd, DP_POLL, &arg));
188*a5eb7107SBryan Cantrill }
189*a5eb7107SBryan Cantrill 
190*a5eb7107SBryan Cantrill int
191*a5eb7107SBryan Cantrill epoll_pwait(int epfd, struct epoll_event *events,
192*a5eb7107SBryan Cantrill     int maxevents, int timeout, const sigset_t *sigmask)
193*a5eb7107SBryan Cantrill {
194*a5eb7107SBryan Cantrill 	struct dvpoll arg;
195*a5eb7107SBryan Cantrill 
196*a5eb7107SBryan Cantrill 	if (maxevents <= 0) {
197*a5eb7107SBryan Cantrill 		errno = EINVAL;
198*a5eb7107SBryan Cantrill 		return (-1);
199*a5eb7107SBryan Cantrill 	}
200*a5eb7107SBryan Cantrill 
201*a5eb7107SBryan Cantrill 	arg.dp_nfds = maxevents;
202*a5eb7107SBryan Cantrill 	arg.dp_timeout = timeout;
203*a5eb7107SBryan Cantrill 	arg.dp_fds = (pollfd_t *)events;
204*a5eb7107SBryan Cantrill 	arg.dp_setp = (sigset_t *)sigmask;
205*a5eb7107SBryan Cantrill 
206*a5eb7107SBryan Cantrill 	return (ioctl(epfd, DP_PPOLL, &arg));
207*a5eb7107SBryan Cantrill }
208