mirror of
https://github.com/brl/mutter.git
synced 2025-02-19 22:54:08 +00:00
thread: Introduce kernel thread support
This commit makes it possible to create a MetaThread where the MetaThreadImpl side runs in a real thread, instead of a artificially separated impl context. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This commit is contained in:
parent
4c317eae07
commit
8b612a6150
@ -436,6 +436,7 @@ meta_kms_new (MetaBackend *backend,
|
|||||||
NULL, error,
|
NULL, error,
|
||||||
"backend", backend,
|
"backend", backend,
|
||||||
"name", "KMS thread",
|
"name", "KMS thread",
|
||||||
|
"thread-type", META_THREAD_TYPE_USER,
|
||||||
NULL);
|
NULL);
|
||||||
kms->flags = flags;
|
kms->flags = flags;
|
||||||
|
|
||||||
|
@ -23,7 +23,9 @@
|
|||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
#include "backends/native/meta-thread.h"
|
#include "backends/native/meta-thread-private.h"
|
||||||
|
|
||||||
|
#define META_THREAD_IMPL_TERMINATE ((gpointer) 1)
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -47,6 +49,8 @@ typedef struct _MetaThreadImplPrivate
|
|||||||
{
|
{
|
||||||
MetaThread *thread;
|
MetaThread *thread;
|
||||||
|
|
||||||
|
GMainLoop *loop;
|
||||||
|
|
||||||
gboolean in_impl_task;
|
gboolean in_impl_task;
|
||||||
|
|
||||||
GMainContext *thread_context;
|
GMainContext *thread_context;
|
||||||
@ -202,6 +206,7 @@ meta_thread_impl_finalize (GObject *object)
|
|||||||
MetaThreadImplPrivate *priv =
|
MetaThreadImplPrivate *priv =
|
||||||
meta_thread_impl_get_instance_private (thread_impl);
|
meta_thread_impl_get_instance_private (thread_impl);
|
||||||
|
|
||||||
|
g_clear_pointer (&priv->loop, g_main_loop_unref);
|
||||||
g_clear_pointer (&priv->impl_source, g_source_destroy);
|
g_clear_pointer (&priv->impl_source, g_source_destroy);
|
||||||
g_clear_pointer (&priv->task_queue, g_async_queue_unref);
|
g_clear_pointer (&priv->task_queue, g_async_queue_unref);
|
||||||
g_clear_pointer (&priv->thread_context, g_main_context_unref);
|
g_clear_pointer (&priv->thread_context, g_main_context_unref);
|
||||||
@ -444,13 +449,31 @@ meta_thread_impl_register_fd (MetaThreadImpl *thread_impl,
|
|||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_thread_impl_terminate (MetaThreadImpl *thread_impl)
|
||||||
|
{
|
||||||
|
MetaThreadImplPrivate *priv =
|
||||||
|
meta_thread_impl_get_instance_private (thread_impl);
|
||||||
|
|
||||||
|
g_async_queue_push (priv->task_queue, META_THREAD_IMPL_TERMINATE);
|
||||||
|
g_main_context_wakeup (priv->thread_context);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
meta_thread_impl_is_in_impl (MetaThreadImpl *thread_impl)
|
meta_thread_impl_is_in_impl (MetaThreadImpl *thread_impl)
|
||||||
{
|
{
|
||||||
MetaThreadImplPrivate *priv =
|
MetaThreadImplPrivate *priv =
|
||||||
meta_thread_impl_get_instance_private (thread_impl);
|
meta_thread_impl_get_instance_private (thread_impl);
|
||||||
|
|
||||||
return priv->in_impl_task;
|
switch (meta_thread_get_thread_type (priv->thread))
|
||||||
|
{
|
||||||
|
case META_THREAD_TYPE_USER:
|
||||||
|
return priv->in_impl_task;
|
||||||
|
case META_THREAD_TYPE_KERNEL:
|
||||||
|
return meta_thread_get_thread (priv->thread) == g_thread_self ();
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -477,6 +500,13 @@ meta_thread_impl_dispatch (MetaThreadImpl *thread_impl)
|
|||||||
if (!task)
|
if (!task)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (task == META_THREAD_IMPL_TERMINATE)
|
||||||
|
{
|
||||||
|
if (priv->loop)
|
||||||
|
g_main_loop_quit (priv->loop);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
priv->in_impl_task = TRUE;
|
priv->in_impl_task = TRUE;
|
||||||
retval = task->func (thread_impl, task->user_data, &error);
|
retval = task->func (thread_impl, task->user_data, &error);
|
||||||
|
|
||||||
@ -505,6 +535,18 @@ meta_thread_impl_dispatch (MetaThreadImpl *thread_impl)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_thread_impl_run (MetaThreadImpl *thread_impl)
|
||||||
|
{
|
||||||
|
MetaThreadImplPrivate *priv =
|
||||||
|
meta_thread_impl_get_instance_private (thread_impl);
|
||||||
|
|
||||||
|
meta_assert_in_thread_impl (priv->thread);
|
||||||
|
|
||||||
|
priv->loop = g_main_loop_new (priv->thread_context, FALSE);
|
||||||
|
g_main_loop_run (priv->loop);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_thread_impl_queue_task (MetaThreadImpl *thread_impl,
|
meta_thread_impl_queue_task (MetaThreadImpl *thread_impl,
|
||||||
MetaThreadTask *task)
|
MetaThreadTask *task)
|
||||||
|
@ -65,6 +65,10 @@ GSource * meta_thread_impl_register_fd (MetaThreadImpl *thread_impl,
|
|||||||
void meta_thread_impl_queue_task (MetaThreadImpl *thread_impl,
|
void meta_thread_impl_queue_task (MetaThreadImpl *thread_impl,
|
||||||
MetaThreadTask *task);
|
MetaThreadTask *task);
|
||||||
|
|
||||||
|
void meta_thread_impl_terminate (MetaThreadImpl *thread_impl);
|
||||||
|
|
||||||
|
void meta_thread_impl_run (MetaThreadImpl *thread_impl);
|
||||||
|
|
||||||
int meta_thread_impl_dispatch (MetaThreadImpl *thread_impl);
|
int meta_thread_impl_dispatch (MetaThreadImpl *thread_impl);
|
||||||
|
|
||||||
gboolean meta_thread_impl_is_in_impl (MetaThreadImpl *thread_impl);
|
gboolean meta_thread_impl_is_in_impl (MetaThreadImpl *thread_impl);
|
||||||
|
@ -28,4 +28,9 @@ META_EXPORT_TEST
|
|||||||
void meta_thread_class_register_impl_type (MetaThreadClass *thread_class,
|
void meta_thread_class_register_impl_type (MetaThreadClass *thread_class,
|
||||||
GType impl_type);
|
GType impl_type);
|
||||||
|
|
||||||
|
META_EXPORT_TEST
|
||||||
|
MetaThreadType meta_thread_get_thread_type (MetaThread *thread);
|
||||||
|
|
||||||
|
GThread * meta_thread_get_thread (MetaThread *thread);
|
||||||
|
|
||||||
#endif /* META_THREAD_PRIVATE_H */
|
#endif /* META_THREAD_PRIVATE_H */
|
||||||
|
@ -25,12 +25,15 @@
|
|||||||
#include "backends/meta-backend-types.h"
|
#include "backends/meta-backend-types.h"
|
||||||
#include "backends/native/meta-thread-impl.h"
|
#include "backends/native/meta-thread-impl.h"
|
||||||
|
|
||||||
|
#include "meta-private-enum-types.h"
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
|
|
||||||
PROP_BACKEND,
|
PROP_BACKEND,
|
||||||
PROP_NAME,
|
PROP_NAME,
|
||||||
|
PROP_THREAD_TYPE,
|
||||||
|
|
||||||
N_PROPS
|
N_PROPS
|
||||||
};
|
};
|
||||||
@ -57,6 +60,13 @@ typedef struct _MetaThreadPrivate
|
|||||||
GMutex callbacks_mutex;
|
GMutex callbacks_mutex;
|
||||||
GList *pending_callbacks;
|
GList *pending_callbacks;
|
||||||
guint callbacks_source_id;
|
guint callbacks_source_id;
|
||||||
|
|
||||||
|
MetaThreadType thread_type;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
GThread *thread;
|
||||||
|
GMutex init_mutex;
|
||||||
|
} kernel;
|
||||||
} MetaThreadPrivate;
|
} MetaThreadPrivate;
|
||||||
|
|
||||||
typedef struct _MetaThreadClassPrivate
|
typedef struct _MetaThreadClassPrivate
|
||||||
@ -98,6 +108,9 @@ meta_thread_get_property (GObject *object,
|
|||||||
case PROP_NAME:
|
case PROP_NAME:
|
||||||
g_value_set_string (value, priv->name);
|
g_value_set_string (value, priv->name);
|
||||||
break;
|
break;
|
||||||
|
case PROP_THREAD_TYPE:
|
||||||
|
g_value_set_enum (value, priv->thread_type);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -121,12 +134,29 @@ meta_thread_set_property (GObject *object,
|
|||||||
case PROP_NAME:
|
case PROP_NAME:
|
||||||
priv->name = g_value_dup_string (value);
|
priv->name = g_value_dup_string (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_THREAD_TYPE:
|
||||||
|
priv->thread_type = g_value_get_enum (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
thread_impl_func (gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaThread *thread = META_THREAD (user_data);
|
||||||
|
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||||
|
|
||||||
|
g_mutex_lock (&priv->kernel.init_mutex);
|
||||||
|
g_mutex_unlock (&priv->kernel.init_mutex);
|
||||||
|
|
||||||
|
meta_thread_impl_run (priv->impl);
|
||||||
|
|
||||||
|
return GINT_TO_POINTER (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_thread_initable_init (GInitable *initable,
|
meta_thread_initable_init (GInitable *initable,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
@ -142,7 +172,15 @@ meta_thread_initable_init (GInitable *initable,
|
|||||||
|
|
||||||
priv->main_context = g_main_context_default ();
|
priv->main_context = g_main_context_default ();
|
||||||
|
|
||||||
thread_context = g_main_context_ref (priv->main_context);
|
switch (priv->thread_type)
|
||||||
|
{
|
||||||
|
case META_THREAD_TYPE_USER:
|
||||||
|
thread_context = g_main_context_ref (priv->main_context);
|
||||||
|
break;
|
||||||
|
case META_THREAD_TYPE_KERNEL:
|
||||||
|
thread_context = g_main_context_new ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
g_assert (g_type_is_a (class_priv->impl_type, META_TYPE_THREAD_IMPL));
|
g_assert (g_type_is_a (class_priv->impl_type, META_TYPE_THREAD_IMPL));
|
||||||
priv->impl = g_object_new (class_priv->impl_type,
|
priv->impl = g_object_new (class_priv->impl_type,
|
||||||
@ -150,6 +188,20 @@ meta_thread_initable_init (GInitable *initable,
|
|||||||
"main-context", thread_context,
|
"main-context", thread_context,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
switch (priv->thread_type)
|
||||||
|
{
|
||||||
|
case META_THREAD_TYPE_USER:
|
||||||
|
break;
|
||||||
|
case META_THREAD_TYPE_KERNEL:
|
||||||
|
g_mutex_init (&priv->kernel.init_mutex);
|
||||||
|
g_mutex_lock (&priv->kernel.init_mutex);
|
||||||
|
priv->kernel.thread = g_thread_new (priv->name,
|
||||||
|
thread_impl_func,
|
||||||
|
thread);
|
||||||
|
g_mutex_unlock (&priv->kernel.init_mutex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,13 +211,42 @@ initable_iface_init (GInitableIface *initable_iface)
|
|||||||
initable_iface->init = meta_thread_initable_init;
|
initable_iface->init = meta_thread_initable_init;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
finalize_thread_user (MetaThread *thread)
|
||||||
|
{
|
||||||
|
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||||
|
|
||||||
|
while (meta_thread_impl_dispatch (priv->impl) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
finalize_thread_kernel (MetaThread *thread)
|
||||||
|
{
|
||||||
|
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||||
|
|
||||||
|
meta_thread_impl_terminate (priv->impl);
|
||||||
|
g_thread_join (priv->kernel.thread);
|
||||||
|
priv->kernel.thread = NULL;
|
||||||
|
g_mutex_clear (&priv->kernel.init_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_thread_finalize (GObject *object)
|
meta_thread_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
MetaThread *thread = META_THREAD (object);
|
MetaThread *thread = META_THREAD (object);
|
||||||
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||||
|
|
||||||
while (meta_thread_impl_dispatch (priv->impl) > 0);
|
switch (priv->thread_type)
|
||||||
|
{
|
||||||
|
case META_THREAD_TYPE_USER:
|
||||||
|
finalize_thread_user (thread);
|
||||||
|
break;
|
||||||
|
case META_THREAD_TYPE_KERNEL:
|
||||||
|
finalize_thread_kernel (thread);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
meta_thread_flush_callbacks (thread);
|
meta_thread_flush_callbacks (thread);
|
||||||
|
|
||||||
g_clear_object (&priv->impl);
|
g_clear_object (&priv->impl);
|
||||||
@ -203,6 +284,16 @@ meta_thread_class_init (MetaThreadClass *klass)
|
|||||||
G_PARAM_CONSTRUCT_ONLY |
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
G_PARAM_STATIC_STRINGS);
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
obj_props[PROP_THREAD_TYPE] =
|
||||||
|
g_param_spec_enum ("thread-type",
|
||||||
|
"thread-type",
|
||||||
|
"Type of thread",
|
||||||
|
META_TYPE_THREAD_TYPE,
|
||||||
|
META_THREAD_TYPE_KERNEL,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
g_object_class_install_properties (object_class, N_PROPS, obj_props);
|
g_object_class_install_properties (object_class, N_PROPS, obj_props);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,12 +408,16 @@ typedef struct _MetaSyncTaskData
|
|||||||
gboolean done;
|
gboolean done;
|
||||||
GError *error;
|
GError *error;
|
||||||
gpointer retval;
|
gpointer retval;
|
||||||
|
struct {
|
||||||
|
GMutex mutex;
|
||||||
|
GCond cond;
|
||||||
|
} kernel;
|
||||||
} MetaSyncTaskData;
|
} MetaSyncTaskData;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sync_task_done_in_impl (gpointer retval,
|
sync_task_done_user_in_impl (gpointer retval,
|
||||||
const GError *error,
|
const GError *error,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MetaSyncTaskData *data = user_data;
|
MetaSyncTaskData *data = user_data;
|
||||||
|
|
||||||
@ -331,18 +426,18 @@ sync_task_done_in_impl (gpointer retval,
|
|||||||
data->error = error ? g_error_copy (error) : NULL;
|
data->error = error ? g_error_copy (error) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
gpointer
|
static gpointer
|
||||||
meta_thread_run_impl_task_sync (MetaThread *thread,
|
run_impl_task_sync_user (MetaThread *thread,
|
||||||
MetaThreadTaskFunc func,
|
MetaThreadTaskFunc func,
|
||||||
gpointer user_data,
|
gpointer user_data,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||||
MetaThreadTask *task;
|
MetaThreadTask *task;
|
||||||
MetaSyncTaskData data = { 0 };
|
MetaSyncTaskData data = { 0 };
|
||||||
|
|
||||||
task = meta_thread_task_new (func, user_data,
|
task = meta_thread_task_new (func, user_data,
|
||||||
sync_task_done_in_impl, &data,
|
sync_task_done_user_in_impl, &data,
|
||||||
META_THREAD_TASK_FEEDBACK_TYPE_IMPL);
|
META_THREAD_TASK_FEEDBACK_TYPE_IMPL);
|
||||||
meta_thread_impl_queue_task (priv->impl, task);
|
meta_thread_impl_queue_task (priv->impl, task);
|
||||||
|
|
||||||
@ -359,6 +454,77 @@ meta_thread_run_impl_task_sync (MetaThread *thread,
|
|||||||
return data.retval;
|
return data.retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sync_task_done_kernel_in_impl (gpointer retval,
|
||||||
|
const GError *error,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaSyncTaskData *data = user_data;
|
||||||
|
|
||||||
|
g_mutex_lock (&data->kernel.mutex);
|
||||||
|
data->done = TRUE;
|
||||||
|
data->retval = retval;
|
||||||
|
data->error = error ? g_error_copy (error) : NULL;
|
||||||
|
g_cond_signal (&data->kernel.cond);
|
||||||
|
g_mutex_unlock (&data->kernel.mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
run_impl_task_sync_kernel (MetaThread *thread,
|
||||||
|
MetaThreadTaskFunc func,
|
||||||
|
gpointer user_data,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||||
|
MetaThreadTask *task;
|
||||||
|
MetaSyncTaskData data = { 0 };
|
||||||
|
|
||||||
|
g_mutex_init (&data.kernel.mutex);
|
||||||
|
g_cond_init (&data.kernel.cond);
|
||||||
|
|
||||||
|
g_mutex_lock (&data.kernel.mutex);
|
||||||
|
priv->waiting_for_impl_task = TRUE;
|
||||||
|
|
||||||
|
task = meta_thread_task_new (func, user_data,
|
||||||
|
sync_task_done_kernel_in_impl, &data,
|
||||||
|
META_THREAD_TASK_FEEDBACK_TYPE_IMPL);
|
||||||
|
meta_thread_impl_queue_task (priv->impl, task);
|
||||||
|
|
||||||
|
while (!data.done)
|
||||||
|
g_cond_wait (&data.kernel.cond, &data.kernel.mutex);
|
||||||
|
priv->waiting_for_impl_task = FALSE;
|
||||||
|
g_mutex_unlock (&data.kernel.mutex);
|
||||||
|
|
||||||
|
g_mutex_clear (&data.kernel.mutex);
|
||||||
|
g_cond_clear (&data.kernel.cond);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
*error = data.error;
|
||||||
|
else
|
||||||
|
g_clear_error (&data.error);
|
||||||
|
|
||||||
|
return data.retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpointer
|
||||||
|
meta_thread_run_impl_task_sync (MetaThread *thread,
|
||||||
|
MetaThreadTaskFunc func,
|
||||||
|
gpointer user_data,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||||
|
|
||||||
|
switch (priv->thread_type)
|
||||||
|
{
|
||||||
|
case META_THREAD_TYPE_USER:
|
||||||
|
return run_impl_task_sync_user (thread, func, user_data, error);
|
||||||
|
case META_THREAD_TYPE_KERNEL:
|
||||||
|
return run_impl_task_sync_kernel (thread, func, user_data, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_thread_post_impl_task (MetaThread *thread,
|
meta_thread_post_impl_task (MetaThread *thread,
|
||||||
MetaThreadTaskFunc func,
|
MetaThreadTaskFunc func,
|
||||||
@ -391,6 +557,24 @@ meta_thread_get_name (MetaThread *thread)
|
|||||||
return priv->name;
|
return priv->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetaThreadType
|
||||||
|
meta_thread_get_thread_type (MetaThread *thread)
|
||||||
|
{
|
||||||
|
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||||
|
|
||||||
|
return priv->thread_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
GThread *
|
||||||
|
meta_thread_get_thread (MetaThread *thread)
|
||||||
|
{
|
||||||
|
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||||
|
|
||||||
|
g_assert (priv->thread_type == META_THREAD_TYPE_KERNEL);
|
||||||
|
|
||||||
|
return priv->kernel.thread;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
meta_thread_is_in_impl_task (MetaThread *thread)
|
meta_thread_is_in_impl_task (MetaThread *thread)
|
||||||
{
|
{
|
||||||
|
@ -27,6 +27,12 @@
|
|||||||
|
|
||||||
typedef struct _MetaThreadImpl MetaThreadImpl;
|
typedef struct _MetaThreadImpl MetaThreadImpl;
|
||||||
|
|
||||||
|
typedef enum _MetaThreadType
|
||||||
|
{
|
||||||
|
META_THREAD_TYPE_KERNEL,
|
||||||
|
META_THREAD_TYPE_USER,
|
||||||
|
} MetaThreadType;
|
||||||
|
|
||||||
#define META_TYPE_THREAD (meta_thread_get_type ())
|
#define META_TYPE_THREAD (meta_thread_get_type ())
|
||||||
META_EXPORT_TEST
|
META_EXPORT_TEST
|
||||||
G_DECLARE_DERIVABLE_TYPE (MetaThread, meta_thread,
|
G_DECLARE_DERIVABLE_TYPE (MetaThread, meta_thread,
|
||||||
|
@ -840,6 +840,7 @@ if have_native_backend
|
|||||||
'backends/native/meta-stage-native.h',
|
'backends/native/meta-stage-native.h',
|
||||||
'backends/native/meta-thread-impl.c',
|
'backends/native/meta-thread-impl.c',
|
||||||
'backends/native/meta-thread-impl.h',
|
'backends/native/meta-thread-impl.h',
|
||||||
|
'backends/native/meta-thread-private.h',
|
||||||
'backends/native/meta-thread.c',
|
'backends/native/meta-thread.c',
|
||||||
'backends/native/meta-thread.h',
|
'backends/native/meta-thread.h',
|
||||||
'backends/native/meta-thread-private.h',
|
'backends/native/meta-thread-private.h',
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <glib-unix.h>
|
#include <glib-unix.h>
|
||||||
|
|
||||||
#include "backends/native/meta-thread.h"
|
|
||||||
#include "backends/native/meta-thread-impl.h"
|
#include "backends/native/meta-thread-impl.h"
|
||||||
|
#include "backends/native/meta-thread-private.h"
|
||||||
#include "meta-test/meta-context-test.h"
|
#include "meta-test/meta-context-test.h"
|
||||||
#include "tests/meta-thread-impl-test.h"
|
#include "tests/meta-thread-impl-test.h"
|
||||||
#include "tests/meta-thread-test.h"
|
#include "tests/meta-thread-test.h"
|
||||||
@ -156,6 +156,7 @@ register_fd_func (MetaThreadImpl *thread_impl,
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
MetaThread *thread;
|
||||||
GMainLoop *loop;
|
GMainLoop *loop;
|
||||||
|
|
||||||
int state;
|
int state;
|
||||||
@ -186,8 +187,9 @@ idle_data_destroy (gpointer user_data)
|
|||||||
{
|
{
|
||||||
IdleData *idle_data = user_data;
|
IdleData *idle_data = user_data;
|
||||||
|
|
||||||
/* XXX: This can only be checked on kernel type threads. */
|
if (meta_thread_get_thread_type (idle_data->thread) ==
|
||||||
/* meta_assert_in_thread_impl (test_thread); */
|
META_THREAD_TYPE_KERNEL)
|
||||||
|
meta_assert_in_thread_impl (test_thread);
|
||||||
|
|
||||||
g_assert_cmpint (idle_data->state, ==, 2);
|
g_assert_cmpint (idle_data->state, ==, 2);
|
||||||
idle_data->state = 3;
|
idle_data->state = 3;
|
||||||
@ -471,6 +473,7 @@ run_thread_tests (MetaThread *thread)
|
|||||||
/* Test idle source */
|
/* Test idle source */
|
||||||
g_debug ("Test idle source");
|
g_debug ("Test idle source");
|
||||||
idle_data = (IdleData) { 0 };
|
idle_data = (IdleData) { 0 };
|
||||||
|
idle_data.thread = thread;
|
||||||
idle_data.loop = g_main_loop_new (NULL, FALSE);
|
idle_data.loop = g_main_loop_new (NULL, FALSE);
|
||||||
meta_thread_run_impl_task_sync (thread, add_idle_func, &idle_data, NULL);
|
meta_thread_run_impl_task_sync (thread, add_idle_func, &idle_data, NULL);
|
||||||
g_main_loop_run (idle_data.loop);
|
g_main_loop_run (idle_data.loop);
|
||||||
@ -553,6 +556,7 @@ meta_test_thread_user_common (void)
|
|||||||
NULL, &error,
|
NULL, &error,
|
||||||
"backend", backend,
|
"backend", backend,
|
||||||
"name", "test user thread",
|
"name", "test user thread",
|
||||||
|
"thread-type", META_THREAD_TYPE_USER,
|
||||||
NULL);
|
NULL);
|
||||||
g_object_add_weak_pointer (G_OBJECT (thread), (gpointer *) &thread);
|
g_object_add_weak_pointer (G_OBJECT (thread), (gpointer *) &thread);
|
||||||
g_assert_nonnull (thread);
|
g_assert_nonnull (thread);
|
||||||
@ -568,6 +572,33 @@ meta_test_thread_user_common (void)
|
|||||||
test_thread = NULL;
|
test_thread = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_test_thread_kernel_common (void)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_context_get_backend (test_context);
|
||||||
|
MetaThread *thread;
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
|
||||||
|
thread = g_initable_new (META_TYPE_THREAD_TEST,
|
||||||
|
NULL, &error,
|
||||||
|
"backend", backend,
|
||||||
|
"name", "test kernel thread",
|
||||||
|
"thread-type", META_THREAD_TYPE_KERNEL,
|
||||||
|
NULL);
|
||||||
|
g_object_add_weak_pointer (G_OBJECT (thread), (gpointer *) &thread);
|
||||||
|
g_assert_nonnull (thread);
|
||||||
|
g_assert_null (error);
|
||||||
|
g_assert (meta_thread_get_backend (thread) == backend);
|
||||||
|
g_assert_cmpstr (meta_thread_get_name (thread), ==, "test kernel thread");
|
||||||
|
test_thread = thread;
|
||||||
|
|
||||||
|
run_thread_tests (thread);
|
||||||
|
|
||||||
|
g_object_unref (thread);
|
||||||
|
g_assert_null (thread);
|
||||||
|
test_thread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static gpointer
|
static gpointer
|
||||||
late_callback (MetaThreadImpl *thread_impl,
|
late_callback (MetaThreadImpl *thread_impl,
|
||||||
gpointer user_data,
|
gpointer user_data,
|
||||||
@ -581,7 +612,7 @@ late_callback (MetaThreadImpl *thread_impl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_test_thread_user_late_callbacks (void)
|
meta_test_thread_late_callbacks_common (MetaThreadType thread_type)
|
||||||
{
|
{
|
||||||
MetaBackend *backend = meta_context_get_backend (test_context);
|
MetaBackend *backend = meta_context_get_backend (test_context);
|
||||||
MetaThread *thread;
|
MetaThread *thread;
|
||||||
@ -592,6 +623,7 @@ meta_test_thread_user_late_callbacks (void)
|
|||||||
NULL, &error,
|
NULL, &error,
|
||||||
"backend", backend,
|
"backend", backend,
|
||||||
"name", "test late callback",
|
"name", "test late callback",
|
||||||
|
"thread-type", thread_type,
|
||||||
NULL);
|
NULL);
|
||||||
g_object_add_weak_pointer (G_OBJECT (thread), (gpointer *) &thread);
|
g_object_add_weak_pointer (G_OBJECT (thread), (gpointer *) &thread);
|
||||||
g_assert_nonnull (thread);
|
g_assert_nonnull (thread);
|
||||||
@ -604,13 +636,29 @@ meta_test_thread_user_late_callbacks (void)
|
|||||||
g_assert_true (done);
|
g_assert_true (done);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_test_thread_user_late_callbacks (void)
|
||||||
|
{
|
||||||
|
meta_test_thread_late_callbacks_common (META_THREAD_TYPE_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_test_thread_kernel_late_callbacks (void)
|
||||||
|
{
|
||||||
|
meta_test_thread_late_callbacks_common (META_THREAD_TYPE_KERNEL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_tests (void)
|
init_tests (void)
|
||||||
{
|
{
|
||||||
g_test_add_func ("/backends/native/thread/user/common",
|
g_test_add_func ("/backends/native/thread/user/common",
|
||||||
meta_test_thread_user_common);
|
meta_test_thread_user_common);
|
||||||
|
g_test_add_func ("/backends/native/thread/kernel/common",
|
||||||
|
meta_test_thread_kernel_common);
|
||||||
g_test_add_func ("/backends/native/thread/user/late-callbacks",
|
g_test_add_func ("/backends/native/thread/user/late-callbacks",
|
||||||
meta_test_thread_user_late_callbacks);
|
meta_test_thread_user_late_callbacks);
|
||||||
|
g_test_add_func ("/backends/native/thread/kernel/late-callbacks",
|
||||||
|
meta_test_thread_kernel_late_callbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
Loading…
x
Reference in New Issue
Block a user