8383#include <mach/mach_time.h>
8484#endif
8585
86+ #ifdef HAVE_KQUEUE
87+ #include <sys/event.h>
88+ #endif
89+
8690#include "glib_trace.h"
8791
8892#include "gmain.h"
@@ -326,6 +330,10 @@ struct _GMainContext
326330
327331 gint64 time ;
328332 gboolean time_is_fresh ;
333+
334+ #ifdef HAVE_KQUEUE
335+ gint kq ;
336+ #endif
329337};
330338
331339struct _GSourceCallback
@@ -599,6 +607,10 @@ _g_main_recover_from_fork_in_child (void)
599607 {
600608 GMainContext * context = l -> data ;
601609
610+ #ifdef HAVE_KQUEUE
611+ context -> kq = kqueue ();
612+ #endif
613+
602614 g_wakeup_free (context -> wakeup );
603615 context -> wakeup = g_wakeup_new ();
604616
@@ -716,6 +728,10 @@ g_main_context_unref (GMainContext *context)
716728
717729 poll_rec_list_free (context , context -> poll_records );
718730
731+ #ifdef HAVE_KQUEUE
732+ close (context -> kq );
733+ #endif
734+
719735 g_wakeup_free (context -> wakeup );
720736 g_cond_clear (& context -> cond );
721737
@@ -812,6 +828,10 @@ g_main_context_new_with_flags (GMainContextFlags flags)
812828 context -> pending_dispatches = g_ptr_array_new ();
813829
814830 context -> time_is_fresh = FALSE;
831+
832+ #ifdef HAVE_KQUEUE
833+ context -> kq = kqueue ();
834+ #endif
815835
816836 context -> wakeup = g_wakeup_new ();
817837 g_wakeup_get_pollfd (context -> wakeup , & context -> wake_up_rec );
@@ -4611,6 +4631,9 @@ g_main_context_poll (GMainContext *context,
46114631 if (n_fds || timeout != 0 )
46124632 {
46134633 int ret , errsv ;
4634+ #ifdef HAVE_KQUEUE
4635+ guint max_events ;
4636+ #endif
46144637
46154638#ifdef G_MAIN_POLL_DEBUG
46164639 poll_timer = NULL ;
@@ -4625,8 +4648,100 @@ g_main_context_poll (GMainContext *context,
46254648 LOCK_CONTEXT (context );
46264649
46274650 poll_func = context -> poll_func ;
4651+ #ifdef HAVE_KQUEUE
4652+ max_events = context -> n_poll_records ;
4653+ #endif
46284654
46294655 UNLOCK_CONTEXT (context );
4656+
4657+ #ifdef HAVE_KQUEUE
4658+ if (poll_func == g_poll )
4659+ {
4660+ struct kevent * events ;
4661+ struct timespec * ts , ts_storage ;
4662+
4663+ events = g_newa (struct kevent , max_events );
4664+
4665+ if (timeout != -1 )
4666+ {
4667+ ts_storage .tv_sec = timeout / 1000 ;
4668+ ts_storage .tv_nsec = (timeout % 1000 ) * 1000000 ;
4669+ ts = & ts_storage ;
4670+ }
4671+ else
4672+ {
4673+ ts = NULL ;
4674+ }
4675+
4676+ ret = kevent (context -> kq , NULL , 0 , events , max_events , ts );
4677+ errsv = errno ;
4678+
4679+ if (ret > 0 )
4680+ {
4681+ int i ;
4682+
4683+ for (int i = 0 ; i < n_fds ; i ++ )
4684+ fds [i ].revents = 0 ;
4685+
4686+ for (i = 0 ; i < ret ; i ++ )
4687+ {
4688+ struct kevent * ev = & events [i ];
4689+
4690+ for (int i = 0 ; i < n_fds ; i ++ )
4691+ {
4692+ GPollFD * pfd = & fds [i ];
4693+
4694+ if (pfd -> fd == (gint ) ev -> ident )
4695+ {
4696+ switch (ev -> filter )
4697+ {
4698+ case EVFILT_READ :
4699+ if (pfd -> events & G_IO_IN )
4700+ pfd -> revents |= G_IO_IN ;
4701+ #ifdef EV_OOBAND
4702+ if (pfd -> events & G_IO_PRI && ev -> flags & EV_OOBAND )
4703+ pfd -> revents |= G_IO_PRI ;
4704+ #endif
4705+ if (ev -> flags & EV_EOF )
4706+ {
4707+ pfd -> revents |= G_IO_HUP ;
4708+ if (ev -> fflags != 0 )
4709+ pfd -> revents |= G_IO_ERR ;
4710+ }
4711+ break ;
4712+ case EVFILT_WRITE :
4713+ if (pfd -> events & G_IO_OUT )
4714+ pfd -> revents |= G_IO_OUT ;
4715+ if (ev -> flags & EV_EOF )
4716+ pfd -> revents |= G_IO_ERR ;
4717+ break ;
4718+ #ifdef EVFILT_EXCEPT
4719+ case EVFILT_EXCEPT :
4720+ if (pfd -> events & G_IO_PRI )
4721+ pfd -> revents |= G_IO_PRI ;
4722+ if (ev -> flags & EV_EOF )
4723+ pfd -> revents |= G_IO_HUP ;
4724+ break ;
4725+ #endif
4726+ case EVFILT_USER :
4727+ if (pfd -> events & G_IO_IN )
4728+ pfd -> revents |= G_IO_IN ;
4729+ break ;
4730+ }
4731+ }
4732+ }
4733+ }
4734+ }
4735+ else if (ret < 0 && errsv != EINTR )
4736+ {
4737+ g_warning ("kevent(2) failed due to: %s." ,
4738+ g_strerror (errsv ));
4739+ }
4740+
4741+ goto out ;
4742+ }
4743+ #endif
4744+
46304745 ret = (* poll_func ) (fds , n_fds , timeout );
46314746 errsv = errno ;
46324747 if (ret < 0 && errsv != EINTR )
@@ -4639,6 +4754,11 @@ g_main_context_poll (GMainContext *context,
46394754#endif
46404755 }
46414756
4757+
4758+ #ifdef HAVE_KQUEUE
4759+ out :
4760+ ;
4761+ #endif
46424762#ifdef G_MAIN_POLL_DEBUG
46434763 if (_g_main_poll_debug )
46444764 {
@@ -4756,6 +4876,43 @@ g_main_context_add_poll_unlocked (GMainContext *context,
47564876
47574877 context -> poll_changed = TRUE;
47584878
4879+ #ifdef HAVE_KQUEUE
4880+ {
4881+ struct kevent events [3 ], * ev ;
4882+
4883+ ev = events ;
4884+ if (fd -> fd == G_KQUEUE_WAKEUP_HANDLE )
4885+ {
4886+ * (fd -> kq ) = context -> kq ;
4887+
4888+ EV_SET (ev , fd -> fd , EVFILT_USER , EV_ADD , NOTE_FFCOPY , 0 , NULL );
4889+ ev ++ ;
4890+ }
4891+ else
4892+ {
4893+ if (fd -> events & G_IO_IN )
4894+ {
4895+ EV_SET (ev , fd -> fd , EVFILT_READ , EV_ADD , 0 , 0 , NULL );
4896+ ev ++ ;
4897+ }
4898+ if (fd -> events & G_IO_OUT )
4899+ {
4900+ EV_SET (ev , fd -> fd , EVFILT_WRITE , EV_ADD , 0 , 0 , NULL );
4901+ ev ++ ;
4902+ }
4903+ #ifdef EVFILT_EXCEPT
4904+ if (fd -> events & G_IO_PRI )
4905+ {
4906+ EV_SET (ev , fd -> fd , EVFILT_EXCEPT , EV_ADD , NOTE_OOB , 0 , NULL );
4907+ ev ++ ;
4908+ }
4909+ #endif
4910+ }
4911+
4912+ kevent (context -> kq , events , ev - events , NULL , 0 , NULL );
4913+ }
4914+ #endif
4915+
47594916 /* Now wake up the main loop if it is waiting in the poll() */
47604917 if (fd != & context -> wake_up_rec )
47614918 g_wakeup_signal (context -> wakeup );
@@ -4817,6 +4974,72 @@ g_main_context_remove_poll_unlocked (GMainContext *context,
48174974
48184975 context -> poll_changed = TRUE;
48194976
4977+ #ifdef HAVE_KQUEUE
4978+ {
4979+ gboolean remove_wakeup , remove_in , remove_out , remove_pri ;
4980+ struct kevent events [3 ], * ev ;
4981+
4982+ remove_wakeup = fd -> fd == G_KQUEUE_WAKEUP_HANDLE ;
4983+ if (remove_wakeup )
4984+ {
4985+ remove_in = FALSE;
4986+ remove_out = FALSE;
4987+ remove_pri = FALSE;
4988+ }
4989+ else
4990+ {
4991+ remove_in = !!(fd -> events & G_IO_IN );
4992+ remove_out = !!(fd -> events & G_IO_OUT );
4993+ remove_pri = !!(fd -> events & G_IO_PRI );
4994+ }
4995+
4996+ for (pollrec = context -> poll_records ; pollrec ; pollrec = pollrec -> next )
4997+ {
4998+ GPollFD * cur = pollrec -> fd ;
4999+
5000+ if (cur -> fd == G_KQUEUE_WAKEUP_HANDLE )
5001+ {
5002+ remove_wakeup = FALSE;
5003+ }
5004+ else if (cur -> fd == fd -> fd )
5005+ {
5006+ if (cur -> events & G_IO_IN )
5007+ remove_in = FALSE;
5008+ if (cur -> events & G_IO_OUT )
5009+ remove_out = FALSE;
5010+ if (cur -> events & G_IO_PRI )
5011+ remove_pri = FALSE;
5012+ }
5013+ }
5014+
5015+ ev = events ;
5016+ if (remove_wakeup )
5017+ {
5018+ EV_SET (ev , fd -> fd , EVFILT_USER , EV_DELETE , 0 , 0 , NULL );
5019+ ev ++ ;
5020+ }
5021+ if (remove_in )
5022+ {
5023+ EV_SET (ev , fd -> fd , EVFILT_READ , EV_DELETE , 0 , 0 , NULL );
5024+ ev ++ ;
5025+ }
5026+ if (remove_out )
5027+ {
5028+ EV_SET (ev , fd -> fd , EVFILT_WRITE , EV_DELETE , 0 , 0 , NULL );
5029+ ev ++ ;
5030+ }
5031+ #ifdef EVFILT_EXCEPT
5032+ if (remove_pri )
5033+ {
5034+ EV_SET (ev , fd -> fd , EVFILT_EXCEPT , EV_DELETE , 0 , 0 , NULL );
5035+ ev ++ ;
5036+ }
5037+ #endif
5038+
5039+ kevent (context -> kq , events , ev - events , NULL , 0 , NULL );
5040+ }
5041+ #endif
5042+
48205043 /* Now wake up the main loop if it is waiting in the poll() */
48215044 g_wakeup_signal (context -> wakeup );
48225045}
0 commit comments