Merge branch 'threadpool-sched-getattr-runtime-check' into 'master'

Add runtime checks and a fallback if we can't get the thread scheduler settings

Closes #2007

See merge request GNOME/glib!1327
This commit is contained in:
Philip Withnall 2020-01-20 10:14:11 +00:00
commit 2a0b1d8ba0
6 changed files with 47 additions and 34 deletions

View File

@ -1162,7 +1162,7 @@ g_system_thread_free (GRealThread *thread)
g_slice_free (GThreadPosix, pt); g_slice_free (GThreadPosix, pt);
} }
void gboolean
g_system_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings) g_system_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings)
{ {
/* FIXME: Implement the same for macOS and the BSDs so it doesn't go through /* FIXME: Implement the same for macOS and the BSDs so it doesn't go through
@ -1202,11 +1202,18 @@ g_system_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_sett
} }
else else
{ {
g_error ("Failed to get thread scheduler attributes: %s", g_strerror (errsv)); g_debug ("Failed to get thread scheduler attributes: %s", g_strerror (errsv));
g_free (scheduler_settings->attr);
return FALSE;
} }
} }
} }
while (res == -1); while (res == -1);
return TRUE;
#else
return FALSE;
#endif #endif
} }

View File

@ -428,11 +428,13 @@ g_thread_win32_proxy (gpointer data)
return 0; return 0;
} }
void gboolean
g_system_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings) g_system_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings)
{ {
HANDLE current_thread = GetCurrentThread (); HANDLE current_thread = GetCurrentThread ();
scheduler_settings->thread_prio = GetThreadPriority (current_thread); scheduler_settings->thread_prio = GetThreadPriority (current_thread);
return TRUE;
} }
GRealThread * GRealThread *

View File

@ -902,11 +902,12 @@ g_thread_new_internal (const gchar *name,
name, func, data, error); name, func, data, error);
} }
void gboolean
g_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings) g_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings)
{ {
g_return_if_fail (scheduler_settings != NULL); g_return_val_if_fail (scheduler_settings != NULL, FALSE);
g_system_thread_get_scheduler_settings (scheduler_settings);
return g_system_thread_get_scheduler_settings (scheduler_settings);
} }
/** /**

View File

@ -114,9 +114,9 @@ static gint max_unused_threads = 2;
static gint kill_unused_threads = 0; static gint kill_unused_threads = 0;
static guint max_idle_time = 15 * 1000; static guint max_idle_time = 15 * 1000;
#ifdef HAVE_GTHREAD_SCHEDULER_SETTINGS
static GThreadSchedulerSettings shared_thread_scheduler_settings; static GThreadSchedulerSettings shared_thread_scheduler_settings;
#else static gboolean have_shared_thread_scheduler_settings = FALSE;
typedef struct typedef struct
{ {
/* Either thread or error are set in the end. Both transfer-full. */ /* Either thread or error are set in the end. Both transfer-full. */
@ -127,7 +127,6 @@ typedef struct
static GCond spawn_thread_cond; static GCond spawn_thread_cond;
static GAsyncQueue *spawn_thread_queue; static GAsyncQueue *spawn_thread_queue;
#endif
static void g_thread_pool_queue_push_unlocked (GRealThreadPool *pool, static void g_thread_pool_queue_push_unlocked (GRealThreadPool *pool,
gpointer data); gpointer data);
@ -294,7 +293,6 @@ g_thread_pool_wait_for_new_task (GRealThreadPool *pool)
return task; return task;
} }
#ifndef HAVE_GTHREAD_SCHEDULER_SETTINGS
static gpointer static gpointer
g_thread_pool_spawn_thread (gpointer data) g_thread_pool_spawn_thread (gpointer data)
{ {
@ -326,7 +324,6 @@ g_thread_pool_spawn_thread (gpointer data)
return NULL; return NULL;
} }
#endif
static gpointer static gpointer
g_thread_pool_thread_proxy (gpointer data) g_thread_pool_thread_proxy (gpointer data)
@ -475,23 +472,26 @@ g_thread_pool_start_thread (GRealThreadPool *pool,
* providing them if supported by the GThread implementation or by * providing them if supported by the GThread implementation or by
* going via our helper thread. * going via our helper thread.
*/ */
#ifdef HAVE_GTHREAD_SCHEDULER_SETTINGS if (have_shared_thread_scheduler_settings)
thread = g_thread_new_internal (name, g_thread_proxy, g_thread_pool_thread_proxy, pool, 0, &shared_thread_scheduler_settings, error); {
#else thread = g_thread_new_internal (name, g_thread_proxy, g_thread_pool_thread_proxy, pool, 0, &shared_thread_scheduler_settings, error);
SpawnThreadData spawn_thread_data = { (GThreadPool *) pool, NULL, NULL }; }
else
{
SpawnThreadData spawn_thread_data = { (GThreadPool *) pool, NULL, NULL };
g_async_queue_lock (spawn_thread_queue); g_async_queue_lock (spawn_thread_queue);
g_async_queue_push_unlocked (spawn_thread_queue, &spawn_thread_data); g_async_queue_push_unlocked (spawn_thread_queue, &spawn_thread_data);
while (!spawn_thread_data.thread && !spawn_thread_data.error) while (!spawn_thread_data.thread && !spawn_thread_data.error)
g_cond_wait (&spawn_thread_cond, _g_async_queue_get_mutex (spawn_thread_queue)); g_cond_wait (&spawn_thread_cond, _g_async_queue_get_mutex (spawn_thread_queue));
thread = spawn_thread_data.thread; thread = spawn_thread_data.thread;
if (!thread) if (!thread)
g_propagate_error (error, g_steal_pointer (&spawn_thread_data.error)); g_propagate_error (error, g_steal_pointer (&spawn_thread_data.error));
g_async_queue_unlock (spawn_thread_queue); g_async_queue_unlock (spawn_thread_queue);
#endif }
} }
if (thread == NULL) if (thread == NULL)
@ -605,13 +605,16 @@ g_thread_pool_new (GFunc func,
*/ */
if (!exclusive) if (!exclusive)
{ {
#ifdef HAVE_GTHREAD_SCHEDULER_SETTINGS if (g_thread_get_scheduler_settings (&shared_thread_scheduler_settings))
g_thread_get_scheduler_settings (&shared_thread_scheduler_settings); {
#else have_shared_thread_scheduler_settings = TRUE;
spawn_thread_queue = g_async_queue_new (); }
g_cond_init (&spawn_thread_cond); else
g_thread_new ("pool-spawner", g_thread_pool_spawn_thread, NULL); {
#endif spawn_thread_queue = g_async_queue_new ();
g_cond_init (&spawn_thread_cond);
g_thread_new ("pool-spawner", g_thread_pool_spawn_thread, NULL);
}
} }
} }
G_UNLOCK (init); G_UNLOCK (init);

