Skip to content

Commit a3106e0

Browse files
committed
Basic prioritisation on Windows
1 parent 800fcbe commit a3106e0

File tree

2 files changed

+82
-2
lines changed

2 files changed

+82
-2
lines changed

src/queue.c

+59-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,29 @@
2828
#include <sys/resource.h>
2929
#endif
3030

31+
#if defined(_WIN32)
32+
// Needs to be free'd after use
33+
static inline wchar_t *_Nullable _dispatch_char_to_wchar_str(const char *str) {
34+
int wideCharSize = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
35+
if (wideCharSize == 0) {
36+
return NULL;
37+
}
38+
39+
wchar_t* wideCharStr = (wchar_t*)malloc(wideCharSize * sizeof(wchar_t));
40+
if (wideCharStr == NULL) {
41+
return NULL;
42+
}
43+
44+
int result = MultiByteToWideChar(CP_UTF8, 0, str, -1, wideCharStr, wideCharSize);
45+
if (result == 0) {
46+
free(wideCharStr);
47+
return NULL;
48+
}
49+
50+
return wideCharStr;
51+
}
52+
#endif
53+
3154
static inline void _dispatch_root_queues_init(void);
3255
static void _dispatch_lane_barrier_complete(dispatch_lane_class_t dqu,
3356
dispatch_qos_t qos, dispatch_wakeup_flags_t flags);
@@ -6237,21 +6260,47 @@ _dispatch_worker_thread(void *context)
62376260
// per‐thread attribute: different threads in the same process can have
62386261
// different nice values. We can thus setup the thread's initial priority
62396262
// by converting the QoS class and relative priority to a 'nice' value.
6240-
#if defined(__linux__)
6263+
#if defined(__linux__)
62416264
pp = _dispatch_priority_to_pp_strip_flags(pri);
62426265
int nice = _dispatch_pp_to_nice(pp);
62436266

62446267
#if HAVE_PTHREAD_SETNAME_NP
6268+
// pthread thread names are restricted to just 16 characters
6269+
// including NUL. It does not make sense to pass the queue's
6270+
// label as a name.
62456271
pthread_setname_np(pthread_self(), "DispatchWorker");
62466272
#endif
62476273

62486274
errno = 0;
62496275
int rc = setpriority(PRIO_PROCESS, 0, nice);
62506276
if (rc != -1 || errno == 0) {
62516277
_dispatch_thread_setspecific(dispatch_priority_key, (void *)(uintptr_t)pp);
6278+
} else {
6279+
_dispatch_log("Failed to set thread priority for worker thread: pqc=%p errno=%d\n", pqc, errno);
62526280
}
6281+
#elif defined(_WIN32)
6282+
pp = _dispatch_priority_to_pp_strip_flags(pri);
6283+
int win_priority = _dispatch_pp_to_win32_priority(pp);
6284+
6285+
HANDLE current = GetCurrentThread();
62536286

6254-
#endif // defined(__linux__)
6287+
// Set thread description to the label of the root queue
6288+
if (dq->dq_label) {
6289+
wchar_t *desc = _dispatch_char_to_wchar_str(dq->dq_label);
6290+
if (likely(desc != NULL)) {
6291+
SetThreadDescription(current, desc);
6292+
free(desc);
6293+
}
6294+
}
6295+
6296+
int rc = SetThreadPriority(current, win_priority);
6297+
if (rc) {
6298+
_dispatch_thread_setspecific(dispatch_priority_key, (void *)(uintptr_t)pp);
6299+
} else {
6300+
DWORD dwError = GetLastError();
6301+
_dispatch_log("Failed to set thread priority for worker thread: pqc=%p win_priority=%d dwError=%lu\n", pqc, win_priority, dwError);
6302+
}
6303+
#endif
62556304

62566305
const int64_t timeout = 5ull * NSEC_PER_SEC;
62576306

@@ -6292,6 +6341,14 @@ _dispatch_worker_thread(void *context)
62926341
(void)os_atomic_inc2o(dq, dgq_thread_pool_size, release);
62936342
_dispatch_root_queue_poke(dq, 1, 0);
62946343
_dispatch_release(dq); // retained in _dispatch_root_queue_poke_slow
6344+
6345+
#if defined(_WIN32)
6346+
// Make sure to properly end the background processing mode
6347+
if (win_priority == THREAD_MODE_BACKGROUND_BEGIN) {
6348+
SetThreadPriority(current, THREAD_MODE_BACKGROUND_END);
6349+
}
6350+
#endif
6351+
62956352
return NULL;
62966353
}
62976354
#if defined(_WIN32)

src/shims/priority.h

+23
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,29 @@ static inline int _dispatch_pp_to_nice(pthread_priority_t pp)
249249
}
250250
#endif // defined(__linux__)
251251

252+
#if defined(_WIN32)
253+
DISPATCH_ALWAYS_INLINE
254+
static inline int _dispatch_pp_to_win32_priority(pthread_priority_t pp) {
255+
uint32_t qos = _dispatch_qos_from_pp(pp);
256+
257+
switch (qos) {
258+
case DISPATCH_QOS_BACKGROUND:
259+
// Make sure to end background mode before exiting the thread!
260+
return THREAD_MODE_BACKGROUND_BEGIN;
261+
case DISPATCH_QOS_UTILITY:
262+
return THREAD_PRIORITY_BELOW_NORMAL;
263+
case DISPATCH_QOS_DEFAULT:
264+
return THREAD_PRIORITY_NORMAL;
265+
case DISPATCH_QOS_USER_INITIATED:
266+
return THREAD_PRIORITY_ABOVE_NORMAL;
267+
case DISPATCH_QOS_USER_INTERACTIVE:
268+
return THREAD_PRIORITY_HIGHEST;
269+
}
270+
271+
return THREAD_PRIORITY_NORMAL;
272+
}
273+
#endif // defined(_WIN32)
274+
252275

253276
// including maintenance
254277
DISPATCH_ALWAYS_INLINE

0 commit comments

Comments
 (0)