From 74740da17c8aa3acfd521fbd9d377000d4d94626 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Wed, 6 Mar 2024 13:52:01 -0800 Subject: [PATCH] glib/gmain: use ppoll() when possible If our GPollFunc is set to g_poll() then we can optionally use a poll() alternative with higher precision. ppoll() provides poll() equivalence but with timeouts in nanoseconds. With more precise polling timouts, frame clocks and other timing sensitive APIs are not restricted to a minimum of 1 millisecond timeout. --- glib/gmain.c | 23 +++++++++++++++++++++++ meson.build | 13 +++++++++++++ 2 files changed, 36 insertions(+) diff --git a/glib/gmain.c b/glib/gmain.c index fe735a656..af343c9ca 100644 --- a/glib/gmain.c +++ b/glib/gmain.c @@ -69,6 +69,10 @@ #include #include +#ifdef HAVE_POLL_H +#include +#endif + #ifdef HAVE_PIDFD #include #include @@ -4548,6 +4552,25 @@ g_main_context_poll_unlocked (GMainContext *context, #endif poll_func = context->poll_func; +#if defined(HAVE_PPOLL) && defined(HAVE_POLL) + if (poll_func == g_poll) + { + struct timespec spec; + struct timespec *spec_p = NULL; + + if (timeout_usec > -1) + { + spec.tv_sec = timeout_usec / G_USEC_PER_SEC; + spec.tv_nsec = (timeout_usec % G_USEC_PER_SEC) * 1000L; + spec_p = &spec; + } + + UNLOCK_CONTEXT (context); + ret = ppoll ((struct pollfd *)fds, n_fds, spec_p, NULL); + LOCK_CONTEXT (context); + } + else +#endif { int timeout_msec = round_timeout_to_msec (timeout_usec); diff --git a/meson.build b/meson.build index 753454209..0ba7ca131 100644 --- a/meson.build +++ b/meson.build @@ -1008,6 +1008,19 @@ if cc.links('''#include glib_conf.set('HAVE_EVENTFD', 1) endif +# Check for ppoll(2) +if cc.links('''#define _GNU_SOURCE + #include + #include + int main (int argc, char ** argv) { + struct pollfd fds[1] = {{0}}; + struct timespec ts = {0}; + ppoll (fds, 1, NULL, NULL); + return 0; + }''', name : 'ppoll(2) system call') + glib_conf.set('HAVE_PPOLL', 1) +endif + # Check for pidfd_open(2) if cc.links('''#include #include