kms: Inhibit real time scheduling until initial mode set
We're already inhibiting real time scheduling when reading new KMS state after hot plugs, as well as when during mode sets, due to the kernel not being able to reliably handle these within the 250 ms limit. However, we didn't do this during initial probing, which meant that occasionally we'd run into these kind of issues during startup. Handle this by always inhibiting real time scheduling up front, and don't uninhibit until all initially discovered device have finished processing their initial mode set. Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3628 Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3960>
This commit is contained in:
parent
d866590b78
commit
d2be0b6950
9 changed files with 106 additions and 9 deletions
|
@ -638,6 +638,7 @@ init_gpus (MetaBackendNative *native,
|
||||||
meta_backend_native_get_instance_private (native);
|
meta_backend_native_get_instance_private (native);
|
||||||
MetaBackend *backend = META_BACKEND (native);
|
MetaBackend *backend = META_BACKEND (native);
|
||||||
MetaUdev *udev = meta_backend_native_get_udev (native);
|
MetaUdev *udev = meta_backend_native_get_udev (native);
|
||||||
|
MetaKms *kms = meta_backend_native_get_kms (native);
|
||||||
g_autoptr (GError) local_error = NULL;
|
g_autoptr (GError) local_error = NULL;
|
||||||
MetaUdevDeviceType device_type = 0;
|
MetaUdevDeviceType device_type = 0;
|
||||||
GList *devices;
|
GList *devices;
|
||||||
|
@ -702,6 +703,8 @@ init_gpus (MetaBackendNative *native,
|
||||||
|
|
||||||
g_list_free_full (devices, g_object_unref);
|
g_list_free_full (devices, g_object_unref);
|
||||||
|
|
||||||
|
meta_kms_notify_probed (kms);
|
||||||
|
|
||||||
if (!meta_backend_is_headless (backend) &&
|
if (!meta_backend_is_headless (backend) &&
|
||||||
g_list_length (meta_backend_get_gpus (backend)) == 0)
|
g_list_length (meta_backend_get_gpus (backend)) == 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -112,6 +112,8 @@ typedef struct _MetaKmsImplDevicePrivate
|
||||||
|
|
||||||
GHashTable *crtc_frames;
|
GHashTable *crtc_frames;
|
||||||
|
|
||||||
|
gboolean realtime_inhibited_pending_mode_set;
|
||||||
|
|
||||||
MetaDeadlineTimerState deadline_timer_state;
|
MetaDeadlineTimerState deadline_timer_state;
|
||||||
|
|
||||||
gboolean sync_file_retrieved;
|
gboolean sync_file_retrieved;
|
||||||
|
@ -1969,6 +1971,12 @@ process_mode_set_update (MetaKmsImplDevice *impl_device,
|
||||||
feedback = do_process (impl_device, NULL, update, flags);
|
feedback = do_process (impl_device, NULL, update, flags);
|
||||||
meta_thread_uninhibit_realtime_in_impl (thread);
|
meta_thread_uninhibit_realtime_in_impl (thread);
|
||||||
|
|
||||||
|
if (priv->realtime_inhibited_pending_mode_set)
|
||||||
|
{
|
||||||
|
priv->realtime_inhibited_pending_mode_set = FALSE;
|
||||||
|
meta_thread_uninhibit_realtime_in_impl (thread);
|
||||||
|
}
|
||||||
|
|
||||||
return feedback;
|
return feedback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2159,6 +2167,15 @@ meta_kms_impl_device_finalize (GObject *object)
|
||||||
MetaKmsImplDevicePrivate *priv =
|
MetaKmsImplDevicePrivate *priv =
|
||||||
meta_kms_impl_device_get_instance_private (impl_device);
|
meta_kms_impl_device_get_instance_private (impl_device);
|
||||||
|
|
||||||
|
if (priv->realtime_inhibited_pending_mode_set)
|
||||||
|
{
|
||||||
|
MetaThreadImpl *thread_impl = META_THREAD_IMPL (priv->impl);
|
||||||
|
MetaThread *thread = meta_thread_impl_get_thread (thread_impl);
|
||||||
|
|
||||||
|
priv->realtime_inhibited_pending_mode_set = FALSE;
|
||||||
|
meta_thread_uninhibit_realtime_in_impl (thread);
|
||||||
|
}
|
||||||
|
|
||||||
meta_kms_impl_remove_impl_device (priv->impl, impl_device);
|
meta_kms_impl_remove_impl_device (priv->impl, impl_device);
|
||||||
|
|
||||||
g_list_free_full (priv->planes, g_object_unref);
|
g_list_free_full (priv->planes, g_object_unref);
|
||||||
|
@ -2208,6 +2225,16 @@ meta_kms_impl_device_init_mode_setting (MetaKmsImplDevice *impl_device,
|
||||||
|
|
||||||
update_connectors (impl_device, drm_resources, 0);
|
update_connectors (impl_device, drm_resources, 0);
|
||||||
|
|
||||||
|
if (!priv->crtcs)
|
||||||
|
{
|
||||||
|
MetaThreadImpl *thread_impl = META_THREAD_IMPL (priv->impl);
|
||||||
|
MetaThread *thread = meta_thread_impl_get_thread (thread_impl);
|
||||||
|
|
||||||
|
g_warn_if_fail (priv->realtime_inhibited_pending_mode_set);
|
||||||
|
meta_thread_uninhibit_realtime_in_impl (thread);
|
||||||
|
priv->realtime_inhibited_pending_mode_set = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
drmModeFreeResources (drm_resources);
|
drmModeFreeResources (drm_resources);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -2285,6 +2312,8 @@ meta_kms_impl_device_initable_init (GInitable *initable,
|
||||||
MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable);
|
MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable);
|
||||||
MetaKmsImplDevicePrivate *priv =
|
MetaKmsImplDevicePrivate *priv =
|
||||||
meta_kms_impl_device_get_instance_private (impl_device);
|
meta_kms_impl_device_get_instance_private (impl_device);
|
||||||
|
MetaThreadImpl *thread_impl = META_THREAD_IMPL (priv->impl);
|
||||||
|
MetaThread *thread = meta_thread_impl_get_thread (thread_impl);
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (!ensure_device_file (impl_device, error))
|
if (!ensure_device_file (impl_device, error))
|
||||||
|
@ -2310,6 +2339,9 @@ meta_kms_impl_device_initable_init (GInitable *initable,
|
||||||
|
|
||||||
priv->sync_file = -1;
|
priv->sync_file = -1;
|
||||||
|
|
||||||
|
meta_thread_inhibit_realtime_in_impl (thread);
|
||||||
|
priv->realtime_inhibited_pending_mode_set = TRUE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,12 +172,32 @@ meta_kms_impl_finalize (GObject *object)
|
||||||
G_OBJECT_CLASS (meta_kms_impl_parent_class)->finalize (object);
|
G_OBJECT_CLASS (meta_kms_impl_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_kms_impl_setup (MetaThreadImpl *thread_impl)
|
||||||
|
{
|
||||||
|
MetaThread *thread = meta_thread_impl_get_thread (thread_impl);
|
||||||
|
|
||||||
|
meta_thread_inhibit_realtime_in_impl (thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_kms_impl_notify_probed (MetaKmsImpl *impl)
|
||||||
|
{
|
||||||
|
MetaThreadImpl *thread_impl = META_THREAD_IMPL (impl);
|
||||||
|
MetaThread *thread = meta_thread_impl_get_thread (thread_impl);
|
||||||
|
|
||||||
|
meta_thread_uninhibit_realtime_in_impl (thread);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_kms_impl_class_init (MetaKmsImplClass *klass)
|
meta_kms_impl_class_init (MetaKmsImplClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
MetaThreadImplClass *thread_impl_class = META_THREAD_IMPL_CLASS (klass);
|
||||||
|
|
||||||
object_class->finalize = meta_kms_impl_finalize;
|
object_class->finalize = meta_kms_impl_finalize;
|
||||||
|
|
||||||
|
thread_impl_class->setup = meta_kms_impl_setup;
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaKmsUpdateFilter *
|
MetaKmsUpdateFilter *
|
||||||
|
|
|
@ -53,6 +53,8 @@ void meta_kms_impl_notify_modes_set (MetaKmsImpl *impl);
|
||||||
|
|
||||||
MetaKmsImpl * meta_kms_impl_new (MetaKms *kms);
|
MetaKmsImpl * meta_kms_impl_new (MetaKms *kms);
|
||||||
|
|
||||||
|
void meta_kms_impl_notify_probed (MetaKmsImpl *impl);
|
||||||
|
|
||||||
MetaKmsUpdateFilter * meta_kms_impl_add_update_filter (MetaKmsImpl *impl,
|
MetaKmsUpdateFilter * meta_kms_impl_add_update_filter (MetaKmsImpl *impl,
|
||||||
MetaKmsUpdateFilterFunc func,
|
MetaKmsUpdateFilterFunc func,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
|
@ -428,6 +428,23 @@ meta_kms_new (MetaBackend *backend,
|
||||||
return kms;
|
return kms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
notify_probed_in_impl (MetaThreadImpl *thread_impl,
|
||||||
|
gpointer user_data,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
meta_kms_impl_notify_probed (META_KMS_IMPL (thread_impl));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_kms_notify_probed (MetaKms *kms)
|
||||||
|
{
|
||||||
|
meta_thread_post_impl_task (META_THREAD (kms),
|
||||||
|
notify_probed_in_impl,
|
||||||
|
NULL, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_kms_finalize (GObject *object)
|
meta_kms_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,6 +64,8 @@ MetaKms * meta_kms_new (MetaBackend *backend,
|
||||||
MetaKmsFlags flags,
|
MetaKmsFlags flags,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
void meta_kms_notify_probed (MetaKms *kms);
|
||||||
|
|
||||||
META_EXPORT_TEST
|
META_EXPORT_TEST
|
||||||
void meta_kms_inhibit_kernel_thread (MetaKms *kms);
|
void meta_kms_inhibit_kernel_thread (MetaKms *kms);
|
||||||
|
|
||||||
|
|
|
@ -568,6 +568,15 @@ meta_thread_impl_dispatch (MetaThreadImpl *thread_impl)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_thread_impl_setup (MetaThreadImpl *thread_impl)
|
||||||
|
{
|
||||||
|
MetaThreadImplClass *klass = META_THREAD_IMPL_GET_CLASS (thread_impl);
|
||||||
|
|
||||||
|
if (klass->setup)
|
||||||
|
klass->setup (thread_impl);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_thread_impl_run (MetaThreadImpl *thread_impl,
|
meta_thread_impl_run (MetaThreadImpl *thread_impl,
|
||||||
MetaThreadImplRunFlags flags)
|
MetaThreadImplRunFlags flags)
|
||||||
|
|
|
@ -38,6 +38,8 @@ G_DECLARE_DERIVABLE_TYPE (MetaThreadImpl, meta_thread_impl,
|
||||||
struct _MetaThreadImplClass
|
struct _MetaThreadImplClass
|
||||||
{
|
{
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
void (* setup) (MetaThreadImpl *thread_impl);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum _MetaThreadTaskFeedbackType
|
typedef enum _MetaThreadTaskFeedbackType
|
||||||
|
@ -70,6 +72,8 @@ void meta_thread_impl_queue_task (MetaThreadImpl *thread_impl,
|
||||||
|
|
||||||
void meta_thread_impl_terminate (MetaThreadImpl *thread_impl);
|
void meta_thread_impl_terminate (MetaThreadImpl *thread_impl);
|
||||||
|
|
||||||
|
void meta_thread_impl_setup (MetaThreadImpl *thread_impl);
|
||||||
|
|
||||||
void meta_thread_impl_run (MetaThreadImpl *thread_impl,
|
void meta_thread_impl_run (MetaThreadImpl *thread_impl,
|
||||||
MetaThreadImplRunFlags flags);
|
MetaThreadImplRunFlags flags);
|
||||||
|
|
||||||
|
|
|
@ -333,22 +333,28 @@ request_normal_scheduling (MetaThread *thread,
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
should_use_realtime_scheduling_in_impl (MetaThread *thread)
|
can_use_realtime_scheduling_in_impl (MetaThread *thread)
|
||||||
{
|
{
|
||||||
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||||
gboolean should_use_realtime_scheduling = FALSE;
|
|
||||||
|
|
||||||
switch (priv->thread_type)
|
switch (priv->thread_type)
|
||||||
{
|
{
|
||||||
case META_THREAD_TYPE_USER:
|
case META_THREAD_TYPE_USER:
|
||||||
break;
|
return FALSE;
|
||||||
case META_THREAD_TYPE_KERNEL:
|
case META_THREAD_TYPE_KERNEL:
|
||||||
if (priv->wants_realtime && priv->kernel.realtime_inhibit_count == 0)
|
return priv->wants_realtime;
|
||||||
should_use_realtime_scheduling = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return should_use_realtime_scheduling;
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
should_use_realtime_scheduling_in_impl (MetaThread *thread)
|
||||||
|
{
|
||||||
|
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||||
|
|
||||||
|
return (can_use_realtime_scheduling_in_impl (thread) &&
|
||||||
|
priv->kernel.realtime_inhibit_count == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -417,11 +423,13 @@ thread_impl_func (gpointer user_data)
|
||||||
priv->kernel.realtime_inhibit_count = 0;
|
priv->kernel.realtime_inhibit_count = 0;
|
||||||
priv->kernel.is_realtime = FALSE;
|
priv->kernel.is_realtime = FALSE;
|
||||||
|
|
||||||
|
meta_thread_impl_setup (impl);
|
||||||
|
|
||||||
sync_realtime_scheduling_in_impl (thread);
|
sync_realtime_scheduling_in_impl (thread);
|
||||||
|
|
||||||
if (priv->kernel.is_realtime)
|
if (can_use_realtime_scheduling_in_impl (thread))
|
||||||
{
|
{
|
||||||
g_message ("Made thread '%s' realtime scheduled", priv->name);
|
g_message ("Thread '%s' will be using real time scheduling", priv->name);
|
||||||
run_flags |= META_THREAD_IMPL_RUN_FLAG_REALTIME;
|
run_flags |= META_THREAD_IMPL_RUN_FLAG_REALTIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue