5555#endif /* !HAVE_DEVPOLL */
5656#endif /* HAVE_SYS_DEVPOLL_H */
5757
58+ #ifdef HAVE_SYS_EPOLL_H
59+ #include <sys/epoll.h>
60+ #include <errno.h>
61+ #endif
62+
5863#ifdef HAVE_SYS_EVENT_H
5964#include <sys/event.h>
6065#endif /* HAVE_SYS_EVENT_H */
@@ -98,7 +103,28 @@ static int kqueue_check_fd(int fd);
98103static int kqueue_get_fd (int ridx );
99104
100105#else /* HAVE_KQUEUE */
101- # ifdef HAVE_DEVPOLL
106+
107+ # ifdef HAVE_EPOLL_CREATE1
108+
109+ #define WHICH "epoll"
110+ #define INIT (nfiles ) epoll_init(nfiles)
111+ #define EXIT () epoll_exit()
112+ #define ADD_FD (fd , rw ) epoll_add_fd(fd, rw)
113+ #define DEL_FD (fd ) epoll_del_fd(fd)
114+ #define WATCH (timeout_msecs ) epoll_watch(timeout_msecs)
115+ #define CHECK_FD (fd ) epoll_check_fd(fd)
116+ #define GET_FD (ridx ) epoll_get_fd(ridx)
117+
118+ static int epoll_init (int nfiles );
119+ static void epoll_exit (void );
120+ static void epoll_add_fd (int fd , int rw );
121+ static void epoll_del_fd (int fd );
122+ static int epoll_watch (long timeout_msecs );
123+ static int epoll_check_fd (int fd );
124+ static int epoll_get_fd (int ridx );
125+
126+ # else /* HAVE_EPOLL_CREATE1 */
127+ # ifdef HAVE_DEVPOLL
102128
103129#define WHICH "devpoll"
104130#define INIT (nfiles ) devpoll_init(nfiles)
@@ -117,8 +143,8 @@ static int devpoll_watch(long timeout_msecs);
117143static int devpoll_check_fd (int fd );
118144static int devpoll_get_fd (int ridx );
119145
120- # else /* HAVE_DEVPOLL */
121- # ifdef HAVE_POLL
146+ # else /* HAVE_DEVPOLL */
147+ # ifdef HAVE_POLL
122148
123149#define WHICH "poll"
124150#define INIT (nfiles ) poll_init(nfiles)
@@ -137,8 +163,8 @@ static int poll_watch(long timeout_msecs);
137163static int poll_check_fd (int fd );
138164static int poll_get_fd (int ridx );
139165
140- # else /* HAVE_POLL */
141- # ifdef HAVE_SELECT
166+ # else /* HAVE_POLL */
167+ # ifdef HAVE_SELECT
142168
143169#define WHICH "select"
144170#define INIT (nfiles ) select_init(nfiles)
@@ -157,9 +183,10 @@ static int select_watch(long timeout_msecs);
157183static int select_check_fd (int fd );
158184static int select_get_fd (int ridx );
159185
160- # endif /* HAVE_SELECT */
161- # endif /* HAVE_POLL */
162- # endif /* HAVE_DEVPOLL */
186+ # endif /* HAVE_SELECT */
187+ # endif /* HAVE_POLL */
188+ # endif /* HAVE_DEVPOLL */
189+ # endif /* HAVE_EPOLL_CREATE1 */
163190#endif /* HAVE_KQUEUE */
164191
165192
@@ -194,7 +221,7 @@ int fdwatch_get_nfiles(void)
194221 }
195222#endif
196223
197- #if defined(HAVE_SELECT ) && ! ( defined(HAVE_POLL ) || defined(HAVE_DEVPOLL ) || defined(HAVE_KQUEUE ) )
224+ #if defined(HAVE_SELECT ) && ! ( defined(HAVE_POLL ) || defined(HAVE_DEVPOLL ) || defined(HAVE_EPOLL_CREATE1 ) || defined( HAVE_KQUEUE ) )
198225 /* If we use select(), then we must limit ourselves to FD_SETSIZE. */
199226 nfiles = MIN (nfiles , FD_SETSIZE );
200227#endif
@@ -471,7 +498,113 @@ static int kqueue_get_fd(int ridx)
471498#else /* HAVE_KQUEUE */
472499
473500
474- # ifdef HAVE_DEVPOLL
501+ # ifdef HAVE_EPOLL_CREATE1
502+
503+ static int epollfd ;
504+ static struct epoll_event * epoll_revents ;
505+ static int * epoll_rfdidx ;
506+
507+ static int epoll_init (int nfiles )
508+ {
509+ int i ;
510+
511+ epollfd = epoll_create1 (EPOLL_CLOEXEC );
512+ if (epollfd == -1 )
513+ return -1 ;
514+
515+ epoll_revents = calloc (nfiles , sizeof (struct epoll_event ));
516+ if (!epoll_revents ) {
517+ close (epollfd );
518+ return -1 ;
519+ }
520+
521+ epoll_rfdidx = malloc (nfiles * sizeof (int ));
522+ if (!epoll_rfdidx ) {
523+ free (epoll_revents );
524+ close (epollfd );
525+ return -1 ;
526+ }
527+
528+ for (i = 0 ; i < nfiles ; i ++ )
529+ epoll_rfdidx [i ] = -1 ;
530+
531+ return 0 ;
532+ }
533+
534+ static void epoll_exit (void )
535+ {
536+ free (epoll_revents );
537+ free (epoll_rfdidx );
538+ close (epollfd );
539+ }
540+
541+ static void epoll_add_fd (int fd , int rw )
542+ {
543+ struct epoll_event ev ;
544+
545+ ev .data .fd = fd ;
546+ ev .events = (rw == FDW_READ ) ? EPOLLIN : EPOLLOUT ;
547+ if (epoll_ctl (epollfd , EPOLL_CTL_ADD , fd , & ev ) < 0 )
548+ syslog (LOG_ERR , "epoll_ctl(ADD, %d): %s" , fd , strerror (errno ));
549+ }
550+
551+ static void epoll_del_fd (int fd )
552+ {
553+ if (epoll_ctl (epollfd , EPOLL_CTL_DEL , fd , NULL ) < 0 )
554+ syslog (LOG_ERR , "epoll_ctl(DEL, %d): %s" , fd , strerror (errno ));
555+ epoll_rfdidx [fd ] = -1 ;
556+ }
557+
558+ static int epoll_watch (long timeout_msecs )
559+ {
560+ int i , r ;
561+
562+ r = epoll_wait (epollfd , epoll_revents , nfiles , (int )timeout_msecs );
563+ if (r <= 0 )
564+ return r ;
565+
566+ for (i = 0 ; i < r ; i ++ )
567+ epoll_rfdidx [epoll_revents [i ].data .fd ] = i ;
568+
569+ return r ;
570+ }
571+
572+ static int epoll_check_fd (int fd )
573+ {
574+ int ridx = epoll_rfdidx [fd ];
575+
576+ if (ridx < 0 || ridx >= nreturned )
577+ return 0 ;
578+
579+ if (epoll_revents [ridx ].data .fd != fd )
580+ return 0 ;
581+
582+ if (epoll_revents [ridx ].events & EPOLLERR )
583+ return 0 ;
584+
585+ switch (fd_rw [fd ]) {
586+ case FDW_READ :
587+ return epoll_revents [ridx ].events & (EPOLLIN | EPOLLHUP | EPOLLRDHUP );
588+
589+ case FDW_WRITE :
590+ return epoll_revents [ridx ].events & (EPOLLOUT | EPOLLHUP );
591+ }
592+
593+ return 0 ;
594+ }
595+
596+ static int epoll_get_fd (int ridx )
597+ {
598+ if (ridx < 0 || ridx >= nreturned ) {
599+ syslog (LOG_ERR , "bad ridx (%d) in epoll_get_fd!" , ridx );
600+ return -1 ;
601+ }
602+
603+ return epoll_revents [ridx ].data .fd ;
604+ }
605+
606+ # else /* HAVE_EPOLL_CREATE1 */
607+ # ifdef HAVE_DEVPOLL
475608
476609static int maxdpevents ;
477610static struct pollfd * dpevents ;
@@ -958,6 +1091,8 @@ static int select_get_fd(int ridx)
9581091
9591092# endif /* HAVE_POLL */
9601093
961- # endif /* HAVE_DEVPOLL */
1094+ # endif /* HAVE_DEVPOLL */
1095+
1096+ # endif /* HAVE_EPOLL_CREATE1 */
9621097
9631098#endif /* HAVE_KQUEUE */
0 commit comments