1
0
Fork 0

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>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
This commit is contained in:
Jonas Ådahl 2024-08-20 11:07:29 +02:00 committed by Mingi Sung
parent 081b918bac
commit 36a1a74f7a
Signed by: sungmg
GPG key ID: 41BAFD6FFD8036C5
9 changed files with 106 additions and 9 deletions

View file

@ -609,6 +609,7 @@ init_gpus (MetaBackendNative *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;
@ -669,6 +670,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)
{

View file

@ -108,6 +108,8 @@ typedef struct _MetaKmsImplDevicePrivate
GHashTable *crtc_frames;
gboolean realtime_inhibited_pending_mode_set;
MetaDeadlineTimerState deadline_timer_state;
gboolean sync_file_retrieved;
@ -1734,6 +1736,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;
}
@ -1924,6 +1932,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);
@ -1973,6 +1990,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;
@ -2050,6 +2077,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))
@ -2075,6 +2104,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;
}

View file

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

View file

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

View file

@ -413,6 +413,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)
{

View file

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

View file

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

View file

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

View file

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