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.
This commit is contained in:
Christian Hergert 2024-03-06 13:52:01 -08:00 committed by Philip Withnall
parent c840d75395
commit 368cb7eb7b
2 changed files with 36 additions and 0 deletions

View File

@ -69,6 +69,10 @@
#include <errno.h>
#include <string.h>
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
#ifdef HAVE_PIDFD
#include <sys/syscall.h>
#include <sys/wait.h>
@ -4558,6 +4562,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);

View File

@ -1008,6 +1008,19 @@ if cc.links('''#include <sys/eventfd.h>
glib_conf.set('HAVE_EVENTFD', 1)
endif
# Check for ppoll(2)
if cc.links('''#define _GNU_SOURCE
#include <poll.h>
#include <stddef.h>
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 <sys/syscall.h>
#include <sys/wait.h>