GThread - Inherit parent thread priority by default for new Win32 threads

This is the default behaviour on POSIX and having different behaviour
between the two GThread implementations could lead to subtle problems.
This commit is contained in:
Sebastian Dröge 2019-09-17 17:27:50 +03:00
parent 9ed4b813e5
commit be537d8b51
2 changed files with 57 additions and 7 deletions

View File

@ -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

View File

@ -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