@@ -2077,13 +2077,6 @@ dispatch_pthread_root_queue_copy_current(void)
2077
2077
return (dispatch_queue_t )_os_object_retain_with_resurrect (dq -> _as_os_obj );
2078
2078
}
2079
2079
2080
- int32_t
2081
- _dispatch_pthread_root_queue_thread_pool_size (dispatch_queue_t dq )
2082
- {
2083
- dispatch_root_queue_context_t qc = dq -> do_ctxt ;
2084
- return os_atomic_load2o (qc , dgq_thread_pool_size , relaxed );
2085
- }
2086
-
2087
2080
#endif // DISPATCH_ENABLE_PTHREAD_ROOT_QUEUES
2088
2081
2089
2082
void
@@ -3956,50 +3949,12 @@ _dispatch_runloop_queue_poke(dispatch_queue_t dq, dispatch_qos_t qos,
3956
3949
}
3957
3950
#endif
3958
3951
3959
- #if DISPATCH_USE_PTHREAD_POOL
3960
- static void
3961
- _dispatch_pthread_root_queue_spawn_workers (dispatch_queue_t dq ,
3962
- pthread_attr_t * attr , int n )
3963
- {
3964
- pthread_t tid , * pthr = & tid ;
3965
- int r ;
3966
-
3967
- do {
3968
- _dispatch_retain (dq );
3969
- while ((r = pthread_create (pthr , attr , _dispatch_worker_thread , dq ))) {
3970
- if (r != EAGAIN ) {
3971
- (void )dispatch_assume_zero (r );
3972
- }
3973
- _dispatch_temporary_resource_shortage ();
3974
- }
3975
- } while (-- n );
3976
- }
3977
-
3978
- bool
3979
- _dispatch_pthread_root_queue_oversubscribe (dispatch_queue_t dq , int n )
3980
- {
3981
- dispatch_root_queue_context_t qc = dq -> do_ctxt ;
3982
- dispatch_pthread_root_queue_context_t pqc = qc -> dgq_ctxt ;
3983
- pthread_attr_t * attr = & pqc -> dpq_thread_attr ;
3984
-
3985
- if (!os_atomic_cmpxchg2o (qc , dgq_pending , 0 , n , relaxed )) {
3986
- return false;
3987
- }
3988
-
3989
- (void )os_atomic_sub2o (qc , dgq_thread_pool_size , n , release );
3990
-
3991
- _dispatch_pthread_root_queue_spawn_workers (dq , attr , n );
3992
-
3993
- return true;
3994
- }
3995
- #endif
3996
-
3997
3952
DISPATCH_NOINLINE
3998
3953
static void
3999
- _dispatch_global_queue_poke_slow (dispatch_queue_t dq , int n )
3954
+ _dispatch_global_queue_poke_slow (dispatch_queue_t dq , int n , int floor )
4000
3955
{
4001
3956
dispatch_root_queue_context_t qc = dq -> do_ctxt ;
4002
- int32_t i = n ;
3957
+ int remaining = n ;
4003
3958
int r = ENOSYS ;
4004
3959
4005
3960
_dispatch_root_queues_init ();
@@ -4019,16 +3974,16 @@ _dispatch_global_queue_poke_slow(dispatch_queue_t dq, int n)
4019
3974
r = pthread_workqueue_additem_np (qc -> dgq_kworkqueue ,
4020
3975
_dispatch_worker_thread4 , dq , & wh , & gen_cnt );
4021
3976
(void )dispatch_assume_zero (r );
4022
- } while (-- i );
3977
+ } while (-- remaining );
4023
3978
return ;
4024
3979
}
4025
3980
#endif // DISPATCH_USE_LEGACY_WORKQUEUE_FALLBACK
4026
3981
#if HAVE_PTHREAD_WORKQUEUE_QOS
4027
- r = _pthread_workqueue_addthreads (( int ) i ,
3982
+ r = _pthread_workqueue_addthreads (remaining ,
4028
3983
_dispatch_priority_to_pp (dq -> dq_priority ));
4029
3984
#elif HAVE_PTHREAD_WORKQUEUE_SETDISPATCH_NP
4030
3985
r = pthread_workqueue_addthreads_np (qc -> dgq_wq_priority ,
4031
- qc -> dgq_wq_options , ( int ) i );
3986
+ qc -> dgq_wq_options , remaining );
4032
3987
#endif
4033
3988
(void )dispatch_assume_zero (r );
4034
3989
return ;
@@ -4038,28 +3993,43 @@ _dispatch_global_queue_poke_slow(dispatch_queue_t dq, int n)
4038
3993
dispatch_pthread_root_queue_context_t pqc = qc -> dgq_ctxt ;
4039
3994
if (fastpath (pqc -> dpq_thread_mediator .do_vtable )) {
4040
3995
while (dispatch_semaphore_signal (& pqc -> dpq_thread_mediator )) {
4041
- if (!-- i ) {
3996
+ _dispatch_root_queue_debug ("signaled sleeping worker for "
3997
+ "global queue: %p" , dq );
3998
+ if (!-- remaining ) {
4042
3999
return ;
4043
4000
}
4044
4001
}
4045
4002
}
4046
- int32_t j , t_count ;
4003
+
4004
+ bool overcommit = dq -> dq_priority & DISPATCH_PRIORITY_FLAG_OVERCOMMIT ;
4005
+ if (overcommit ) {
4006
+ os_atomic_add2o (qc , dgq_pending , remaining , relaxed );
4007
+ } else {
4008
+ if (!os_atomic_cmpxchg2o (qc , dgq_pending , 0 , remaining , relaxed )) {
4009
+ _dispatch_root_queue_debug ("worker thread request still pending for "
4010
+ "global queue: %p" , dq );
4011
+ return ;
4012
+ }
4013
+ }
4014
+
4015
+ int32_t can_request , t_count ;
4047
4016
// seq_cst with atomic store to tail <rdar://problem/16932833>
4048
4017
t_count = os_atomic_load2o (qc , dgq_thread_pool_size , ordered );
4049
4018
do {
4050
- #if HAVE_INTERNAL_PTHREAD_WORKQUEUE
4051
- bool pool_full = t_count <= 0 ; // oversubscription encoded by negative dgq_thread_pool_size
4052
- #else
4053
- bool pool_full = t_count == 0 ;
4054
- #endif
4055
- if (pool_full ) {
4019
+ can_request = t_count < floor ? 0 : t_count - floor ;
4020
+ if (remaining > can_request ) {
4021
+ _dispatch_root_queue_debug ("pthread pool reducing request from %d to %d" ,
4022
+ remaining , can_request );
4023
+ os_atomic_sub2o (qc , dgq_pending , remaining - can_request , relaxed );
4024
+ remaining = can_request ;
4025
+ }
4026
+ if (remaining == 0 ) {
4056
4027
_dispatch_root_queue_debug ("pthread pool is full for root queue: "
4057
4028
"%p" , dq );
4058
4029
return ;
4059
4030
}
4060
- j = i > t_count ? t_count : i ;
4061
4031
} while (!os_atomic_cmpxchgvw2o (qc , dgq_thread_pool_size , t_count ,
4062
- t_count - j , & t_count , acquire ));
4032
+ t_count - remaining , & t_count , acquire ));
4063
4033
4064
4034
pthread_attr_t * attr = & pqc -> dpq_thread_attr ;
4065
4035
pthread_t tid , * pthr = & tid ;
@@ -4068,30 +4038,41 @@ _dispatch_global_queue_poke_slow(dispatch_queue_t dq, int n)
4068
4038
pthr = _dispatch_mgr_root_queue_init ();
4069
4039
}
4070
4040
#endif
4071
- _dispatch_pthread_root_queue_spawn_workers (dq , attr , j );
4041
+ do {
4042
+ _dispatch_retain (dq );
4043
+ while ((r = pthread_create (pthr , attr , _dispatch_worker_thread , dq ))) {
4044
+ if (r != EAGAIN ) {
4045
+ (void )dispatch_assume_zero (r );
4046
+ }
4047
+ _dispatch_temporary_resource_shortage ();
4048
+ }
4049
+ } while (-- remaining );
4072
4050
#endif // DISPATCH_USE_PTHREAD_POOL
4073
4051
}
4074
4052
4075
4053
DISPATCH_NOINLINE
4076
4054
void
4077
- _dispatch_global_queue_poke (dispatch_queue_t dq , int n )
4055
+ _dispatch_global_queue_poke (dispatch_queue_t dq , int n , int floor )
4078
4056
{
4079
4057
if (!_dispatch_queue_class_probe (dq )) {
4080
4058
return ;
4081
4059
}
4082
4060
#if HAVE_PTHREAD_WORKQUEUES
4083
4061
dispatch_root_queue_context_t qc = dq -> do_ctxt ;
4084
4062
if (
4063
+ #if HAVE_INTERNAL_PTHREAD_WORKQUEUE
4064
+ false && /* counting done in poke_slow for this config */
4065
+ #endif
4085
4066
#if DISPATCH_USE_PTHREAD_POOL
4086
- (qc -> dgq_kworkqueue != (void * )(~0ul )) &&
4067
+ (qc -> dgq_kworkqueue != (void * )(~0ul )) &&
4087
4068
#endif
4088
- !os_atomic_cmpxchg2o (qc , dgq_pending , 0 , n , relaxed )) {
4089
- _dispatch_root_queue_debug ("worker thread request still pending for "
4069
+ !os_atomic_cmpxchg2o (qc , dgq_pending , 0 , n , relaxed )) {
4070
+ _dispatch_root_queue_debug ("worker thread request still pending for "
4090
4071
"global queue: %p" , dq );
4091
4072
return ;
4092
4073
}
4093
4074
#endif // HAVE_PTHREAD_WORKQUEUES
4094
- return _dispatch_global_queue_poke_slow (dq , n );
4075
+ return _dispatch_global_queue_poke_slow (dq , n , floor );
4095
4076
}
4096
4077
4097
4078
#pragma mark -
@@ -5296,7 +5277,7 @@ _dispatch_root_queue_drain_one_slow(dispatch_queue_t dq)
5296
5277
(void )os_atomic_dec2o (qc , dgq_pending , relaxed );
5297
5278
}
5298
5279
if (!available ) {
5299
- _dispatch_global_queue_poke (dq , 1 );
5280
+ _dispatch_global_queue_poke (dq , 1 , 0 );
5300
5281
}
5301
5282
return available ;
5302
5283
}
@@ -5363,7 +5344,7 @@ _dispatch_root_queue_drain_one(dispatch_queue_t dq)
5363
5344
}
5364
5345
5365
5346
os_atomic_store2o (dq , dq_items_head , next , relaxed );
5366
- _dispatch_global_queue_poke (dq , 1 );
5347
+ _dispatch_global_queue_poke (dq , 1 , 0 );
5367
5348
out :
5368
5349
return head ;
5369
5350
}
@@ -5506,6 +5487,9 @@ _dispatch_worker_thread(void *context)
5506
5487
dispatch_root_queue_context_t qc = dq -> do_ctxt ;
5507
5488
dispatch_pthread_root_queue_context_t pqc = qc -> dgq_ctxt ;
5508
5489
5490
+ int pending = (int )os_atomic_dec2o (qc , dgq_pending , relaxed );
5491
+ dispatch_assert (pending >= 0 );
5492
+
5509
5493
if (pqc -> dpq_observer_hooks .queue_will_execute ) {
5510
5494
_dispatch_set_pthread_root_queue_observer_hooks (
5511
5495
& pqc -> dpq_observer_hooks );
@@ -5525,7 +5509,9 @@ _dispatch_worker_thread(void *context)
5525
5509
5526
5510
#if HAVE_INTERNAL_PTHREAD_WORKQUEUE
5527
5511
bool overcommit = qc -> dgq_wq_options & WORKQ_ADDTHREADS_OPTION_OVERCOMMIT ;
5528
- if (!overcommit ) {
5512
+ bool manager = dq == & _dispatch_mgr_root_queue ;
5513
+ bool monitored = !(overcommit || manager );
5514
+ if (monitored ) {
5529
5515
_dispatch_workq_worker_register (dq , qc -> dgq_wq_priority );
5530
5516
}
5531
5517
#endif
@@ -5539,12 +5525,12 @@ _dispatch_worker_thread(void *context)
5539
5525
dispatch_time (0 , timeout )) == 0 );
5540
5526
5541
5527
#if HAVE_INTERNAL_PTHREAD_WORKQUEUE
5542
- if (! overcommit ) {
5528
+ if (monitored ) {
5543
5529
_dispatch_workq_worker_unregister (dq , qc -> dgq_wq_priority );
5544
5530
}
5545
5531
#endif
5546
5532
(void )os_atomic_inc2o (qc , dgq_thread_pool_size , release );
5547
- _dispatch_global_queue_poke (dq , 1 );
5533
+ _dispatch_global_queue_poke (dq , 1 , 0 );
5548
5534
_dispatch_release (dq );
5549
5535
5550
5536
return NULL ;
0 commit comments