mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-03-30 12:23:06 +02:00
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>
This commit is contained in:
parent
0c0469b56d
commit
9ba95e25b7
30
glib/gmain.c
30
glib/gmain.c
@ -277,7 +277,8 @@ struct _GMainContext
|
|||||||
|
|
||||||
guint next_id;
|
guint next_id;
|
||||||
GList *source_lists;
|
GList *source_lists;
|
||||||
gint in_check_or_prepare;
|
gboolean in_check_or_prepare;
|
||||||
|
gboolean need_wakeup;
|
||||||
|
|
||||||
GPollRec *poll_records;
|
GPollRec *poll_records;
|
||||||
guint n_poll_records;
|
guint n_poll_records;
|
||||||
@ -651,6 +652,7 @@ g_main_context_new (void)
|
|||||||
|
|
||||||
context->pending_dispatches = g_ptr_array_new ();
|
context->pending_dispatches = g_ptr_array_new ();
|
||||||
|
|
||||||
|
context->need_wakeup = FALSE;
|
||||||
context->time_is_fresh = FALSE;
|
context->time_is_fresh = FALSE;
|
||||||
|
|
||||||
context->wakeup = g_wakeup_new ();
|
context->wakeup = g_wakeup_new ();
|
||||||
@ -1127,17 +1129,11 @@ source_remove_from_context (GSource *source,
|
|||||||
static void
|
static void
|
||||||
conditional_wakeup (GMainContext *context)
|
conditional_wakeup (GMainContext *context)
|
||||||
{
|
{
|
||||||
/* We want to signal wakeups in two cases:
|
/* This flag is set if at the start of prepare() we have no other ready
|
||||||
* 1 When the context is owned by another thread
|
* sources, and hence would wait in poll(). In that case, any other threads
|
||||||
* 2 When the context owner is NULL (two subcases)
|
* attaching sources will need to signal a wakeup.
|
||||||
* 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
|
|
||||||
*/
|
*/
|
||||||
if (context->owner != G_THREAD_SELF)
|
if (context->need_wakeup)
|
||||||
g_wakeup_signal (context->wakeup);
|
g_wakeup_signal (context->wakeup);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3469,6 +3465,10 @@ g_main_context_prepare (GMainContext *context,
|
|||||||
|
|
||||||
LOCK_CONTEXT (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;
|
context->time_is_fresh = FALSE;
|
||||||
|
|
||||||
if (context->in_check_or_prepare)
|
if (context->in_check_or_prepare)
|
||||||
@ -3594,6 +3594,8 @@ g_main_context_prepare (GMainContext *context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_source_iter_clear (&iter);
|
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));
|
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));
|
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++)
|
for (i = 0; i < n_fds; i++)
|
||||||
{
|
{
|
||||||
if (fds[i].fd == context->wake_up_rec.fd)
|
if (fds[i].fd == context->wake_up_rec.fd)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user