Skip to content

Commit 9a6b76d

Browse files
committed
Basic worker thread prioritization on Linux
1 parent 9208a63 commit 9a6b76d

File tree

1 file changed

+37
-2
lines changed

1 file changed

+37
-2
lines changed

src/queue.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
#include "protocol.h" // _dispatch_send_wakeup_runloop_thread
2424
#endif
2525

26+
#if defined(__linux__)
27+
#include <errno.h>
28+
#include <sys/resource.h>
29+
#endif
30+
2631
static inline void _dispatch_root_queues_init(void);
2732
static void _dispatch_lane_barrier_complete(dispatch_lane_class_t dqu,
2833
dispatch_qos_t qos, dispatch_wakeup_flags_t flags);
@@ -6169,6 +6174,7 @@ _dispatch_root_queue_init_pthread_pool(dispatch_queue_global_t dq,
61696174
}
61706175
if (pool_size && pool_size < thread_pool_size) thread_pool_size = pool_size;
61716176
dq->dgq_thread_pool_size = thread_pool_size;
6177+
// TODO: Save priority for later configuration in _dispatch_worker_thread
61726178
qos_class_t cls = _dispatch_qos_to_qos_class(_dispatch_priority_qos(pri) ?:
61736179
_dispatch_priority_fallback_qos(pri));
61746180
if (cls) {
@@ -6216,10 +6222,39 @@ _dispatch_worker_thread(void *context)
62166222
_dispatch_sigmask();
62176223
#endif
62186224
_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__)
62196256

62206257
const int64_t timeout = 5ull * NSEC_PER_SEC;
6221-
pthread_priority_t pp = _dispatch_get_priority();
6222-
dispatch_priority_t pri = dq->dq_priority;
62236258

62246259
// If the queue is neither
62256260
// - the manager

0 commit comments

Comments
 (0)