From 105a3d60df5df74fd7ea78cacc0d9ca30607b45a Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 10 Oct 2023 14:48:55 -0400 Subject: [PATCH 4/4] kms/impl-device: Inhibit real-time scheduling when mode setting Certain kernel drivers can take an unreasonably long time to complete mode setting operations. That excessive CPU time is charged to the process's rlimits which can lead to the process getting killed if the thread is a real-time thread. This commit inhibits real-time scheduling around mode setting commits, since those commits are the ones currently presenting as excessively slow. Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3037 --- src/backends/native/meta-kms-impl-device.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c index da372383d..d53552704 100644 --- a/src/backends/native/meta-kms-impl-device.c +++ b/src/backends/native/meta-kms-impl-device.c @@ -1554,141 +1554,154 @@ meta_kms_impl_device_schedule_process (MetaKmsImplDevice *impl_device, if (crtc_frame->await_flush) return; if (!is_using_deadline_timer (impl_device)) goto needs_flush; if (crtc_frame->pending_page_flip) return; if (ensure_deadline_timer_armed (impl_device, crtc_frame, &error)) return; if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) g_warning ("Failed to determine deadline: %s", error->message); priv = meta_kms_impl_device_get_instance_private (impl_device); priv->deadline_timer_inhibited = TRUE; needs_flush: meta_kms_device_set_needs_flush (meta_kms_crtc_get_device (crtc), crtc); } static MetaKmsFeedback * process_mode_set_update (MetaKmsImplDevice *impl_device, MetaKmsUpdate *update, MetaKmsUpdateFlag flags) { MetaKmsImplDevicePrivate *priv = meta_kms_impl_device_get_instance_private (impl_device); + MetaKmsImpl *kms_impl = meta_kms_impl_device_get_impl (impl_device); + MetaThreadImpl *thread_impl = META_THREAD_IMPL (kms_impl); + MetaThread *thread = meta_thread_impl_get_thread (thread_impl); + MetaKmsFeedback *feedback; CrtcFrame *crtc_frame; GList *l; GHashTableIter iter; for (l = meta_kms_update_get_mode_sets (update); l; l = l->next) { MetaKmsModeSet *mode_set = l->data; MetaKmsCrtc *crtc = mode_set->crtc; crtc_frame = get_crtc_frame (impl_device, crtc); if (!crtc_frame) continue; if (!crtc_frame->pending_update) continue; meta_kms_update_merge_from (update, crtc_frame->pending_update); g_clear_pointer (&crtc_frame->pending_update, meta_kms_update_free); } g_hash_table_iter_init (&iter, priv->crtc_frames); while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &crtc_frame)) { crtc_frame->deadline.is_deadline_page_flip = FALSE; crtc_frame->await_flush = FALSE; crtc_frame->pending_page_flip = FALSE; g_clear_pointer (&crtc_frame->pending_update, meta_kms_update_free); disarm_crtc_frame_deadline_timer (crtc_frame); } - return do_process (impl_device, NULL, update, flags); + meta_thread_inhibit_realtime_in_impl (thread); + feedback = do_process (impl_device, NULL, update, flags); + meta_thread_uninhibit_realtime_in_impl (thread); + + return feedback; } MetaKmsFeedback * meta_kms_impl_device_process_update (MetaKmsImplDevice *impl_device, MetaKmsUpdate *update, MetaKmsUpdateFlag flags) { g_autoptr (GError) error = NULL; if (!ensure_device_file (impl_device, &error)) { MetaKmsFeedback *feedback = NULL; feedback = meta_kms_feedback_new_failed (NULL, g_steal_pointer (&error)); queue_result_feedback (impl_device, update, feedback); meta_kms_update_free (update); return feedback; } meta_kms_update_realize (update, impl_device); if (flags & META_KMS_UPDATE_FLAG_TEST_ONLY) { return do_process (impl_device, meta_kms_update_get_latch_crtc (update), update, flags); } else if (flags & META_KMS_UPDATE_FLAG_MODE_SET) { return process_mode_set_update (impl_device, update, flags); } else { g_assert_not_reached (); } } void meta_kms_impl_device_disable (MetaKmsImplDevice *impl_device) { MetaKmsImplDevicePrivate *priv = meta_kms_impl_device_get_instance_private (impl_device); + MetaKmsImpl *kms_impl = meta_kms_impl_device_get_impl (impl_device); + MetaThreadImpl *thread_impl = META_THREAD_IMPL (kms_impl); + MetaThread *thread = meta_thread_impl_get_thread (thread_impl); MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); if (!priv->device_file) return; meta_kms_impl_device_hold_fd (impl_device); + meta_thread_inhibit_realtime_in_impl (thread); klass->disable (impl_device); + meta_thread_uninhibit_realtime_in_impl (thread); g_list_foreach (priv->crtcs, (GFunc) meta_kms_crtc_disable_in_impl, NULL); g_list_foreach (priv->connectors, (GFunc) meta_kms_connector_disable_in_impl, NULL); meta_kms_impl_device_unhold_fd (impl_device); } void meta_kms_impl_device_handle_page_flip_callback (MetaKmsImplDevice *impl_device, MetaKmsPageFlipData *page_flip_data) { MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); klass->handle_page_flip_callback (impl_device, page_flip_data); } void meta_kms_impl_device_discard_pending_page_flips (MetaKmsImplDevice *impl_device) { MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); klass->discard_pending_page_flips (impl_device); } void meta_kms_impl_device_hold_fd (MetaKmsImplDevice *impl_device) { MetaKmsImplDevicePrivate *priv = meta_kms_impl_device_get_instance_private (impl_device); MetaKms *kms = meta_kms_device_get_kms (priv->device); -- 2.41.0