Differential D355 Diff 749 files/gmain-only-signal-GWakeup-right-before-or-during-a-blocking-poll.patch
Changeset View
Changeset View
Standalone View
Standalone View
files/gmain-only-signal-GWakeup-right-before-or-during-a-blocking-poll.patch
- This file was added.
| From 5d74233476d61771b4d67d50bec5420f551ef922 Mon Sep 17 00:00:00 2001 | |||||
| From: Paolo Bonzini <pbonzini@redhat.com> | |||||
| Date: Tue, 4 Apr 2017 09:56:47 +0200 | |||||
| Subject: [PATCH] gmain: only signal GWakeup right before or during a blocking | |||||
| poll | |||||
| Since commit e4ee307 ("Do not wake up main loop if change is from same | |||||
| thread", bug 761102), GMainContext uses context->owner to decide if the | |||||
| event loop is being run in the current thread. However, what really | |||||
| matters is the phase in the prepare/query/poll/check/dispatch sequence. | |||||
| Wakeups are only needed between the end of prepare and the end of poll, | |||||
| and then only if prepare found that no sources were ready. | |||||
| There is no need to take threads into account, because prepare, check | |||||
| and all callers of conditional_wakeup all look at the new need_wakeup | |||||
| flag inside LOCK_CONTEXT/UNLOCK_CONTEXT. | |||||
| With this change, g_main_context_is_owner and g_main_context_wait are | |||||
| the only functions for which acquire/release matters, just like before | |||||
| commit e4ee307. | |||||
| Signed-off-by: Paolo Bonzini <bonzini@gnu.org> | |||||
| --- | |||||
| glib/gmain.c | 30 +++++++++++++++++++----------- | |||||
| 1 file changed, 19 insertions(+), 11 deletions(-) | |||||
| diff --git a/glib/gmain.c b/glib/gmain.c | |||||
| index ab2908e52..af0a29ae5 100644 | |||||
| --- a/glib/gmain.c | |||||
| +++ b/glib/gmain.c | |||||
| @@ -277,7 +277,8 @@ struct _GMainContext | |||||
| guint next_id; | |||||
| GList *source_lists; | |||||
| - gint in_check_or_prepare; | |||||
| + gboolean in_check_or_prepare; | |||||
| + gboolean need_wakeup; | |||||
| GPollRec *poll_records; | |||||
| guint n_poll_records; | |||||
| @@ -651,6 +652,7 @@ g_main_context_new (void) | |||||
| context->pending_dispatches = g_ptr_array_new (); | |||||
| + context->need_wakeup = FALSE; | |||||
| context->time_is_fresh = FALSE; | |||||
| context->wakeup = g_wakeup_new (); | |||||
| @@ -1127,17 +1129,11 @@ source_remove_from_context (GSource *source, | |||||
| static void | |||||
| conditional_wakeup (GMainContext *context) | |||||
| { | |||||
| - /* We want to signal wakeups in two cases: | |||||
| - * 1 When the context is owned by another thread | |||||
| - * 2 When the context owner is NULL (two subcases) | |||||
| - * 2a Possible if the context has never been acquired | |||||
| - * 2b Or if the context has no current owner | |||||
| - * | |||||
| - * At least case 2a) is necessary to ensure backwards compatibility with | |||||
| - * qemu's use of GMainContext. | |||||
| - * https://bugzilla.gnome.org/show_bug.cgi?id=761102#c14 | |||||
| + /* This flag is set if at the start of prepare() we have no other ready | |||||
| + * sources, and hence would wait in poll(). In that case, any other threads | |||||
| + * attaching sources will need to signal a wakeup. | |||||
| */ | |||||
| - if (context->owner != G_THREAD_SELF) | |||||
| + if (context->need_wakeup) | |||||
| g_wakeup_signal (context->wakeup); | |||||
| } | |||||
| @@ -3469,6 +3465,10 @@ g_main_context_prepare (GMainContext *context, | |||||
| LOCK_CONTEXT (context); | |||||
| + /* context->need_wakeup is protected by LOCK_CONTEXT/UNLOCK_CONTEXT, | |||||
| + * so need not set it yet. | |||||
| + */ | |||||
| + | |||||
| context->time_is_fresh = FALSE; | |||||
| if (context->in_check_or_prepare) | |||||
| @@ -3594,6 +3594,8 @@ g_main_context_prepare (GMainContext *context, | |||||
| } | |||||
| } | |||||
| g_source_iter_clear (&iter); | |||||
| + /* See conditional_wakeup() where this is used */ | |||||
| + context->need_wakeup = (n_ready == 0); | |||||
| TRACE (GLIB_MAIN_CONTEXT_AFTER_PREPARE (context, current_priority, n_ready)); | |||||
| @@ -3728,6 +3730,12 @@ g_main_context_check (GMainContext *context, | |||||
| TRACE (GLIB_MAIN_CONTEXT_BEFORE_CHECK (context, max_priority, fds, n_fds)); | |||||
| + /* We don't need to wakeup during check or dispatch, because | |||||
| + * all sources will be re-evaluated during prepare/query. | |||||
| + */ | |||||
| + context->need_wakeup = FALSE; | |||||
| + | |||||
| + /* And if we have a wakeup pending, acknowledge it */ | |||||
| for (i = 0; i < n_fds; i++) | |||||
| { | |||||
| if (fds[i].fd == context->wake_up_rec.fd) | |||||
| -- | |||||
| 2.12.2 | |||||
Copyright © 2015-2021 Solus Project. The Solus logo is Copyright © 2016-2021 Solus Project. All Rights Reserved.