@@ -265,6 +265,10 @@ static constexpr size_t globalQueueCacheCount =
265265 static_cast <size_t >(JobPriority::UserInteractive) + 1 ;
266266static std::atomic<dispatch_queue_t > globalQueueCache[globalQueueCacheCount];
267267
268+ #ifndef __APPLE__
269+ extern " C" void dispatch_queue_set_width (dispatch_queue_t dq, long width);
270+ #endif
271+
268272static dispatch_queue_t getGlobalQueue (JobPriority priority) {
269273 size_t numericPriority = static_cast <size_t >(priority);
270274 if (numericPriority >= globalQueueCacheCount)
@@ -275,6 +279,25 @@ static dispatch_queue_t getGlobalQueue(JobPriority priority) {
275279 if (SWIFT_LIKELY (queue))
276280 return queue;
277281
282+ #ifndef __APPLE__
283+ const int DISPATCH_QUEUE_WIDTH_MAX_LOGICAL_CPUS = -3 ;
284+
285+ // Create a new cooperative concurrent queue and swap it in.
286+ dispatch_queue_attr_t newQueueAttr = dispatch_queue_attr_make_with_qos_class (
287+ DISPATCH_QUEUE_CONCURRENT, (dispatch_qos_class_t )priority, 0 );
288+ dispatch_queue_t newQueue = dispatch_queue_create (
289+ " Swift global concurrent queue" , newQueueAttr);
290+ dispatch_queue_set_width (newQueue, DISPATCH_QUEUE_WIDTH_MAX_LOGICAL_CPUS);
291+
292+ if (!ptr->compare_exchange_strong (queue, newQueue,
293+ /* success*/ std::memory_order_release,
294+ /* failure*/ std::memory_order_acquire)) {
295+ dispatch_release (newQueue);
296+ return queue;
297+ }
298+
299+ return newQueue;
300+ #else
278301 // If we don't have a queue cached for this priority, cache it now. This may
279302 // race with other threads doing this at the same time for this priority, but
280303 // that's OK, they'll all end up writing the same value.
@@ -284,6 +307,7 @@ static dispatch_queue_t getGlobalQueue(JobPriority priority) {
284307 // Unconditionally store it back in the cache. If we raced with another
285308 // thread, we'll just overwrite the entry with the same value.
286309 ptr->store (queue, std::memory_order_relaxed);
310+ #endif
287311
288312 return queue;
289313}
0 commit comments