]> git.eshelyaron.com Git - emacs.git/commitdiff
Simplify timerfd configuration and fix some minor glitches.
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 31 Jul 2014 20:17:01 +0000 (13:17 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 31 Jul 2014 20:17:01 +0000 (13:17 -0700)
* configure.ac (HAVE_TIMERFD): Define only if TFD_CLOEXEC works,
since the code leaked file descriptors to children when !TFD_CLOEXEC.
(HAVE_TIMERFD_CLOEXEC): Remove; no longer used.
* m4/clock_time.m4 (gl_CLOCK_TIME): Don't check for clock_getres.
This reverts the previous change to this file, so it matches
gnulib again.
* src/atimer.c (TIMERFD_CREATE_FLAGS): Remove; we now assume TFD_CLOEXEC.
(alarm_timer, alarm_timer_ok, set_alarm, init_atimer):
Fall back on timer_create if timerfd_create fails at runtime.
(resolution) [HAVE_CLOCK_GETRES]: Remove; we now rely on the
kernel primitives to do resolution.  All uses removed.
(timerfd) [!HAVE_TIMERFD]: Define to be -1, for convenience.
(turn_on_atimers): Clear timer_create-based timers too,
for consistency.

ChangeLog
configure.ac
m4/clock_time.m4
src/ChangeLog
src/atimer.c

index c7fd47636a5a24d7dfa64fe98cdf63c81bf37971..2dfef7037fe0714202322b15cbd99d988a207105 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2014-07-31  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Simplify timerfd configuration and fix some minor glitches.
+       * configure.ac (HAVE_TIMERFD): Define only if TFD_CLOEXEC works,
+       since the code leaked file descriptors to children when !TFD_CLOEXEC.
+       (HAVE_TIMERFD_CLOEXEC): Remove; no longer used.
+       * m4/clock_time.m4 (gl_CLOCK_TIME): Don't check for clock_getres.
+       This reverts the previous change to this file, so it matches
+       gnulib again.
+
 2014-07-28  Dmitry Antipov  <dmantipov@yandex.ru>
 
        * configure.ac (toplevel): Check whether GNU/Linux-specific
index 89440446ee5e611924202ade9dbe50699e297f7b..4f3fde56af282d323613a774123ead76ee7878a1 100644 (file)
@@ -1539,7 +1539,7 @@ if test "$ac_cv_header_sys_sysinfo_h" = yes; then
       AC_DEFINE(LINUX_SYSINFO_UNIT, 1,
                 [Define to 1 if Linux sysinfo sizes are in multiples of mem_unit bytes.]))
   fi
-fi  
+fi
 
 dnl On Solaris 8 there's a compilation warning for term.h because
 dnl it doesn't define `bool'.
@@ -3711,25 +3711,18 @@ AC_SUBST(LIBS_TERMCAP)
 AC_SUBST(TERMCAP_OBJ)
 
 # GNU/Linux-specific timer functions.
