@@ -74,11 +74,11 @@ static int _dispatch_pthread_sigmask(int how, sigset_t *set, sigset_t *oset);
74
74
#endif
75
75
76
76
#if DISPATCH_COCOA_COMPAT
77
- static dispatch_once_t _dispatch_main_q_port_pred ;
77
+ static dispatch_once_t _dispatch_main_q_handle_pred ;
78
78
static void _dispatch_runloop_queue_poke (dispatch_queue_t dq ,
79
79
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 );
80
+ static void _dispatch_runloop_queue_handle_init (void * ctxt );
81
+ static void _dispatch_runloop_queue_handle_dispose (dispatch_queue_t dq );
82
82
#endif
83
83
84
84
static void _dispatch_root_queues_init_once (void * context );
@@ -4063,6 +4063,46 @@ _dispatch_queue_wakeup(dispatch_queue_t dq, pthread_priority_t pp,
4063
4063
}
4064
4064
4065
4065
#if DISPATCH_COCOA_COMPAT
4066
+
4067
+ DISPATCH_ALWAYS_INLINE
4068
+ static inline bool
4069
+ _dispatch_runloop_handle_is_valid (dispatch_runloop_handle_t handle )
4070
+ {
4071
+ #if TARGET_OS_MAC
4072
+ return MACH_PORT_VALID (handle );
4073
+ #elif defined(__linux__ )
4074
+ return handle >= 0 ;
4075
+ #else
4076
+ #error "runloop support not implemented on this platform"
4077
+ #endif
4078
+ }
4079
+
4080
+ DISPATCH_ALWAYS_INLINE
4081
+ static inline dispatch_runloop_handle_t
4082
+ _dispatch_runloop_queue_get_handle (dispatch_queue_t dq )
4083
+ {
4084
+ #if TARGET_OS_MAC
4085
+ return ((dispatch_runloop_handle_t )(uintptr_t )dq -> do_ctxt );
4086
+ #elif defined(__linux__ )
4087
+ return ((dispatch_runloop_handle_t )(uintptr_t )dq -> do_ctxt ) - 1 ;
4088
+ #else
4089
+ #error "runloop support not implemented on this platform"
4090
+ #endif
4091
+ }
4092
+
4093
+ DISPATCH_ALWAYS_INLINE
4094
+ static inline void
4095
+ _dispatch_runloop_queue_set_handle (dispatch_queue_t dq , dispatch_runloop_handle_t handle )
4096
+ {
4097
+ #if TARGET_OS_MAC
4098
+ dq -> do_ctxt = (void * )(uintptr_t )handle ;
4099
+ #elif defined(__linux__ )
4100
+ dq -> do_ctxt = (void * )(uintptr_t )(handle + 1 );
4101
+ #else
4102
+ #error "runloop support not implemented on this platform"
4103
+ #endif
4104
+ }
4105
+
4066
4106
void
4067
4107
_dispatch_runloop_queue_wakeup (dispatch_queue_t dq , pthread_priority_t pp ,
4068
4108
dispatch_wakeup_flags_t flags )
@@ -4090,13 +4130,6 @@ _dispatch_runloop_queue_wakeup(dispatch_queue_t dq, pthread_priority_t pp,
4090
4130
return _dispatch_release_tailcall (dq );
4091
4131
}
4092
4132
}
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
4133
#endif
4101
4134
4102
4135
void
@@ -4130,11 +4163,13 @@ _dispatch_root_queue_wakeup(dispatch_queue_t dq,
4130
4163
static inline void
4131
4164
_dispatch_runloop_queue_class_poke (dispatch_queue_t dq )
4132
4165
{
4133
- mach_port_t mp = ( mach_port_t ) dq -> do_ctxt ;
4134
- if (!mp ) {
4166
+ dispatch_runloop_handle_t handle = _dispatch_runloop_queue_get_handle ( dq ) ;
4167
+ if (!_dispatch_runloop_handle_is_valid ( handle ) ) {
4135
4168
return ;
4136
4169
}
4137
- kern_return_t kr = _dispatch_send_wakeup_runloop_thread (mp , 0 );
4170
+
4171
+ #if TARGET_OS_MAC
4172
+ kern_return_t kr = _dispatch_send_wakeup_runloop_thread (handle , 0 );
4138
4173
switch (kr ) {
4139
4174
case MACH_SEND_TIMEOUT :
4140
4175
case MACH_SEND_TIMED_OUT :
@@ -4144,6 +4179,15 @@ _dispatch_runloop_queue_class_poke(dispatch_queue_t dq)
4144
4179
(void )dispatch_assume_zero (kr );
4145
4180
break ;
4146
4181
}
4182
+ #elif defined(__linux__ )
4183
+ int result ;
4184
+ do {
4185
+ result = eventfd_write (handle , 1 );
4186
+ } while (result == -1 && errno == EINTR );
4187
+ (void )dispatch_assume_zero (result );
4188
+ #else
4189
+ #error "runloop support not implemented on this platform"
4190
+ #endif
4147
4191
}
4148
4192
4149
4193
DISPATCH_NOINLINE
@@ -4158,8 +4202,8 @@ _dispatch_runloop_queue_poke(dispatch_queue_t dq,
4158
4202
// or in _dispatch_queue_cleanup2() for the main thread.
4159
4203
4160
4204
if (dq == & _dispatch_main_q ) {
4161
- dispatch_once_f (& _dispatch_main_q_port_pred , dq ,
4162
- _dispatch_runloop_queue_port_init );
4205
+ dispatch_once_f (& _dispatch_main_q_handle_pred , dq ,
4206
+ _dispatch_runloop_queue_handle_init );
4163
4207
}
4164
4208
_dispatch_queue_override_priority (dq , /* inout */ & pp , /* inout */ & flags );
4165
4209
if (flags & DISPATCH_WAKEUP_OVERRIDING ) {
@@ -4501,8 +4545,8 @@ _dispatch_main_queue_drain(void)
4501
4545
" from the wrong thread" );
4502
4546
}
4503
4547
4504
- dispatch_once_f (& _dispatch_main_q_port_pred , dq ,
4505
- _dispatch_runloop_queue_port_init );
4548
+ dispatch_once_f (& _dispatch_main_q_handle_pred , dq ,
4549
+ _dispatch_runloop_queue_handle_init );
4506
4550
4507
4551
_dispatch_perfmon_start ();
4508
4552
// <rdar://problem/23256682> hide the frame chaining when CFRunLoop
@@ -5547,7 +5591,7 @@ _dispatch_runloop_root_queue_create_4CF(const char *label, unsigned long flags)
5547
5591
_dispatch_queue_init (dq , DQF_THREAD_BOUND | DQF_CANNOT_TRYSYNC , 1 , false);
5548
5592
dq -> do_targetq = _dispatch_get_root_queue (_DISPATCH_QOS_CLASS_DEFAULT ,true);
5549
5593
dq -> dq_label = label ? label : "runloop-queue" ; // no-copy contract
5550
- _dispatch_runloop_queue_port_init (dq );
5594
+ _dispatch_runloop_queue_handle_init (dq );
5551
5595
_dispatch_queue_set_bound_thread (dq );
5552
5596
_dispatch_object_debug (dq , "%s" , __func__ );
5553
5597
return _dispatch_introspection_queue_create (dq );
@@ -5569,7 +5613,7 @@ _dispatch_runloop_queue_dispose(dispatch_queue_t dq)
5569
5613
{
5570
5614
_dispatch_object_debug (dq , "%s" , __func__ );
5571
5615
_dispatch_introspection_queue_dispose (dq );
5572
- _dispatch_runloop_queue_port_dispose (dq );
5616
+ _dispatch_runloop_queue_handle_dispose (dq );
5573
5617
_dispatch_queue_destroy (dq );
5574
5618
}
5575
5619
@@ -5594,71 +5638,90 @@ _dispatch_runloop_root_queue_wakeup_4CF(dispatch_queue_t dq)
5594
5638
_dispatch_runloop_queue_wakeup (dq , 0 , false);
5595
5639
}
5596
5640
5597
- mach_port_t
5641
+ dispatch_runloop_handle_t
5598
5642
_dispatch_runloop_root_queue_get_port_4CF (dispatch_queue_t dq )
5599
5643
{
5600
5644
if (slowpath (dq -> do_vtable != DISPATCH_VTABLE (queue_runloop ))) {
5601
5645
DISPATCH_CLIENT_CRASH (dq -> do_vtable , "Not a runloop queue" );
5602
5646
}
5603
- return ( mach_port_t ) dq -> do_ctxt ;
5647
+ return _dispatch_runloop_queue_get_handle ( dq ) ;
5604
5648
}
5605
5649
5606
5650
static void
5607
- _dispatch_runloop_queue_port_init (void * ctxt )
5651
+ _dispatch_runloop_queue_handle_init (void * ctxt )
5608
5652
{
5609
5653
dispatch_queue_t dq = (dispatch_queue_t )ctxt ;
5610
- mach_port_t mp ;
5611
- kern_return_t kr ;
5654
+ dispatch_runloop_handle_t handle ;
5612
5655
5613
5656
_dispatch_fork_becomes_unsafe ();
5614
- kr = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE , & mp );
5657
+
5658
+ #if TARGET_OS_MAC
5659
+ kern_return_t kr ;
5660
+ kr = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE , & handle );
5615
5661
DISPATCH_VERIFY_MIG (kr );
5616
5662
(void )dispatch_assume_zero (kr );
5617
- kr = mach_port_insert_right (mach_task_self (), mp , mp ,
5663
+ kr = mach_port_insert_right (mach_task_self (), handle , handle ,
5618
5664
MACH_MSG_TYPE_MAKE_SEND );
5619
5665
DISPATCH_VERIFY_MIG (kr );
5620
5666
(void )dispatch_assume_zero (kr );
5621
5667
if (dq != & _dispatch_main_q ) {
5622
5668
struct mach_port_limits limits = {
5623
5669
.mpl_qlimit = 1 ,
5624
5670
};
5625
- kr = mach_port_set_attributes (mach_task_self (), mp ,
5671
+ kr = mach_port_set_attributes (mach_task_self (), handle ,
5626
5672
MACH_PORT_LIMITS_INFO , (mach_port_info_t )& limits ,
5627
5673
sizeof (limits ));
5628
5674
DISPATCH_VERIFY_MIG (kr );
5629
5675
(void )dispatch_assume_zero (kr );
5630
5676
}
5631
- dq -> do_ctxt = (void * )(uintptr_t )mp ;
5677
+ #elif defined(__linux__ )
5678
+ handle = eventfd (0 , EFD_CLOEXEC | EFD_NONBLOCK );
5679
+ #else
5680
+ #error "runloop support not implemented on this platform"
5681
+ #endif
5682
+ (void )dispatch_assume (_dispatch_runloop_handle_is_valid (handle ));
5683
+ _dispatch_runloop_queue_set_handle (dq , handle );
5632
5684
5633
5685
_dispatch_program_is_probably_callback_driven = true;
5634
5686
}
5635
5687
5636
5688
static void
5637
- _dispatch_runloop_queue_port_dispose (dispatch_queue_t dq )
5689
+ _dispatch_runloop_queue_handle_dispose (dispatch_queue_t dq )
5638
5690
{
5639
- mach_port_t mp = ( mach_port_t ) dq -> do_ctxt ;
5640
- if (!mp ) {
5691
+ dispatch_runloop_handle_t handle = _dispatch_runloop_queue_get_handle ( dq ) ;
5692
+ if (!_dispatch_runloop_handle_is_valid ( handle ) ) {
5641
5693
return ;
5642
5694
}
5643
5695
dq -> do_ctxt = NULL ;
5644
- kern_return_t kr = mach_port_deallocate (mach_task_self (), mp );
5696
+ #if TARGET_OS_MAC
5697
+ kern_return_t kr = mach_port_deallocate (mach_task_self (), hand );
5645
5698
DISPATCH_VERIFY_MIG (kr );
5646
5699
(void )dispatch_assume_zero (kr );
5647
5700
kr = mach_port_mod_refs (mach_task_self (), mp , MACH_PORT_RIGHT_RECEIVE , -1 );
5648
5701
DISPATCH_VERIFY_MIG (kr );
5649
5702
(void )dispatch_assume_zero (kr );
5703
+ #elif defined(__linux__ )
5704
+ int rc = close (handle );
5705
+ (void )dispatch_assume_zero (rc );
5706
+ #else
5707
+ #error "runloop support not implemented on this platform"
5708
+ #endif
5650
5709
}
5651
5710
5652
5711
#pragma mark -
5653
5712
#pragma mark dispatch_main_queue
5654
5713
5655
- mach_port_t
5714
+ dispatch_runloop_handle_t
5715
+ #if TARGET_OS_MAC
5656
5716
_dispatch_get_main_queue_port_4CF (void )
5717
+ #else
5718
+ _dispatch_get_main_queue_handle_4CF (void )
5719
+ #endif
5657
5720
{
5658
5721
dispatch_queue_t dq = & _dispatch_main_q ;
5659
- dispatch_once_f (& _dispatch_main_q_port_pred , dq ,
5660
- _dispatch_runloop_queue_port_init );
5661
- return ( mach_port_t ) dq -> do_ctxt ;
5722
+ dispatch_once_f (& _dispatch_main_q_handle_pred , dq ,
5723
+ _dispatch_runloop_queue_handle_init );
5724
+ return _dispatch_runloop_queue_get_handle ( dq ) ;
5662
5725
}
5663
5726
5664
5727
static bool main_q_is_draining ;
@@ -5673,7 +5736,11 @@ _dispatch_queue_set_mainq_drain_state(bool arg)
5673
5736
}
5674
5737
5675
5738
void
5739
+ #if TARGET_OS_MAC
5676
5740
_dispatch_main_queue_callback_4CF (mach_msg_header_t * msg DISPATCH_UNUSED )
5741
+ #else
5742
+ _dispatch_main_queue_callback_4CF (void )
5743
+ #endif
5677
5744
{
5678
5745
if (main_q_is_draining ) {
5679
5746
return ;
@@ -5798,9 +5865,9 @@ _dispatch_queue_cleanup2(void)
5798
5865
#endif
5799
5866
5800
5867
#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 );
5868
+ dispatch_once_f (& _dispatch_main_q_handle_pred , dq ,
5869
+ _dispatch_runloop_queue_handle_init );
5870
+ _dispatch_runloop_queue_handle_dispose (dq );
5804
5871
#endif
5805
5872
}
5806
5873
0 commit comments