3939#ifdef BSD
4040#include <sys/event.h>
4141#define USE_KQUEUE
42- #define NFD 2
4342#if defined(__NetBSD__ ) || defined(__OpenBSD__ )
4443#define HAVE_KQUEUE1
4544#endif
9190#define UTIME_MAX (TIME_MAX * 2) + 1
9291#endif
9392
94- #ifndef NFD
95- #define NFD 1
96- #endif
97-
9893#ifndef UNUSED
9994#define UNUSED (a ) (void)(a)
10095#endif
@@ -178,17 +173,15 @@ eloop_event_setup_fds(struct eloop *eloop)
178173 struct eloop_event * e , * ne ;
179174#ifdef USE_PPOLL
180175 struct pollfd * pfd ;
181- size_t nfds = 0 ;
182176
183- nfds += eloop -> nevents ;
184- if (nfds > eloop -> nfds ) {
185- pfd = eloop_realloca (eloop -> fds , nfds , sizeof (* pfd ));
177+ if (eloop -> nevents > eloop -> nfds ) {
178+ pfd = eloop_realloca (eloop -> fds , eloop -> nevents , sizeof (* pfd ));
186179 if (pfd == NULL )
187180 return -1 ;
188181 eloop -> fds = pfd ;
189- eloop -> nfds = nfds ;
190- }
191- pfd = eloop -> fds ;
182+ eloop -> nfds = eloop -> nevents ;
183+ } else
184+ pfd = eloop -> fds ;
192185#endif
193186
194187 TAILQ_FOREACH_SAFE (e , & eloop -> events , next , ne ) {
@@ -240,25 +233,93 @@ eloop_event_count(const struct eloop *eloop)
240233 return eloop -> nevents ;
241234}
242235
243- int
244- eloop_event_add (struct eloop * eloop , int fd , unsigned short events ,
245- void (* cb )(void * , unsigned short ), void * cb_arg )
246- {
247- struct eloop_event * e ;
248- bool added ;
249236#if defined(USE_KQUEUE )
237+
238+ static int
239+ eloop_signal_kqueue (struct eloop * eloop , const int * signals , size_t nsignals )
240+ {
241+ size_t n = nsignals == 0 ? eloop -> nsignals : nsignals ;
242+ struct kevent ke [n ], * kep = ke ;
243+ size_t i ;
244+
245+ if (eloop -> signal_cb == NULL || n == 0 )
246+ return 0 ;
247+
248+ if (signals == NULL )
249+ signals = eloop -> signals ;
250+ for (i = 0 ; i < n ; i ++ )
251+ EV_SET (kep ++ , (uintptr_t )signals [i ],
252+ EVFILT_SIGNAL , nsignals == 0 ? EV_DELETE : EV_ADD , 0 , 0 , NULL );
253+
254+ return _kevent (eloop -> fd , ke , n , NULL , 0 , NULL );
255+ }
256+
257+ static int
258+ eloop_event_kqueue (struct eloop * eloop , struct eloop_event * e ,
259+ unsigned short events )
260+ {
250261#ifdef EVFILT_PROCDESC
251262#define NKE 3
252263#else
253264#define NKE 2
254265#endif
255- struct kevent ke [NKE ], * kep = & ke [0 ];
256- size_t n = NKE ;
266+ struct kevent ke [NKE ], * kep = ke ;
267+ int fd = e -> fd ;
268+
269+ if (events & ELE_READ && !(e -> events & ELE_READ ))
270+ EV_SET (kep ++ , (uintptr_t )fd , EVFILT_READ , EV_ADD , 0 , 0 , e );
271+ else if (!(events & ELE_READ ) && e -> events & ELE_READ )
272+ EV_SET (kep ++ , (uintptr_t )fd , EVFILT_READ , EV_DELETE , 0 , 0 , e );
273+ if (events & ELE_WRITE && !(e -> events & ELE_WRITE ))
274+ EV_SET (kep ++ , (uintptr_t )fd , EVFILT_WRITE , EV_ADD , 0 , 0 , e );
275+ else if (!(events & ELE_WRITE ) && e -> events & ELE_WRITE )
276+ EV_SET (kep ++ , (uintptr_t )fd , EVFILT_WRITE , EV_DELETE , 0 , 0 , e );
277+ #ifdef EVFILT_PROCDESC
278+ if (events & ELE_HANGUP && !(e -> events & ELE_HANGUP ))
279+ EV_SET (kep ++ , (uintptr_t )fd , EVFILT_PROCDESC , EV_ADD , NOTE_EXIT ,
280+ 0 , e );
281+ else if (!(events & ELE_HANGUP ) && e -> events & ELE_HANGUP )
282+ EV_SET (kep ++ , (uintptr_t )fd , EVFILT_PROCDESC , EV_DELETE , NOTE_EXIT ,
283+ 0 , e );
284+ #endif
285+ if (kep == ke )
286+ return 0 ;
287+ if (_kevent (eloop -> fd , ke , kep - ke , NULL , 0 , NULL ) == -1 )
288+ return -1 ;
289+ return 1 ;
290+ }
291+
257292#elif defined(USE_EPOLL )
293+
294+ static int
295+ eloop_event_epoll (struct eloop * eloop , struct eloop_event * e ,
296+ unsigned short events )
297+ {
258298 struct epoll_event epe ;
259- int op ;
299+
300+ memset (& epe , 0 , sizeof (epe ));
301+ epe .data .ptr = e ;
302+ if (events & ELE_READ )
303+ epe .events |= EPOLLIN ;
304+ if (events & ELE_WRITE )
305+ epe .events |= EPOLLOUT ;
306+ op = added ? EPOLL_CTL_ADD : EPOLL_CTL_MOD ;
307+ if (eve .events == 0 )
308+ return 0 ;
309+ if (epoll_ctl (eloop -> fd , op , fd , & epe ) == -1 )
310+ return -1 ;
311+ return 1 ;
312+ }
260313#endif
261314
315+ int
316+ eloop_event_add (struct eloop * eloop , int fd , unsigned short events ,
317+ void (* cb )(void * , unsigned short ), void * cb_arg )
318+ {
319+ struct eloop_event * e ;
320+ bool added ;
321+ int kadded ;
322+
262323 if (fd == -1 || !(events & (ELE_READ | ELE_WRITE | ELE_HANGUP ))) {
263324 errno = EINVAL ;
264325 return -1 ;
@@ -291,54 +352,22 @@ eloop_event_add(struct eloop *eloop, int fd, unsigned short events,
291352 e -> cb_arg = cb_arg ;
292353
293354#if defined(USE_KQUEUE )
294- if (events & ELE_READ && !(e -> events & ELE_READ ))
295- EV_SET (kep ++ , (uintptr_t )fd , EVFILT_READ , EV_ADD , 0 , 0 , e );
296- else if (!(events & ELE_READ ) && e -> events & ELE_READ )
297- EV_SET (kep ++ , (uintptr_t )fd , EVFILT_READ , EV_DELETE , 0 , 0 , e );
298- else
299- n -- ;
300- if (events & ELE_WRITE && !(e -> events & ELE_WRITE ))
301- EV_SET (kep ++ , (uintptr_t )fd , EVFILT_WRITE , EV_ADD , 0 , 0 , e );
302- else if (!(events & ELE_WRITE ) && e -> events & ELE_WRITE )
303- EV_SET (kep ++ , (uintptr_t )fd , EVFILT_WRITE , EV_DELETE , 0 , 0 , e );
304- else
305- n -- ;
306- #ifdef EVFILT_PROCDESC
307- if (events & ELE_HANGUP )
308- EV_SET (kep ++ , (uintptr_t )fd , EVFILT_PROCDESC , EV_ADD , NOTE_EXIT ,
309- 0 , e );
310- else
311- n -- ;
312- #endif
313- if (n != 0 && _kevent (eloop -> fd , ke , n , NULL , 0 , NULL ) == -1 ) {
314- if (added ) {
315- TAILQ_REMOVE (& eloop -> events , e , next );
316- TAILQ_INSERT_TAIL (& eloop -> free_events , e , next );
317- }
318- return -1 ;
319- }
355+ kadded = eloop_event_kqueue (eloop , e , events );
320356#elif defined(USE_EPOLL )
321- memset (& epe , 0 , sizeof (epe ));
322- epe .data .ptr = e ;
323- if (events & ELE_READ )
324- epe .events |= EPOLLIN ;
325- if (events & ELE_WRITE )
326- epe .events |= EPOLLOUT ;
327- op = added ? EPOLL_CTL_ADD : EPOLL_CTL_MOD ;
328- if (epe .events != 0 && epoll_ctl (eloop -> fd , op , fd , & epe ) == -1 ) {
329- if (added ) {
330- TAILQ_REMOVE (& eloop -> events , e , next );
331- TAILQ_INSERT_TAIL (& eloop -> free_events , e , next );
332- }
333- return -1 ;
334- }
357+ kadded = eloop_event_epoll (eloop , e , events );
335358#elif defined(USE_PPOLL )
336359 e -> pollfd = NULL ;
337- UNUSED ( added ) ;
360+ kadded = 1 ;
338361#endif
362+
363+ if (kadded != 1 && added ) {
364+ TAILQ_REMOVE (& eloop -> events , e , next );
365+ TAILQ_INSERT_TAIL (& eloop -> free_events , e , next );
366+ }
367+
339368 e -> events = events ;
340369 eloop -> events_need_setup = true;
341- return 0 ;
370+ return kadded ;
342371}
343372
344373int
@@ -666,76 +695,37 @@ eloop_forked(struct eloop *eloop, unsigned short flags)
666695{
667696#if defined(USE_KQUEUE ) || defined(USE_EPOLL )
668697 struct eloop_event * e ;
669- #if defined(USE_KQUEUE )
670- struct kevent * pfds , * pfd ;
671- size_t i ;
698+ unsigned short events ;
672699 int err ;
673- #elif defined(USE_EPOLL )
674- struct epoll_event epe = { .events = 0 };
675- #endif
676700
677- #if defined(USE_KQUEUE ) || defined(USE_EPOLL )
678701 /* The fd is invalid after a fork, no need to close it. */
679702 eloop -> fd = -1 ;
680703 if (flags && eloop_open (eloop ) == -1 )
681704 return -1 ;
682- #endif
705+
683706 eloop_clear (eloop , flags );
684707 if (!flags )
685708 return 0 ;
686709
687710#ifdef USE_KQUEUE
688- pfds = malloc (
689- (eloop -> nsignals + (eloop -> nevents * NFD )) * sizeof (* pfds ));
690- if (pfds == NULL )
711+ if (eloop_signal_kqueue (eloop , eloop -> signals , eloop -> nsignals ) == -1 )
691712 return -1 ;
692- pfd = pfds ;
693-
694- if (eloop -> signal_cb != NULL ) {
695- for (i = 0 ; i < eloop -> nsignals ; i ++ ) {
696- EV_SET (pfd ++ , (uintptr_t )eloop -> signals [i ],
697- EVFILT_SIGNAL , EV_ADD , 0 , 0 , NULL );
698- }
699- } else
700- i = 0 ;
701713#endif
702714
703715 TAILQ_FOREACH (e , & eloop -> events , next ) {
704716 if (e -> fd == -1 )
705717 continue ;
718+ events = e -> events ;
719+ e -> events = 0 ;
706720#if defined(USE_KQUEUE )
707- if (e -> events & ELE_READ ) {
708- EV_SET (pfd ++ , (uintptr_t )e -> fd , EVFILT_READ , EV_ADD , 0 ,
709- 0 , e );
710- i ++ ;
711- }
712- if (e -> events & ELE_WRITE ) {
713- EV_SET (pfd ++ , (uintptr_t )e -> fd , EVFILT_WRITE , EV_ADD , 0 ,
714- 0 , e );
715- i ++ ;
716- }
721+ err = eloop_event_kqueue (eloop , e , events );
717722#elif defined(USE_EPOLL )
718- memset (& epe , 0 , sizeof (epe ));
719- epe .data .ptr = e ;
720- if (e -> events & ELE_READ )
721- epe .events |= EPOLLIN ;
722- if (e -> events & ELE_WRITE )
723- epe .events |= EPOLLOUT ;
724- if (epoll_ctl (eloop -> fd , EPOLL_CTL_ADD , e -> fd , & epe ) == -1 )
725- return -1 ;
723+ err = eloop_event_epoll (eloop , e , events );
726724#endif
725+ if (err == -1 )
726+ return -1 ;
727727 }
728-
729- #if defined(USE_KQUEUE )
730- if (i == 0 )
731- err = 0 ;
732- else
733- err = _kevent (eloop -> fd , pfds , i , NULL , 0 , NULL );
734- free (pfds );
735- return err ;
736- #else
737728 return 0 ;
738- #endif
739729#else
740730 eloop_clear (eloop , flags );
741731 return 0 ;
@@ -746,24 +736,10 @@ int
746736eloop_signal_set_cb (struct eloop * eloop , const int * signals , size_t nsignals ,
747737 void (* signal_cb )(int , void * ), void * signal_cb_ctx )
748738{
749- #ifdef USE_KQUEUE
750- size_t i ;
751- struct kevent * ke , * kes ;
752- #endif
753- int error = 0 ;
754739
755740#ifdef USE_KQUEUE
756- ke = kes = malloc (MAX (eloop -> nsignals , nsignals ) * sizeof (* kes ));
757- if (kes == NULL )
741+ if (eloop_signal_kqueue (eloop , NULL , 0 ) == -1 )
758742 return -1 ;
759- for (i = 0 ; i < eloop -> nsignals ; i ++ ) {
760- EV_SET (ke ++ , (uintptr_t )eloop -> signals [i ], EVFILT_SIGNAL ,
761- EV_DELETE , 0 , 0 , NULL );
762- }
763- if (i != 0 && _kevent (eloop -> fd , kes , i , NULL , 0 , NULL ) == -1 ) {
764- error = -1 ;
765- goto out ;
766- }
767743#endif
768744
769745 eloop -> signals = signals ;
@@ -772,23 +748,11 @@ eloop_signal_set_cb(struct eloop *eloop, const int *signals, size_t nsignals,
772748 eloop -> signal_cb_ctx = signal_cb_ctx ;
773749
774750#ifdef USE_KQUEUE
775- if (signal_cb == NULL )
776- goto out ;
777- ke = kes ;
778- for (i = 0 ; i < eloop -> nsignals ; i ++ ) {
779- EV_SET (ke ++ , (uintptr_t )eloop -> signals [i ], EVFILT_SIGNAL ,
780- EV_ADD , 0 , 0 , NULL );
781- }
782- if (i != 0 ) {
783- if (_kevent (eloop -> fd , kes , i , NULL , 0 , NULL ) == -1 )
784- error = -1 ;
785- eloop -> events_need_setup = true;
786- }
787- out :
788- free (kes );
751+ if (eloop_signal_kqueue (eloop , signals , nsignals ) == -1 )
752+ return -1 ;
789753#endif
790754
791- return error ;
755+ return 0 ;
792756}
793757
794758#ifndef USE_KQUEUE
@@ -1016,7 +980,7 @@ eloop_run_ppoll(struct eloop *eloop, const struct timespec *ts)
1016980 struct pollfd * pfd ;
1017981 unsigned short events ;
1018982
1019- n = ppoll (eloop -> fds , (nfds_t )eloop -> nfds , ts , & eloop -> sigset );
983+ n = ppoll (eloop -> fds , (nfds_t )eloop -> nevents , ts , & eloop -> sigset );
1020984 if (n == -1 || n == 0 )
1021985 return n ;
1022986
0 commit comments