-if test $opsys = gnu-linux; then
-  AC_MSG_CHECKING([whether Linux timerfd functions are supported])
-  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/timerfd.h>]],
-                                    [[timerfd_create (CLOCK_REALTIME, 0);
-                                      timerfd_settime (0, 0, NULL, NULL)]])],
-  emacs_cv_linux_timerfd=yes, emacs_cv_linux_timerfd=no)
-  AC_MSG_RESULT([$emacs_cv_linux_timerfd])
-  if test $emacs_cv_linux_timerfd = yes; then
-    AC_DEFINE(HAVE_TIMERFD, 1, [Define to 1 if Linux timerfd functions are supported.])
-    AC_MSG_CHECKING([whether TFD_CLOEXEC is defined])
-      AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/timerfd.h>]],
-                                        [[timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC)]])],
-    emacs_cv_tfd_cloexec=yes, emacs_cv_tfd_cloexec=no)
-    AC_MSG_RESULT([$emacs_cv_tfd_cloexec])
-    if test $emacs_cv_tfd_cloexec = yes; then
-      AC_DEFINE(HAVE_TIMERFD_CLOEXEC, 1, [Define to 1 if TFD_CLOEXEC is defined.])
-    fi
-  fi
-fi  
+AC_CACHE_CHECK([for timerfd interface], [emacs_cv_have_timerfd],
+  [AC_COMPILE_IFELSE(
+     [AC_LANG_PROGRAM([[#include <sys/timerfd.h>
+                     ]],
+                     [[timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC);
+                       timerfd_settime (0, TFD_TIMER_ABSTIME, 0, 0);]])],
+     [emacs_cv_have_timerfd=yes],
+     [emacs_cv_have_timerfd=no])])
+if test "$emacs_cv_have_timerfd" = yes; then
+  AC_DEFINE([HAVE_TIMERFD], 1,
+    [Define to 1 if timerfd functions are supported as in GNU/Linux.])
+fi
 
 # Do we have res_init, for detecting changes in /etc/resolv.conf?
 # On Darwin, res_init appears not to be useful: see bug#562 and
index 8513c6d781a4521cf059da3c87da5acda0d0bf5c..6c4a637dc6281cb3373ddb8a888803ea985051ad 100644 (file)
@@ -26,6 +26,6 @@ AC_DEFUN([gl_CLOCK_TIME],
     AC_SEARCH_LIBS([clock_gettime], [rt posix4],
                    [test "$ac_cv_search_clock_gettime" = "none required" ||
                     LIB_CLOCK_GETTIME=$ac_cv_search_clock_gettime])
-    AC_CHECK_FUNCS([clock_getres clock_gettime clock_settime])
+    AC_CHECK_FUNCS([clock_gettime clock_settime])
   LIBS=$gl_saved_libs
 ])
index 985e3b33e0612bb0628528de6535020a5c615b73..f3ab7f9b99029487c9339bde9d98d4ab7f09a9c2 100644 (file)
@@ -1,5 +1,15 @@
 2014-07-31  Paul Eggert  <eggert@cs.ucla.edu>
 
+       Simplify timerfd configuration and fix some minor glitches.
+       * atimer.c (TIMERFD_CREATE_FLAGS): Remove; we now assume TFD_CLOEXEC.
+       (alarm_timer, alarm_timer_ok, set_alarm, init_atimer):
+       Fall back on timer_create if timerfd_create fails at runtime.
+       (resolution) [HAVE_CLOCK_GETRES]: Remove; we now rely on the
+       kernel primitives to do resolution.  All uses removed.
+       (timerfd) [!HAVE_TIMERFD]: Define to be -1, for convenience.
+       (turn_on_atimers): Clear timer_create-based timers too,
+       for consistency.
+
        * frame.c (x_set_frame_parameters): Don't use uninitialized locals.
        Without this change, the code can access the local variable 'width'
        even when it has not been initialized, and likewise for 'height';
index c03ac96c6dac87a826a335540ecb4abcd68f6c66..daac32f19b4957141293cc89f022648cb8464307 100644 (file)
@@ -27,13 +27,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <unistd.h>
 
 #ifdef HAVE_TIMERFD
-#include <sys/timerfd.h>
-#ifdef HAVE_TIMERFD_CLOEXEC
-#define TIMERFD_CREATE_FLAGS TFD_CLOEXEC
-#else
-#define TIMERFD_CREATE_FLAGS 0
-#endif /* HAVE_TIMERFD_CLOEXEC */
-#endif /* HAVE_TIMERFD */
+# include <sys/timerfd.h>
+#endif
 
 /* Free-list of atimer structures.  */
 
@@ -49,23 +44,18 @@ static struct atimer *stopped_atimers;
 
 static struct atimer *atimers;
 
