23
23
#include "protocol.h"
24
24
#endif
25
25
26
+ #if defined(__linux__ )
27
+ #include <sys/eventfd.h>
28
+ #endif
29
+
26
30
#if (!HAVE_PTHREAD_WORKQUEUES || DISPATCH_DEBUG ) && \
27
31
!defined(DISPATCH_ENABLE_THREAD_POOL )
28
32
#define DISPATCH_ENABLE_THREAD_POOL 1
@@ -74,11 +78,11 @@ static int _dispatch_pthread_sigmask(int how, sigset_t *set, sigset_t *oset);
74
78
#endif
75
79
76
80
#if DISPATCH_COCOA_COMPAT
77
- static dispatch_once_t _dispatch_main_q_port_pred ;
81
+ static dispatch_once_t _dispatch_main_q_handle_pred ;
78
82
static void _dispatch_runloop_queue_poke (dispatch_queue_t dq ,
79
83
pthread_priority_t pp , dispatch_wakeup_flags_t flags );
80
- static void _dispatch_runloop_queue_port_init (void * ctxt );
81
- static void _dispatch_runloop_queue_port_dispose (dispatch_queue_t dq );
84
+ static void _dispatch_runloop_queue_handle_init (void * ctxt );
85
+ static void _dispatch_runloop_queue_handle_dispose (dispatch_queue_t dq );
82
86
#endif
83
87
84
88
static void _dispatch_root_queues_init_once (void * context );
@@ -4090,13 +4094,6 @@ _dispatch_runloop_queue_wakeup(dispatch_queue_t dq, pthread_priority_t pp,
4090
4094
return _dispatch_release_tailcall (dq );
4091
4095
}
4092
4096
}
4093
- #else
4094
- void
4095
- _dispatch_runloop_queue_wakeup (dispatch_queue_t dq , pthread_priority_t pp ,
4096
- dispatch_wakeup_flags_t flags )
4097
- {
4098
- LINUX_PORT_ERROR ();
4099
- }
4100
4097
#endif
4101
4098
4102
4099
void
@@ -4130,6 +4127,7 @@ _dispatch_root_queue_wakeup(dispatch_queue_t dq,
4130
4127
static inline void
4131
4128
_dispatch_runloop_queue_class_poke (dispatch_queue_t dq )
4132
4129
{
4130
+ #if TARGET_OS_MAC
4133
4131
mach_port_t mp = (mach_port_t )dq -> do_ctxt ;
4134
4132
if (!mp ) {
4135
4133
return ;
@@ -4144,6 +4142,17 @@ _dispatch_runloop_queue_class_poke(dispatch_queue_t dq)
4144
4142
(void )dispatch_assume_zero (kr );
4145
4143
break ;
4146
4144
}
4145
+ #elif defined(__linux__ )
4146
+ int efd = (int )dq -> do_ctxt ;
4147
+
4148
+ if (efd != 0 ) {
4149
+ int result ;
4150
+ do {
4151
+ result = eventfd_write (efd , 1 );
4152
+ } while (result == -1 && errno == EINTR );
4153
+ (void )dispatch_assume_zero (result );
4154
+ }
4155
+ #endif
4147
4156
}
4148
4157
4149
4158
DISPATCH_NOINLINE
@@ -4158,8 +4167,8 @@ _dispatch_runloop_queue_poke(dispatch_queue_t dq,
4158
4167
// or in _dispatch_queue_cleanup2() for the main thread.
4159
4168
4160
4169
if (dq == & _dispatch_main_q ) {
4161
- dispatch_once_f (& _dispatch_main_q_port_pred , dq ,
4162
- _dispatch_runloop_queue_port_init );
4170
+ dispatch_once_f (& _dispatch_main_q_handle_pred , dq ,
4171
+ _dispatch_runloop_queue_handle_init );
4163
4172
}
4164
4173
_dispatch_queue_override_priority (dq , /* inout */ & pp , /* inout */ & flags );
4165
4174
if (flags & DISPATCH_WAKEUP_OVERRIDING ) {
@@ -4501,8 +4510,8 @@ _dispatch_main_queue_drain(void)
4501
4510
" from the wrong thread" );
4502
4511
}
4503
4512
4504
- dispatch_once_f (& _dispatch_main_q_port_pred , dq ,
4505
- _dispatch_runloop_queue_port_init );
4513
+ dispatch_once_f (& _dispatch_main_q_handle_pred , dq ,
4514
+ _dispatch_runloop_queue_handle_init );
4506
4515
4507
4516
_dispatch_perfmon_start ();
4508
4517
// <rdar://problem/23256682> hide the frame chaining when CFRunLoop
@@ -5547,7 +5556,7 @@ _dispatch_runloop_root_queue_create_4CF(const char *label, unsigned long flags)
5547
5556
_dispatch_queue_init (dq , DQF_THREAD_BOUND | DQF_CANNOT_TRYSYNC , 1 , false);
5548
5557
dq -> do_targetq = _dispatch_get_root_queue (_DISPATCH_QOS_CLASS_DEFAULT ,true);
5549
5558
dq -> dq_label = label ? label : "runloop-queue" ; // no-copy contract
5550
- _dispatch_runloop_queue_port_init (dq );
5559
+ _dispatch_runloop_queue_handle_init (dq );
5551
5560
_dispatch_queue_set_bound_thread (dq );
5552
5561
_dispatch_object_debug (dq , "%s" , __func__ );
5553
5562
return _dispatch_introspection_queue_create (dq );
@@ -5569,7 +5578,7 @@ _dispatch_runloop_queue_dispose(dispatch_queue_t dq)
5569
5578
{
5570
5579
_dispatch_object_debug (dq , "%s" , __func__ );
5571
5580
_dispatch_introspection_queue_dispose (dq );
5572
- _dispatch_runloop_queue_port_dispose (dq );
5581
+ _dispatch_runloop_queue_handle_dispose (dq );
5573
5582
_dispatch_queue_destroy (dq );
5574
5583
}
5575
5584
@@ -5604,13 +5613,17 @@ _dispatch_runloop_root_queue_get_port_4CF(dispatch_queue_t dq)
5604
5613
}
5605
5614
5606
5615
static void
5607
- _dispatch_runloop_queue_port_init (void * ctxt )
5616
+ _dispatch_runloop_queue_handle_init (void * ctxt )
5608
5617
{
5609
5618
dispatch_queue_t dq = (dispatch_queue_t )ctxt ;
5619
+ #if TARGET_OS_MAC
5610
5620
mach_port_t mp ;
5611
5621
kern_return_t kr ;
5622
+ #endif
5612
5623
5613
5624
_dispatch_fork_becomes_unsafe ();
5625
+
5626
+ #if TARGET_OS_MAC
5614
5627
kr = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE , & mp );
5615
5628
DISPATCH_VERIFY_MIG (kr );
5616
5629
(void )dispatch_assume_zero (kr );
@@ -5629,13 +5642,21 @@ _dispatch_runloop_queue_port_init(void *ctxt)
5629
5642
(void )dispatch_assume_zero (kr );
5630
5643
}
5631
5644
dq -> do_ctxt = (void * )(uintptr_t )mp ;
5645
+ #elif defined(__linux__ )
5646
+ int efd = eventfd (0 , EFD_CLOEXEC | EFD_NONBLOCK );
5647
+ (void )dispatch_assume (efd != 0 );
5648
+ dq -> do_ctxt = (void * )(uintptr_t )efd ;
5649
+ #else
5650
+ #error "not implemented for this platform"
5651
+ #endif
5632
5652
5633
5653
_dispatch_program_is_probably_callback_driven = true;
5634
5654
}
5635
5655
5636
5656
static void
5637
- _dispatch_runloop_queue_port_dispose (dispatch_queue_t dq )
5657
+ _dispatch_runloop_queue_handle_dispose (dispatch_queue_t dq )
5638
5658
{
5659
+ #if TARGET_OS_MAC
5639
5660
mach_port_t mp = (mach_port_t )dq -> do_ctxt ;
5640
5661
if (!mp ) {
5641
5662
return ;
@@ -5647,19 +5668,39 @@ _dispatch_runloop_queue_port_dispose(dispatch_queue_t dq)
5647
5668
kr = mach_port_mod_refs (mach_task_self (), mp , MACH_PORT_RIGHT_RECEIVE , -1 );
5648
5669
DISPATCH_VERIFY_MIG (kr );
5649
5670
(void )dispatch_assume_zero (kr );
5671
+ #elif defined(__linux__ )
5672
+ int efd = (int )dq -> do_ctxt ;
5673
+ if (!efd ) {
5674
+ return ;
5675
+ }
5676
+ dq -> do_ctxt = NULL ;
5677
+ int rc = close (efd );
5678
+ (void )dispatch_assume_zero (rc );
5679
+ #endif
5650
5680
}
5651
5681
5652
5682
#pragma mark -
5653
5683
#pragma mark dispatch_main_queue
5654
5684
5685
+ #if TARGET_OS_MAC
5655
5686
mach_port_t
5656
5687
_dispatch_get_main_queue_port_4CF (void )
5657
5688
{
5658
5689
dispatch_queue_t dq = & _dispatch_main_q ;
5659
- dispatch_once_f (& _dispatch_main_q_port_pred , dq ,
5660
- _dispatch_runloop_queue_port_init );
5690
+ dispatch_once_f (& _dispatch_main_q_handle_pred , dq ,
5691
+ _dispatch_runloop_queue_handle_init );
5661
5692
return (mach_port_t )dq -> do_ctxt ;
5662
5693
}
5694
+ #else
5695
+ dispatch_handle_t
5696
+ _dispatch_get_main_queue_handle_4CF (void )
5697
+ {
5698
+ dispatch_queue_t dq = & _dispatch_main_q ;
5699
+ dispatch_once_f (& _dispatch_main_q_handle_pred , dq ,
5700
+ _dispatch_runloop_queue_handle_init );
5701
+ return (dispatch_handle_t )dq -> do_ctxt ;
5702
+ }
5703
+ #endif
5663
5704
5664
5705
static bool main_q_is_draining ;
5665
5706
@@ -5673,7 +5714,11 @@ _dispatch_queue_set_mainq_drain_state(bool arg)
5673
5714
}
5674
5715
5675
5716
void
5717
+ #if TARGET_OS_MAC
5676
5718
_dispatch_main_queue_callback_4CF (mach_msg_header_t * msg DISPATCH_UNUSED )
5719
+ #else
5720
+ _dispatch_main_queue_callback_4CF ()
5721
+ #endif
5677
5722
{
5678
5723
if (main_q_is_draining ) {
5679
5724
return ;
@@ -5798,9 +5843,9 @@ _dispatch_queue_cleanup2(void)
5798
5843
#endif
5799
5844
5800
5845
#if DISPATCH_COCOA_COMPAT
5801
- dispatch_once_f (& _dispatch_main_q_port_pred , dq ,
5802
- _dispatch_runloop_queue_port_init );
5803
- _dispatch_runloop_queue_port_dispose (dq );
5846
+ dispatch_once_f (& _dispatch_main_q_handle_pred , dq ,
5847
+ _dispatch_runloop_queue_handle_init );
5848
+ _dispatch_runloop_queue_handle_dispose (dq );
5804
5849
#endif
5805
5850
}
5806
5851
0 commit comments