From d2be0b6950104dce8a17574bf43837eb57660b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Tue, 20 Aug 2024 11:07:29 +0200 Subject: [PATCH] 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: --- src/backends/native/meta-backend-native.c | 3 ++ src/backends/native/meta-kms-impl-device.c | 32 ++++++++++++++++++++++ src/backends/native/meta-kms-impl.c | 20 ++++++++++++++ src/backends/native/meta-kms-impl.h | 2 ++ src/backends/native/meta-kms.c | 17 ++++++++++++ src/backends/native/meta-kms.h | 2 ++ src/backends/native/meta-thread-impl.c | 9 ++++++ src/backends/native/meta-thread-impl.h | 4 +++ src/backends/native/meta-thread.c | 26 ++++++++++++------ 9 files changed, 106 insertions(+), 9 deletions(-) diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c index c57bea944..dee6f7bbc 100644 --- a/src/backends/native/meta-backend-native.c +++ b/src/backends/native/meta-backend-native.c @@ -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) { diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c index 09c8ecb4d..fb9456080 100644 --- a/src/backends/native/meta-kms-impl-device.c +++ b/src/backends/native/meta-kms-impl-device.c @@ -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; } diff --git a/src/backends/native/meta-kms-impl.c b/src/backends/native/meta-kms-impl.c index 99019ca85..e34af9820 100644 --- a/src/backends/native/meta-kms-impl.c +++ b/src/backends/native/meta-kms-impl.c @@ -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 * diff --git a/src/backends/native/meta-kms-impl.h b/src/backends/native/meta-kms-impl.h index f8379fab2..582bebf5e 100644 --- a/src/backends/native/meta-kms-impl.h +++ b/src/backends/native/meta-kms-impl.h @@ -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); diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c index 32f3a0088..9af95ca9c 100644 --- a/src/backends/native/meta-kms.c +++ b/src/backends/native/meta-kms.c @@ -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) { diff --git a/src/backends/native/meta-kms.h b/src/backends/native/meta-kms.h index 743401406..057c7a234 100644 --- a/src/backends/native/meta-kms.h +++ b/src/backends/native/meta-kms.h @@ -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); diff --git a/src/backends/native/meta-thread-impl.c b/src/backends/native/meta-thread-impl.c index 28ef349f7..d02d49203 100644 --- a/src/backends/native/meta-thread-impl.c +++ b/src/backends/native/meta-thread-impl.c @@ -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) diff --git a/src/backends/native/meta-thread-impl.h b/src/backends/native/meta-thread-impl.h index 2083b3bf1..1837c465c 100644 --- a/src/backends/native/meta-thread-impl.h +++ b/src/backends/native/meta-thread-impl.h @@ -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); diff --git a/src/backends/native/meta-thread.c b/src/backends/native/meta-thread.c index 17cc281ff..f668d1363 100644 --- a/src/backends/native/meta-thread.c +++ b/src/backends/native/meta-thread.c @@ -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; }