-#if defined (HAVE_TIMERFD)
-/* File descriptor returned by timerfd_create.  GNU/Linux-specific.  */
-static int timerfd;
-#elif defined (HAVE_ITIMERSPEC)
-/* The alarm timer used if POSIX timers are available.  */
+#ifdef HAVE_ITIMERSPEC
+/* The alarm timer and whether it was properly initialized, if
+   POSIX timers are available.  */
 static timer_t alarm_timer;
-#endif
-
-#if defined (HAVE_TIMERFD) || defined (HAVE_ITIMERSPEC)
-/* Non-zero if one of the above was successfully initialized.  Do not
-   use bool due to special treatment if HAVE_TIMERFD, see below.  */
-static int special_timer_available;
-#endif
+static bool alarm_timer_ok;
 
-#ifdef HAVE_CLOCK_GETRES
-/* Resolution of CLOCK_REALTIME clock.  */
-static struct timespec resolution;
+# ifdef HAVE_TIMERFD
+/* File descriptor for timer, or -1 if it could not be created.  */
+static int timerfd;
+# else
+enum { timerfd = -1 };
+# endif
 #endif
 
 /* Block/unblock SIGALRM.  */
@@ -92,20 +82,20 @@ static void schedule_atimer (struct atimer *);
 static struct atimer *append_atimer_lists (struct atimer *,
                                            struct atimer *);
 
-/* Start a new atimer of type TYPE.  TIME specifies when the timer is
+/* Start a new atimer of type TYPE.  TIMESTAMP specifies when the timer is
    ripe.  FN is the function to call when the timer fires.
    CLIENT_DATA is stored in the client_data member of the atimer
    structure returned and so made available to FN when it is called.
 
-   If TYPE is ATIMER_ABSOLUTE, TIME is the absolute time at which the
+   If TYPE is ATIMER_ABSOLUTE, TIMESTAMP is the absolute time at which the
    timer fires.
 
-   If TYPE is ATIMER_RELATIVE, the timer is ripe TIME s/us in the
+   If TYPE is ATIMER_RELATIVE, the timer is ripe TIMESTAMP seconds in the
    future.
 
    In both cases, the timer is automatically freed after it has fired.
 
-   If TYPE is ATIMER_CONTINUOUS, the timer fires every TIME s/us.
+   If TYPE is ATIMER_CONTINUOUS, the timer fires every TIMESTAMP seconds.
 
    Value is a pointer to the atimer started.  It can be used in calls
    to cancel_atimer; don't free it yourself.  */
@@ -117,16 +107,10 @@ start_atimer (enum atimer_type type, struct timespec timestamp,
   struct atimer *t;
   sigset_t oldset;
 
-#if !defined (HAVE_SETITIMER)
-  /* Round TIME up to the next full second if we don't have itimers.  */
+  /* Round TIMESTAMP up to the next full second if we don't have itimers.  */
+#ifndef HAVE_SETITIMER
   if (timestamp.tv_nsec != 0 && timestamp.tv_sec < TYPE_MAXIMUM (time_t))
     timestamp = make_timespec (timestamp.tv_sec + 1, 0);
-#elif defined (HAVE_CLOCK_GETRES)
-  /* Check that the system clock is precise enough.  If
-     not, round TIME up to the system clock resolution.  */
-  if (timespec_valid_p (resolution)
-      && timespec_cmp (timestamp, resolution) < 0)
-    timestamp = resolution;
 #endif /* not HAVE_SETITIMER */
 
   /* Get an atimer structure from the free-list, or allocate
@@ -311,25 +295,24 @@ set_alarm (void)
 #endif
       struct timespec now, interval;
 
-#if defined (HAVE_TIMERFD) || defined (HAVE_ITIMERSPEC)
-      if (special_timer_available)
+#ifdef HAVE_ITIMERSPEC
+      if (0 <= timerfd || alarm_timer_ok)
        {
          struct itimerspec ispec;
          ispec.it_value = atimers->expiration;
          ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0;
-#if defined (HAVE_TIMERFD)
-         if (special_timer_available == 1)
+# ifdef HAVE_TIMERFD
+         if (timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0)
            {
              add_timer_wait_descriptor (timerfd);
-             special_timer_available++;
+             return;
            }
-         if (timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0)
-#elif defined (HAVE_ITIMERSPEC)
-         if (timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0) == 0)
-#endif     
+# endif
+         if (alarm_timer_ok
+             && timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0) == 0)
            return;
        }
-#endif /* HAVE_TIMERFD || HAVE_ITIMERSPEC */
+#endif
 
       /* Determine interval till the next timer is ripe.
         Don't set the interval to 0; this disables the timer.  */
@@ -453,15 +436,15 @@ turn_on_atimers (bool on)
     set_alarm ();
   else
     {
-#ifdef HAVE_TIMERFD
-      if (special_timer_available > 1)
-       {
-         struct itimerspec ispec;
-         memset (&ispec, 0, sizeof (ispec));
-         /* Writing zero expiration time should disarm it.  */
-         timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0);
-       }
-#endif /* HAVE_TIMERFD */
+#ifdef HAVE_ITIMERSPEC
+      struct itimerspec ispec;
+      memset (&ispec, 0, sizeof ispec);
+      if (alarm_timer_ok)
+       timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0);
+# ifdef HAVE_TIMERFD
+      timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0);
+# endif
+#endif
       alarm (0);
     }
 }
