@@ -1740,7 +1740,7 @@ static inline dispatch_priority_t
1740
1740
_dispatch_root_queue_identity_assume (dispatch_queue_t assumed_rq )
1741
1741
{
1742
1742
dispatch_priority_t old_dbp = _dispatch_get_basepri ();
1743
- dispatch_assert (dx_type (assumed_rq ) == DISPATCH_QUEUE_GLOBAL_ROOT_TYPE );
1743
+ dispatch_assert (dx_hastypeflag (assumed_rq , QUEUE_ROOT ) );
1744
1744
_dispatch_reset_basepri (assumed_rq -> dq_priority );
1745
1745
_dispatch_queue_set_current (assumed_rq );
1746
1746
return old_dbp ;
@@ -2108,11 +2108,25 @@ _dispatch_queue_priority_inherit_from_target(dispatch_queue_t dq,
2108
2108
2109
2109
if ((!_dispatch_priority_qos (pri ) || (pri & inherited_flag )) &&
2110
2110
(tpri & rootqueue_flag )) {
2111
+ if (_dispatch_priority_override_qos (pri ) == DISPATCH_QOS_SATURATED ) {
2112
+ pri &= DISPATCH_PRIORITY_OVERRIDE_MASK ;
2113
+ } else {
2114
+ pri = 0 ;
2115
+ }
2111
2116
if (tpri & defaultqueue_flag ) {
2112
- dq -> dq_priority = 0 ;
2117
+ // <rdar://problem/32921639> base queues need to know they target
2118
+ // the default root queue so that _dispatch_queue_override_qos()
2119
+ // in _dispatch_queue_class_wakeup() can fallback to QOS_DEFAULT
2120
+ // if no other priority was provided.
2121
+ pri |= defaultqueue_flag ;
2113
2122
} else {
2114
- dq -> dq_priority = (tpri & ~rootqueue_flag ) | inherited_flag ;
2123
+ pri | = (tpri & ~rootqueue_flag ) | inherited_flag ;
2115
2124
}
2125
+ dq -> dq_priority = pri ;
2126
+ } else if (pri & defaultqueue_flag ) {
2127
+ // the DEFAULTQUEUE flag is only set on queues due to the code above,
2128
+ // and must never be kept if we don't target a global root queue.
2129
+ dq -> dq_priority = (pri & ~defaultqueue_flag );
2116
2130
}
2117
2131
#else
2118
2132
(void )dq ; (void )tq ;
@@ -2272,7 +2286,9 @@ static inline dispatch_qos_t
2272
2286
_dispatch_queue_override_qos (dispatch_queue_class_t dqu , dispatch_qos_t qos )
2273
2287
{
2274
2288
if (dqu ._oq -> oq_priority & DISPATCH_PRIORITY_FLAG_DEFAULTQUEUE ) {
2275
- return qos ;
2289
+ // queues targeting the default root queue use any asynchronous
2290
+ // workitem priority available and fallback to QOS_DEFAULT otherwise.
2291
+ return qos ? qos : DISPATCH_QOS_DEFAULT ;
2276
2292
}
2277
2293
// for asynchronous workitems, queue priority is the floor for overrides
2278
2294
return MAX (qos , _dispatch_priority_qos (dqu ._oq -> oq_priority ));
@@ -2338,14 +2354,20 @@ _dispatch_block_has_private_data(const dispatch_block_t block)
2338
2354
}
2339
2355
2340
2356
DISPATCH_ALWAYS_INLINE DISPATCH_WARN_RESULT
2341
- static inline bool
2342
- _dispatch_block_invoke_should_set_priority (dispatch_block_flags_t flags )
2343
- {
2344
- if (flags & DISPATCH_BLOCK_HAS_PRIORITY ) {
2345
- return (flags & DISPATCH_BLOCK_ENFORCE_QOS_CLASS ) ||
2346
- !(flags & DISPATCH_BLOCK_INHERIT_QOS_CLASS );
2347
- }
2348
- return false;
2357
+ static inline pthread_priority_t
2358
+ _dispatch_block_invoke_should_set_priority (dispatch_block_flags_t flags ,
2359
+ pthread_priority_t new_pri )
2360
+ {
2361
+ pthread_priority_t old_pri , p = 0 ; // 0 means do not change priority.
2362
+ if ((flags & DISPATCH_BLOCK_HAS_PRIORITY )
2363
+ && ((flags & DISPATCH_BLOCK_ENFORCE_QOS_CLASS ) ||
2364
+ !(flags & DISPATCH_BLOCK_INHERIT_QOS_CLASS ))) {
2365
+ old_pri = _dispatch_get_priority ();
2366
+ new_pri &= ~_PTHREAD_PRIORITY_FLAGS_MASK ;
2367
+ p = old_pri & ~_PTHREAD_PRIORITY_FLAGS_MASK ;
2368
+ if (!p || p >= new_pri ) p = 0 ;
2369
+ }
2370
+ return p ;
2349
2371
}
2350
2372
2351
2373
DISPATCH_ALWAYS_INLINE
0 commit comments