View File

@ -74,7 +74,7 @@ void g_system_thread_free (GRealThread *thread);
void g_system_thread_exit (void); void g_system_thread_exit (void);
void g_system_thread_set_name (const gchar *name); void g_system_thread_set_name (const gchar *name);
void g_system_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings); gboolean g_system_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings);
/* gthread.c */ /* gthread.c */
GThread *g_thread_new_internal (const gchar *name, GThread *g_thread_new_internal (const gchar *name,
@ -85,7 +85,7 @@ GThread *g_thread_new_internal (const gchar *name,
const GThreadSchedulerSettings *scheduler_settings, const GThreadSchedulerSettings *scheduler_settings,
GError **error); GError **error);
void g_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings); gboolean g_thread_get_scheduler_settings (GThreadSchedulerSettings *scheduler_settings);
gpointer g_thread_proxy (gpointer thread); gpointer g_thread_proxy (gpointer thread);

View File

@ -1731,7 +1731,7 @@ else
glib_conf.set('HAVE_PTHREAD_GETNAME_NP', 1) glib_conf.set('HAVE_PTHREAD_GETNAME_NP', 1)
endif endif
if cc.has_header_symbol('sys/syscall.h', 'SYS_sched_getattr,') if cc.has_header_symbol('sys/syscall.h', 'SYS_sched_getattr')
glib_conf.set('HAVE_SYS_SCHED_GETATTR', 1) glib_conf.set('HAVE_SYS_SCHED_GETATTR', 1)
endif endif