@@ -494,14 +477,14 @@ debug_timer_callback (struct atimer *t)
     r->intime = 0;
   else if (result >= 0)
     {
-#ifdef HAVE_SETITIMER      
+#ifdef HAVE_SETITIMER
       struct timespec delta = timespec_sub (now, r->expected);
       /* Too late if later than expected + 0.01s.  FIXME:
         this should depend from system clock resolution.  */
       if (timespec_cmp (delta, make_timespec (0, 10000000)) > 0)
        r->intime = 0;
       else
-#endif /* HAVE_SETITIMER */    
+#endif /* HAVE_SETITIMER */
        r->intime = 1;
     }
 }
@@ -543,21 +526,20 @@ Return t if all self-tests are passed, nil otherwise.  */)
 void
 init_atimer (void)
 {
-#if defined (HAVE_TIMERFD)
-  timerfd = timerfd_create (CLOCK_REALTIME, TIMERFD_CREATE_FLAGS);
-  special_timer_available = !!(timerfd != -1);
-#elif defined (HAVE_ITIMERSPEC)
-  struct sigevent sigev;
-  sigev.sigev_notify = SIGEV_SIGNAL;
-  sigev.sigev_signo = SIGALRM;
-  sigev.sigev_value.sival_ptr = &alarm_timer;
-  special_timer_available
-    = timer_create (CLOCK_REALTIME, &sigev, &alarm_timer) == 0;
-#endif /* HAVE_TIMERFD */
-#ifdef HAVE_CLOCK_GETRES
-  if (clock_getres (CLOCK_REALTIME, &resolution))
-    resolution = invalid_timespec ();
-#endif  
+#ifdef HAVE_ITIMERSPEC
+# ifdef HAVE_TIMERFD
+  timerfd = timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC);
+# endif
+  if (timerfd < 0)
+    {
+      struct sigevent sigev;
+      sigev.sigev_notify = SIGEV_SIGNAL;
+      sigev.sigev_signo = SIGALRM;
+      sigev.sigev_value.sival_ptr = &alarm_timer;
+      alarm_timer_ok
+       = timer_create (CLOCK_REALTIME, &sigev, &alarm_timer) == 0;
+    }
+#endif
   free_atimers = stopped_atimers = atimers = NULL;
 
   /* pending_signals is initialized in init_keyboard.  */
@@ -567,5 +549,5 @@ init_atimer (void)
 
 #ifdef ENABLE_CHECKING
   defsubr (&Sdebug_timer_check);
-#endif  
+#endif
 }