|
23 | 23 | #include "protocol.h" // _dispatch_send_wakeup_runloop_thread
|
24 | 24 | #endif
|
25 | 25 |
|
| 26 | +#if defined(__linux__) |
| 27 | +#include <errno.h> |
| 28 | +#include <sys/resource.h> |
| 29 | +#endif |
| 30 | + |
26 | 31 | static inline void _dispatch_root_queues_init(void);
|
27 | 32 | static void _dispatch_lane_barrier_complete(dispatch_lane_class_t dqu,
|
28 | 33 | dispatch_qos_t qos, dispatch_wakeup_flags_t flags);
|
@@ -6169,6 +6174,7 @@ _dispatch_root_queue_init_pthread_pool(dispatch_queue_global_t dq,
|
6169 | 6174 | }
|
6170 | 6175 | if (pool_size && pool_size < thread_pool_size) thread_pool_size = pool_size;
|
6171 | 6176 | dq->dgq_thread_pool_size = thread_pool_size;
|
| 6177 | + // TODO: Save priority for later configuration in _dispatch_worker_thread |
6172 | 6178 | qos_class_t cls = _dispatch_qos_to_qos_class(_dispatch_priority_qos(pri) ?:
|
6173 | 6179 | _dispatch_priority_fallback_qos(pri));
|
6174 | 6180 | if (cls) {
|
@@ -6216,10 +6222,39 @@ _dispatch_worker_thread(void *context)
|
6216 | 6222 | _dispatch_sigmask();
|
6217 | 6223 | #endif
|
6218 | 6224 | _dispatch_introspection_thread_add();
|
| 6225 | + dispatch_priority_t pri = dq->dq_priority; |
| 6226 | + pthread_priority_t pp = _dispatch_get_priority(); |
| 6227 | + |
| 6228 | + // The Linux kernel does not have a direct analogue to the QoS-based |
| 6229 | + // thread policy engine found in XNU. |
| 6230 | + // |
| 6231 | + // We cannot use 'pthread_setschedprio', because all threads with default |
| 6232 | + // scheduling policy (SCHED_OTHER) have the same pthread 'priority'. |
| 6233 | + // For both CFS, which was introduced in Linux 2.6.23, and its successor |
| 6234 | + // EEVDF (since 6.6) 'sched_get_priority_max' and 'sched_get_priority_min' |
| 6235 | + // will just return 0. |
| 6236 | + // |
| 6237 | + // However, as outlined in "man 2 setpriority", the nice value is a |
| 6238 | + // per‐thread attribute: different threads in the same process can have |
| 6239 | + // different nice values. We can thus setup the thread's initial priority |
| 6240 | + // by converting the QoS class and relative priority to a 'nice' value. |
| 6241 | + #if defined(__linux__) |
| 6242 | + pp = _dispatch_priority_to_pp_strip_flags(pri); |
| 6243 | + int nice = _dispatch_pp_to_nice(pp); |
| 6244 | + |
| 6245 | + #if HAVE_PTHREAD_SETNAME_NP |
| 6246 | + pthread_setname_np(pthread_self(), "DispatchWorker"); |
| 6247 | + #endif |
| 6248 | + |
| 6249 | + errno = 0; |
| 6250 | + int rc = setpriority(PRIO_PROCESS, 0, nice); |
| 6251 | + if (rc != -1 || errno == 0) { |
| 6252 | + _dispatch_thread_setspecific(dispatch_priority_key, (void *)(uintptr_t)pp); |
| 6253 | + } |
| 6254 | + |
| 6255 | + #endif // defined(__linux__) |
6219 | 6256 |
|
6220 | 6257 | const int64_t timeout = 5ull * NSEC_PER_SEC;
|
6221 |
| - pthread_priority_t pp = _dispatch_get_priority(); |
6222 |
| - dispatch_priority_t pri = dq->dq_priority; |
6223 | 6258 |
|
6224 | 6259 | // If the queue is neither
|
6225 | 6260 | // - the manager
|
|
0 commit comments