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);
|
||||
MetaBackend *backend = META_BACKEND (native);
|
||||
MetaUdev *udev = meta_backend_native_get_udev (native);
|
||||
MetaKms *kms = meta_backend_native_get_kms (native);
|
||||
g_autoptr (GError) local_error = NULL;
|
||||
MetaUdevDeviceType device_type = 0;
|
||||
GList *devices;
|
||||
|
@ -702,6 +703,8 @@ init_gpus (MetaBackendNative *native,
|
|||
|
||||
g_list_free_full (devices, g_object_unref);
|
||||
|
||||
meta_kms_notify_probed (kms);
|
||||
|
||||
if (!meta_backend_is_headless (backend) &&
|
||||
g_list_length (meta_backend_get_gpus (backend)) == 0)
|
||||
{
|
||||
|
|
|
@ -112,6 +112,8 @@ typedef struct _MetaKmsImplDevicePrivate
|
|||
|
||||
GHashTable *crtc_frames;
|
||||
|
||||
gboolean realtime_inhibited_pending_mode_set;
|
||||
|
||||
MetaDeadlineTimerState deadline_timer_state;
|
||||
|
||||
gboolean sync_file_retrieved;
|
||||
|
@ -1969,6 +1971,12 @@ process_mode_set_update (MetaKmsImplDevice *impl_device,
|
|||
feedback = do_process (impl_device, NULL, update, flags);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2159,6 +2167,15 @@ meta_kms_impl_device_finalize (GObject *object)
|
|||
MetaKmsImplDevicePrivate *priv =
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
return TRUE;
|
||||
|
@ -2285,6 +2312,8 @@ meta_kms_impl_device_initable_init (GInitable *initable,
|
|||
MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable);
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
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;
|
||||
|
||||
if (!ensure_device_file (impl_device, error))
|
||||
|
@ -2310,6 +2339,9 @@ meta_kms_impl_device_initable_init (GInitable *initable,
|
|||
|
||||
priv->sync_file = -1;
|
||||
|
||||
meta_thread_inhibit_realtime_in_impl (thread);
|
||||
priv->realtime_inhibited_pending_mode_set = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -172,12 +172,32 @@ meta_kms_impl_finalize (GObject *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
|
||||
meta_kms_impl_class_init (MetaKmsImplClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
MetaThreadImplClass *thread_impl_class = META_THREAD_IMPL_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_kms_impl_finalize;
|
||||
|
||||
thread_impl_class->setup = meta_kms_impl_setup;
|
||||
}
|
||||
|
||||
MetaKmsUpdateFilter *
|
||||
|
|
|
@ -53,6 +53,8 @@ void meta_kms_impl_notify_modes_set (MetaKmsImpl *impl);
|
|||
|
||||
MetaKmsImpl * meta_kms_impl_new (MetaKms *kms);
|
||||
|
||||
void meta_kms_impl_notify_probed (MetaKmsImpl *impl);
|
||||
|
||||
MetaKmsUpdateFilter * meta_kms_impl_add_update_filter (MetaKmsImpl *impl,
|
||||
MetaKmsUpdateFilterFunc func,
|
||||
gpointer user_data);
|
||||
|
|
|
@ -428,6 +428,23 @@ meta_kms_new (MetaBackend *backend,
|
|||
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
|
||||
meta_kms_finalize (GObject *object)
|
||||
{
|
||||
|
|
|
@ -64,6 +64,8 @@ MetaKms * meta_kms_new (MetaBackend *backend,
|
|||
MetaKmsFlags flags,
|
||||
GError **error);
|
||||
|
||||
void meta_kms_notify_probed (MetaKms *kms);
|
||||
|
||||
META_EXPORT_TEST
|
||||
void meta_kms_inhibit_kernel_thread (MetaKms *kms);
|
||||
|
||||
|
|
|
@ -568,6 +568,15 @@ meta_thread_impl_dispatch (MetaThreadImpl *thread_impl)
|
|||
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
|
||||
meta_thread_impl_run (MetaThreadImpl *thread_impl,
|
||||
MetaThreadImplRunFlags flags)
|
||||
|
|
|
@ -38,6 +38,8 @@ G_DECLARE_DERIVABLE_TYPE (MetaThreadImpl, meta_thread_impl,
|
|||
struct _MetaThreadImplClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* setup) (MetaThreadImpl *thread_impl);
|
||||
};
|
||||
|
||||
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_setup (MetaThreadImpl *thread_impl);
|
||||
|
||||
void meta_thread_impl_run (MetaThreadImpl *thread_impl,
|
||||
MetaThreadImplRunFlags flags);
|
||||
|
||||
|
|
|
@ -333,22 +333,28 @@ request_normal_scheduling (MetaThread *thread,
|
|||
}
|
||||
|
||||
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);
|
||||
gboolean should_use_realtime_scheduling = FALSE;
|
||||
|
||||
switch (priv->thread_type)
|
||||
{
|
||||
case META_THREAD_TYPE_USER:
|
||||
break;
|
||||
return FALSE;
|
||||
case META_THREAD_TYPE_KERNEL:
|
||||
if (priv->wants_realtime && priv->kernel.realtime_inhibit_count == 0)
|
||||
should_use_realtime_scheduling = TRUE;
|
||||
break;
|
||||
return priv->wants_realtime;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -417,11 +423,13 @@ thread_impl_func (gpointer user_data)
|
|||
priv->kernel.realtime_inhibit_count = 0;
|
||||
priv->kernel.is_realtime = FALSE;
|
||||
|
||||
meta_thread_impl_setup (impl);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue