mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-11 15:06:14 +01:00
Add Linux timerfd_create() backend for g_date_time_source_new()
This makes the source efficient on Linux. Tested on Fedora 15 x86_64 + updates, kernel-2.6.40-4.fc15.x86_64 Also tested fallback code for unsupported flag TFD_TIMER_CANCEL_ON_SET on kernel 2.6.38. https://bugzilla.gnome.org/show_bug.cgi?id=655129
This commit is contained in:
parent
1feb752996
commit
5763c63147
17
configure.ac
17
configure.ac
@ -2665,6 +2665,23 @@ if test x"$glib_cv_eventfd" = x"yes"; then
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_EVENTFD, [test "$glib_cv_eventfd" = "yes"])
|
||||
|
||||
AC_CACHE_CHECK(for timerfd_create(2) system call,
|
||||
glib_cv_timerfd,AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
|
||||
#include <sys/timerfd.h>
|
||||
#include <unistd.h>
|
||||
],[
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC);
|
||||
return 0;
|
||||
}
|
||||
])],glib_cv_timerfd=yes,glib_cv_timerfd=no))
|
||||
if test x"$glib_cv_timerfd" = x"yes"; then
|
||||
AC_DEFINE(HAVE_TIMERFD, 1, [we have the timerfd_create(2) system call])
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_TIMERFD, [test "$glib_cv_timerfd" = "yes"])
|
||||
|
||||
dnl ****************************************
|
||||
dnl *** GLib POLL* compatibility defines ***
|
||||
dnl ****************************************
|
||||
|
@ -63,6 +63,7 @@
|
||||
#include "gatomic.h"
|
||||
#include "gfileutils.h"
|
||||
#include "ghash.h"
|
||||
#include "giochannel.h"
|
||||
#include "gmain.h"
|
||||
#include "gmappedfile.h"
|
||||
#include "gstrfuncs.h"
|
||||
@ -75,6 +76,9 @@
|
||||
#ifndef G_OS_WIN32
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#ifdef HAVE_TIMERFD
|
||||
#include <sys/timerfd.h>
|
||||
#endif
|
||||
#endif /* !G_OS_WIN32 */
|
||||
|
||||
/**
|
||||
@ -2596,6 +2600,8 @@ struct _GDateTimeSource
|
||||
gint64 wakeup_expiration;
|
||||
|
||||
gboolean cancel_on_set;
|
||||
|
||||
GPollFD pollfd;
|
||||
};
|
||||
|
||||
static inline void
|
||||
@ -2632,7 +2638,17 @@ g_datetime_source_prepare (GSource *source,
|
||||
gint *timeout)
|
||||
{
|
||||
GDateTimeSource *datetime_source = (GDateTimeSource*)source;
|
||||
gint64 monotonic_now = g_source_get_time (source);
|
||||
gint64 monotonic_now;
|
||||
|
||||
#ifdef HAVE_TIMERFD
|
||||
if (datetime_source->pollfd.fd != -1)
|
||||
{
|
||||
*timeout = -1;
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
monotonic_now = g_source_get_time (source);
|
||||
|
||||
if (monotonic_now < datetime_source->wakeup_expiration)
|
||||
{
|
||||
@ -2652,6 +2668,11 @@ g_datetime_source_check (GSource *source)
|
||||
{
|
||||
GDateTimeSource *datetime_source = (GDateTimeSource*)source;
|
||||
|
||||
#ifdef HAVE_TIMERFD
|
||||
if (datetime_source->pollfd.fd != -1)
|
||||
return datetime_source->pollfd.revents != 0;
|
||||
#endif
|
||||
|
||||
if (g_datetime_source_is_expired (datetime_source))
|
||||
return TRUE;
|
||||
|
||||
@ -2681,6 +2702,11 @@ g_datetime_source_dispatch (GSource *source,
|
||||
static void
|
||||
g_datetime_source_finalize (GSource *source)
|
||||
{
|
||||
#ifdef HAVE_TIMERFD
|
||||
GDateTimeSource *datetime_source = (GDateTimeSource*)source;
|
||||
if (datetime_source->pollfd.fd != -1)
|
||||
close (datetime_source->pollfd.fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
static GSourceFuncs g_datetime_source_funcs = {
|
||||
@ -2690,6 +2716,45 @@ static GSourceFuncs g_datetime_source_funcs = {
|
||||
g_datetime_source_finalize
|
||||
};
|
||||
|
||||
#ifdef HAVE_TIMERFD
|
||||
static gboolean
|
||||
g_datetime_source_init_timerfd (GDateTimeSource *datetime_source,
|
||||
gint64 unix_seconds)
|
||||
{
|
||||
struct itimerspec its;
|
||||
int settime_flags;
|
||||
|
||||
datetime_source->pollfd.fd = timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC);
|
||||
if (datetime_source->pollfd.fd == -1)
|
||||
return FALSE;
|
||||
|
||||
memset (&its, 0, sizeof (its));
|
||||
its.it_value.tv_sec = (time_t) unix_seconds;
|
||||
|
||||
/* http://article.gmane.org/gmane.linux.kernel/1132138 */
|
||||
#ifndef TFD_TIMER_CANCEL_ON_SET
|
||||
#define TFD_TIMER_CANCEL_ON_SET (1 << 1)
|
||||
#endif
|
||||
|
||||
settime_flags = TFD_TIMER_ABSTIME;
|
||||
if (datetime_source->cancel_on_set)
|
||||
settime_flags |= TFD_TIMER_CANCEL_ON_SET;
|
||||
|
||||
if (timerfd_settime (datetime_source->pollfd.fd, settime_flags, &its, NULL) < 0)
|
||||
{
|
||||
close (datetime_source->pollfd.fd);
|
||||
datetime_source->pollfd.fd = -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
datetime_source->pollfd.events = G_IO_IN;
|
||||
|
||||
g_source_add_poll ((GSource*) datetime_source, &datetime_source->pollfd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* g_date_time_source_new:
|
||||
* @datetime: Time to await
|
||||
@ -2733,11 +2798,21 @@ g_date_time_source_new (GDateTime *datetime,
|
||||
gboolean cancel_on_set)
|
||||
{
|
||||
GDateTimeSource *datetime_source;
|
||||
gint64 unix_seconds;
|
||||
|
||||
unix_seconds = g_date_time_to_unix (datetime);
|
||||
|
||||
datetime_source = (GDateTimeSource*) g_source_new (&g_datetime_source_funcs, sizeof (GDateTimeSource));
|
||||
|
||||
datetime_source->cancel_on_set = cancel_on_set;
|
||||
datetime_source->real_expiration = g_date_time_to_unix (datetime) * 1000000;
|
||||
|
||||
#ifdef HAVE_TIMERFD
|
||||
if (g_datetime_source_init_timerfd (datetime_source, unix_seconds))
|
||||
return (GSource*)datetime_source;
|
||||
/* Fall through to non-timerfd code */
|
||||
#endif
|
||||
|
||||
datetime_source->real_expiration = unix_seconds * 1000000;
|
||||
g_datetime_source_reschedule (datetime_source, g_get_monotonic_time ());
|
||||
|
||||
return (GSource*)datetime_source;
|
||||
|
Loading…
Reference in New Issue
Block a user