83
83
#include <mach/mach_time.h>
84
84
#endif
85
85
86
+ #ifdef HAVE_KQUEUE
87
+ #include <sys/event.h>
88
+ #endif
89
+
86
90
#include "glib_trace.h"
87
91
88
92
#include "gmain.h"
@@ -326,6 +330,10 @@ struct _GMainContext
326
330
327
331
gint64 time ;
328
332
gboolean time_is_fresh ;
333
+
334
+ #ifdef HAVE_KQUEUE
335
+ gint kq ;
336
+ #endif
329
337
};
330
338
331
339
struct _GSourceCallback
@@ -599,6 +607,10 @@ _g_main_recover_from_fork_in_child (void)
599
607
{
600
608
GMainContext * context = l -> data ;
601
609
610
+ #ifdef HAVE_KQUEUE
611
+ context -> kq = kqueue ();
612
+ #endif
613
+
602
614
g_wakeup_free (context -> wakeup );
603
615
context -> wakeup = g_wakeup_new ();
604
616
@@ -716,6 +728,10 @@ g_main_context_unref (GMainContext *context)
716
728
717
729
poll_rec_list_free (context , context -> poll_records );
718
730
731
+ #ifdef HAVE_KQUEUE
732
+ close (context -> kq );
733
+ #endif
734
+
719
735
g_wakeup_free (context -> wakeup );
720
736
g_cond_clear (& context -> cond );
721
737
@@ -812,6 +828,10 @@ g_main_context_new_with_flags (GMainContextFlags flags)
812
828
context -> pending_dispatches = g_ptr_array_new ();
813
829
814
830
context -> time_is_fresh = FALSE;
831
+
832
+ #ifdef HAVE_KQUEUE
833
+ context -> kq = kqueue ();
834
+ #endif
815
835
816
836
context -> wakeup = g_wakeup_new ();
817
837
g_wakeup_get_pollfd (context -> wakeup , & context -> wake_up_rec );
@@ -4611,6 +4631,9 @@ g_main_context_poll (GMainContext *context,
4611
4631
if (n_fds || timeout != 0 )
4612
4632
{
4613
4633
int ret , errsv ;
4634
+ #ifdef HAVE_KQUEUE
4635
+ guint max_events ;
4636
+ #endif
4614
4637
4615
4638
#ifdef G_MAIN_POLL_DEBUG
4616
4639
poll_timer = NULL ;
@@ -4625,8 +4648,100 @@ g_main_context_poll (GMainContext *context,
4625
4648
LOCK_CONTEXT (context );
4626
4649
4627
4650
poll_func = context -> poll_func ;
4651
+ #ifdef HAVE_KQUEUE
4652
+ max_events = context -> n_poll_records ;
4653
+ #endif
4628
4654
4629
4655
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
+
4630
4745
ret = (* poll_func ) (fds , n_fds , timeout );
4631
4746
errsv = errno ;
4632
4747
if (ret < 0 && errsv != EINTR )
@@ -4639,6 +4754,11 @@ g_main_context_poll (GMainContext *context,
4639
4754
#endif
4640
4755
}
4641
4756
4757
+
4758
+ #ifdef HAVE_KQUEUE
4759
+ out :
4760
+ ;
4761
+ #endif
4642
4762
#ifdef G_MAIN_POLL_DEBUG
4643
4763
if (_g_main_poll_debug )
4644
4764
{
@@ -4756,6 +4876,43 @@ g_main_context_add_poll_unlocked (GMainContext *context,
4756
4876
4757
4877
context -> poll_changed = TRUE;
4758
4878
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
+
4759
4916
/* Now wake up the main loop if it is waiting in the poll() */
4760
4917
if (fd != & context -> wake_up_rec )
4761
4918
g_wakeup_signal (context -> wakeup );
@@ -4817,6 +4974,72 @@ g_main_context_remove_poll_unlocked (GMainContext *context,
4817
4974
4818
4975
context -> poll_changed = TRUE;
4819
4976
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
+
4820
5043
/* Now wake up the main loop if it is waiting in the poll() */
4821
5044
g_wakeup_signal (context -> wakeup );
4822
5045
}
0 commit comments