diff --git a/glib/gthread-win32.c b/glib/gthread-win32.c index 89df0daa0..9cbe2bcfb 100644 --- a/glib/gthread-win32.c +++ b/glib/gthread-win32.c @@ -439,9 +439,13 @@ g_system_thread_new (GThreadFunc proxy, GThreadWin32 *thread; GRealThread *base_thread; guint ignore; + const gchar *message = NULL; + HANDLE current_thread; + int current_prio; thread = g_slice_new0 (GThreadWin32); thread->proxy = proxy; + thread->handle = (HANDLE) NULL; base_thread = (GRealThread*)thread; base_thread->ref_count = 2; base_thread->ours = TRUE; @@ -450,19 +454,57 @@ g_system_thread_new (GThreadFunc proxy, base_thread->thread.data = data; base_thread->name = g_strdup (name); - thread->handle = (HANDLE) _beginthreadex (NULL, stack_size, g_thread_win32_proxy, thread, 0, &ignore); + thread->handle = (HANDLE) _beginthreadex (NULL, stack_size, g_thread_win32_proxy, thread, + CREATE_SUSPENDED, &ignore); if (thread->handle == NULL) { - gchar *win_error = g_win32_error_message (GetLastError ()); - g_set_error (error, G_THREAD_ERROR, G_THREAD_ERROR_AGAIN, - "Error creating thread: %s", win_error); - g_free (win_error); - g_slice_free (GThreadWin32, thread); - return NULL; + message = "Error creating thread"; + goto error; + } + + /* For thread priority inheritance we need to manually set the thread + * priority of the new thread to the priority of the current thread. We + * also have to start the thread suspended and resume it after actually + * setting the priority here. + * + * On Windows, by default all new threads are created with NORMAL thread + * priority. + */ + + current_thread = GetCurrentThread (); + current_prio = GetThreadPriority (current_thread); + if (current_prio == THREAD_PRIORITY_ERROR_RETURN) + { + message = "Error getting current thread priority"; + goto error; + } + + if (SetThreadPriority (thread->handle, current_prio) == 0) + { + message = "Error setting new thread priority"; + goto error; + } + + if (ResumeThread (thread->handle) == -1) + { + message = "Error resuming new thread"; + goto error; } return (GRealThread *) thread; + +error: + { + gchar *win_error = g_win32_error_message (GetLastError ()); + g_set_error (error, G_THREAD_ERROR, G_THREAD_ERROR_AGAIN, + "%s: %s", message, win_error); + g_free (win_error); + if (thread->handle) + CloseHandle (thread->handle); + g_slice_free (GThreadWin32, thread); + return NULL; + } } void diff --git a/glib/gthread.c b/glib/gthread.c index f8989009a..919b3adf5 100644 --- a/glib/gthread.c +++ b/glib/gthread.c @@ -833,6 +833,14 @@ g_thread_proxy (gpointer data) * To free the struct returned by this function, use g_thread_unref(). * Note that g_thread_join() implicitly unrefs the #GThread as well. * + * New threads by default inherit their scheduler policy (POSIX) or thread + * priority (Windows) of the thread creating the new thread. + * + * This behaviour changed in GLib 2.64: before threads on Windows were not + * inheriting the thread priority but were spawned with the default priority. + * Starting with GLib 2.64 the behaviour is now consistent between Windows and + * POSIX and all threads inherit their parent thread's priority. + * * Returns: the new #GThread * * Since: 2.32