aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2014-07-31 13:17:01 -0700
committerPaul Eggert2014-07-31 13:17:01 -0700
commit5c6476b48a2d00bef6ada92fa210ac7cd1bc9a77 (patch)
tree6f92d25b9731476c9aceab154149f8cf87def1e2
parentf3655f35ccd5a56c158a5db399c5f168b2e928d0 (diff)
downloademacs-5c6476b48a2d00bef6ada92fa210ac7cd1bc9a77.tar.gz
emacs-5c6476b48a2d00bef6ada92fa210ac7cd1bc9a77.zip
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. * 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.
-rw-r--r--ChangeLog10
-rw-r--r--configure.ac33
-rw-r--r--m4/clock_time.m42
-rw-r--r--src/ChangeLog10
-rw-r--r--src/atimer.c124
5 files changed, 87 insertions, 92 deletions
diff --git a/ChangeLog b/ChangeLog
index c7fd47636a5..2dfef7037fe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
12014-07-31 Paul Eggert <eggert@cs.ucla.edu>
2
3 Simplify timerfd configuration and fix some minor glitches.
4 * configure.ac (HAVE_TIMERFD): Define only if TFD_CLOEXEC works,
5 since the code leaked file descriptors to children when !TFD_CLOEXEC.
6 (HAVE_TIMERFD_CLOEXEC): Remove; no longer used.
7 * m4/clock_time.m4 (gl_CLOCK_TIME): Don't check for clock_getres.
8 This reverts the previous change to this file, so it matches
9 gnulib again.
10
12014-07-28 Dmitry Antipov <dmantipov@yandex.ru> 112014-07-28 Dmitry Antipov <dmantipov@yandex.ru>
2 12
3 * configure.ac (toplevel): Check whether GNU/Linux-specific 13 * configure.ac (toplevel): Check whether GNU/Linux-specific
diff --git a/configure.ac b/configure.ac
index 89440446ee5..4f3fde56af2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1539,7 +1539,7 @@ if test "$ac_cv_header_sys_sysinfo_h" = yes; then
1539 AC_DEFINE(LINUX_SYSINFO_UNIT, 1, 1539 AC_DEFINE(LINUX_SYSINFO_UNIT, 1,
1540 [Define to 1 if Linux sysinfo sizes are in multiples of mem_unit bytes.])) 1540 [Define to 1 if Linux sysinfo sizes are in multiples of mem_unit bytes.]))
1541 fi 1541 fi
1542fi 1542fi
1543 1543
1544dnl On Solaris 8 there's a compilation warning for term.h because 1544dnl On Solaris 8 there's a compilation warning for term.h because
1545dnl it doesn't define `bool'. 1545dnl it doesn't define `bool'.
@@ -3711,25 +3711,18 @@ AC_SUBST(LIBS_TERMCAP)
3711AC_SUBST(TERMCAP_OBJ) 3711AC_SUBST(TERMCAP_OBJ)
3712 3712
3713# GNU/Linux-specific timer functions. 3713# GNU/Linux-specific timer functions.
3714if test $opsys = gnu-linux; then 3714AC_CACHE_CHECK([for timerfd interface], [emacs_cv_have_timerfd],
3715 AC_MSG_CHECKING([whether Linux timerfd functions are supported]) 3715 [AC_COMPILE_IFELSE(
3716 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/timerfd.h>]], 3716 [AC_LANG_PROGRAM([[#include <sys/timerfd.h>
3717 [[timerfd_create (CLOCK_REALTIME, 0); 3717 ]],
3718 timerfd_settime (0, 0, NULL, NULL)]])], 3718 [[timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC);
3719 emacs_cv_linux_timerfd=yes, emacs_cv_linux_timerfd=no) 3719 timerfd_settime (0, TFD_TIMER_ABSTIME, 0, 0);]])],
3720 AC_MSG_RESULT([$emacs_cv_linux_timerfd]) 3720 [emacs_cv_have_timerfd=yes],
3721 if test $emacs_cv_linux_timerfd = yes; then 3721 [emacs_cv_have_timerfd=no])])
3722 AC_DEFINE(HAVE_TIMERFD, 1, [Define to 1 if Linux timerfd functions are supported.]) 3722if test "$emacs_cv_have_timerfd" = yes; then
3723 AC_MSG_CHECKING([whether TFD_CLOEXEC is defined]) 3723 AC_DEFINE([HAVE_TIMERFD], 1,
3724 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/timerfd.h>]], 3724 [Define to 1 if timerfd functions are supported as in GNU/Linux.])
3725 [[timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC)]])], 3725fi
3726 emacs_cv_tfd_cloexec=yes, emacs_cv_tfd_cloexec=no)
3727 AC_MSG_RESULT([$emacs_cv_tfd_cloexec])
3728 if test $emacs_cv_tfd_cloexec = yes; then
3729 AC_DEFINE(HAVE_TIMERFD_CLOEXEC, 1, [Define to 1 if TFD_CLOEXEC is defined.])
3730 fi
3731 fi
3732fi
3733 3726
3734# Do we have res_init, for detecting changes in /etc/resolv.conf? 3727# Do we have res_init, for detecting changes in /etc/resolv.conf?
3735# On Darwin, res_init appears not to be useful: see bug#562 and 3728# On Darwin, res_init appears not to be useful: see bug#562 and
diff --git a/m4/clock_time.m4 b/m4/clock_time.m4
index 8513c6d781a..6c4a637dc62 100644
--- a/m4/clock_time.m4
+++ b/m4/clock_time.m4
@@ -26,6 +26,6 @@ AC_DEFUN([gl_CLOCK_TIME],
26 AC_SEARCH_LIBS([clock_gettime], [rt posix4], 26 AC_SEARCH_LIBS([clock_gettime], [rt posix4],
27 [test "$ac_cv_search_clock_gettime" = "none required" || 27 [test "$ac_cv_search_clock_gettime" = "none required" ||
28 LIB_CLOCK_GETTIME=$ac_cv_search_clock_gettime]) 28 LIB_CLOCK_GETTIME=$ac_cv_search_clock_gettime])
29 AC_CHECK_FUNCS([clock_getres clock_gettime clock_settime]) 29 AC_CHECK_FUNCS([clock_gettime clock_settime])
30 LIBS=$gl_saved_libs 30 LIBS=$gl_saved_libs
31]) 31])
diff --git a/src/ChangeLog b/src/ChangeLog
index 985e3b33e06..f3ab7f9b990 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,15 @@
12014-07-31 Paul Eggert <eggert@cs.ucla.edu> 12014-07-31 Paul Eggert <eggert@cs.ucla.edu>
2 2
3 Simplify timerfd configuration and fix some minor glitches.
4 * atimer.c (TIMERFD_CREATE_FLAGS): Remove; we now assume TFD_CLOEXEC.
5 (alarm_timer, alarm_timer_ok, set_alarm, init_atimer):
6 Fall back on timer_create if timerfd_create fails at runtime.
7 (resolution) [HAVE_CLOCK_GETRES]: Remove; we now rely on the
8 kernel primitives to do resolution. All uses removed.
9 (timerfd) [!HAVE_TIMERFD]: Define to be -1, for convenience.
10 (turn_on_atimers): Clear timer_create-based timers too,
11 for consistency.
12
3 * frame.c (x_set_frame_parameters): Don't use uninitialized locals. 13 * frame.c (x_set_frame_parameters): Don't use uninitialized locals.
4 Without this change, the code can access the local variable 'width' 14 Without this change, the code can access the local variable 'width'
5 even when it has not been initialized, and likewise for 'height'; 15 even when it has not been initialized, and likewise for 'height';
diff --git a/src/atimer.c b/src/atimer.c
index c03ac96c6da..daac32f19b4 100644
--- a/src/atimer.c
+++ b/src/atimer.c
@@ -27,13 +27,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
27#include <unistd.h> 27#include <unistd.h>
28 28
29#ifdef HAVE_TIMERFD 29#ifdef HAVE_TIMERFD
30#include <sys/timerfd.h> 30# include <sys/timerfd.h>
31#ifdef HAVE_TIMERFD_CLOEXEC 31#endif
32#define TIMERFD_CREATE_FLAGS TFD_CLOEXEC
33#else
34#define TIMERFD_CREATE_FLAGS 0
35#endif /* HAVE_TIMERFD_CLOEXEC */
36#endif /* HAVE_TIMERFD */
37 32
38/* Free-list of atimer structures. */ 33/* Free-list of atimer structures. */
39 34
@@ -49,23 +44,18 @@ static struct atimer *stopped_atimers;
49 44
50static struct atimer *atimers; 45static struct atimer *atimers;
51 46
52#if defined (HAVE_TIMERFD) 47#ifdef HAVE_ITIMERSPEC
53/* File descriptor returned by timerfd_create. GNU/Linux-specific. */ 48/* The alarm timer and whether it was properly initialized, if
54static int timerfd; 49 POSIX timers are available. */
55#elif defined (HAVE_ITIMERSPEC)
56/* The alarm timer used if POSIX timers are available. */
57static timer_t alarm_timer; 50static timer_t alarm_timer;
58#endif 51static bool alarm_timer_ok;
59
60#if defined (HAVE_TIMERFD) || defined (HAVE_ITIMERSPEC)
61/* Non-zero if one of the above was successfully initialized. Do not
62 use bool due to special treatment if HAVE_TIMERFD, see below. */
63static int special_timer_available;
64#endif
65 52
66#ifdef HAVE_CLOCK_GETRES 53# ifdef HAVE_TIMERFD
67/* Resolution of CLOCK_REALTIME clock. */ 54/* File descriptor for timer, or -1 if it could not be created. */
68static struct timespec resolution; 55static int timerfd;
56# else
57enum { timerfd = -1 };
58# endif
69#endif 59#endif
70 60
71/* Block/unblock SIGALRM. */ 61/* Block/unblock SIGALRM. */
@@ -92,20 +82,20 @@ static void schedule_atimer (struct atimer *);
92static struct atimer *append_atimer_lists (struct atimer *, 82static struct atimer *append_atimer_lists (struct atimer *,
93 struct atimer *); 83 struct atimer *);
94 84
95/* Start a new atimer of type TYPE. TIME specifies when the timer is 85/* Start a new atimer of type TYPE. TIMESTAMP specifies when the timer is
96 ripe. FN is the function to call when the timer fires. 86 ripe. FN is the function to call when the timer fires.
97 CLIENT_DATA is stored in the client_data member of the atimer 87 CLIENT_DATA is stored in the client_data member of the atimer
98 structure returned and so made available to FN when it is called. 88 structure returned and so made available to FN when it is called.
99 89
100 If TYPE is ATIMER_ABSOLUTE, TIME is the absolute time at which the 90 If TYPE is ATIMER_ABSOLUTE, TIMESTAMP is the absolute time at which the
101 timer fires. 91 timer fires.
102 92
103 If TYPE is ATIMER_RELATIVE, the timer is ripe TIME s/us in the 93 If TYPE is ATIMER_RELATIVE, the timer is ripe TIMESTAMP seconds in the
104 future. 94 future.
105 95
106 In both cases, the timer is automatically freed after it has fired. 96 In both cases, the timer is automatically freed after it has fired.
107 97
108 If TYPE is ATIMER_CONTINUOUS, the timer fires every TIME s/us. 98 If TYPE is ATIMER_CONTINUOUS, the timer fires every TIMESTAMP seconds.
109 99
110 Value is a pointer to the atimer started. It can be used in calls 100 Value is a pointer to the atimer started. It can be used in calls
111 to cancel_atimer; don't free it yourself. */ 101 to cancel_atimer; don't free it yourself. */
@@ -117,16 +107,10 @@ start_atimer (enum atimer_type type, struct timespec timestamp,
117 struct atimer *t; 107 struct atimer *t;
118 sigset_t oldset; 108 sigset_t oldset;
119 109
120#if !defined (HAVE_SETITIMER) 110 /* Round TIMESTAMP up to the next full second if we don't have itimers. */
121 /* Round TIME up to the next full second if we don't have itimers. */ 111#ifndef HAVE_SETITIMER
122 if (timestamp.tv_nsec != 0 && timestamp.tv_sec < TYPE_MAXIMUM (time_t)) 112 if (timestamp.tv_nsec != 0 && timestamp.tv_sec < TYPE_MAXIMUM (time_t))
123 timestamp = make_timespec (timestamp.tv_sec + 1, 0); 113 timestamp = make_timespec (timestamp.tv_sec + 1, 0);
124#elif defined (HAVE_CLOCK_GETRES)
125 /* Check that the system clock is precise enough. If
126 not, round TIME up to the system clock resolution. */
127 if (timespec_valid_p (resolution)
128 && timespec_cmp (timestamp, resolution) < 0)
129 timestamp = resolution;
130#endif /* not HAVE_SETITIMER */ 114#endif /* not HAVE_SETITIMER */
131 115
132 /* Get an atimer structure from the free-list, or allocate 116 /* Get an atimer structure from the free-list, or allocate
@@ -311,25 +295,24 @@ set_alarm (void)
311#endif 295#endif
312 struct timespec now, interval; 296 struct timespec now, interval;
313 297
314#if defined (HAVE_TIMERFD) || defined (HAVE_ITIMERSPEC) 298#ifdef HAVE_ITIMERSPEC
315 if (special_timer_available) 299 if (0 <= timerfd || alarm_timer_ok)
316 { 300 {
317 struct itimerspec ispec; 301 struct itimerspec ispec;
318 ispec.it_value = atimers->expiration; 302 ispec.it_value = atimers->expiration;
319 ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0; 303 ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0;
320#if defined (HAVE_TIMERFD) 304# ifdef HAVE_TIMERFD
321 if (special_timer_available == 1) 305 if (timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0)
322 { 306 {
323 add_timer_wait_descriptor (timerfd); 307 add_timer_wait_descriptor (timerfd);
324 special_timer_available++; 308 return;
325 } 309 }
326 if (timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0) 310# endif
327#elif defined (HAVE_ITIMERSPEC) 311 if (alarm_timer_ok
328 if (timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0) == 0) 312 && timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0) == 0)
329#endif
330 return; 313 return;
331 } 314 }
332#endif /* HAVE_TIMERFD || HAVE_ITIMERSPEC */ 315#endif
333 316
334 /* Determine interval till the next timer is ripe. 317 /* Determine interval till the next timer is ripe.
335 Don't set the interval to 0; this disables the timer. */ 318 Don't set the interval to 0; this disables the timer. */
@@ -453,15 +436,15 @@ turn_on_atimers (bool on)
453 set_alarm (); 436 set_alarm ();
454 else 437 else
455 { 438 {
456#ifdef HAVE_TIMERFD 439#ifdef HAVE_ITIMERSPEC
457 if (special_timer_available > 1) 440 struct itimerspec ispec;
458 { 441 memset (&ispec, 0, sizeof ispec);
459 struct itimerspec ispec; 442 if (alarm_timer_ok)
460 memset (&ispec, 0, sizeof (ispec)); 443 timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0);
461 /* Writing zero expiration time should disarm it. */ 444# ifdef HAVE_TIMERFD
462 timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0); 445 timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0);
463 } 446# endif
464#endif /* HAVE_TIMERFD */ 447#endif
465 alarm (0); 448 alarm (0);
466 } 449 }
467} 450}
@@ -494,14 +477,14 @@ debug_timer_callback (struct atimer *t)
494 r->intime = 0; 477 r->intime = 0;
495 else if (result >= 0) 478 else if (result >= 0)
496 { 479 {
497#ifdef HAVE_SETITIMER 480#ifdef HAVE_SETITIMER
498 struct timespec delta = timespec_sub (now, r->expected); 481 struct timespec delta = timespec_sub (now, r->expected);
499 /* Too late if later than expected + 0.01s. FIXME: 482 /* Too late if later than expected + 0.01s. FIXME:
500 this should depend from system clock resolution. */ 483 this should depend from system clock resolution. */
501 if (timespec_cmp (delta, make_timespec (0, 10000000)) > 0) 484 if (timespec_cmp (delta, make_timespec (0, 10000000)) > 0)
502 r->intime = 0; 485 r->intime = 0;
503 else 486 else
504#endif /* HAVE_SETITIMER */ 487#endif /* HAVE_SETITIMER */
505 r->intime = 1; 488 r->intime = 1;
506 } 489 }
507} 490}
@@ -543,21 +526,20 @@ Return t if all self-tests are passed, nil otherwise. */)
543void 526void
544init_atimer (void) 527init_atimer (void)
545{ 528{
546#if defined (HAVE_TIMERFD) 529#ifdef HAVE_ITIMERSPEC
547 timerfd = timerfd_create (CLOCK_REALTIME, TIMERFD_CREATE_FLAGS); 530# ifdef HAVE_TIMERFD
548 special_timer_available = !!(timerfd != -1); 531 timerfd = timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC);
549#elif defined (HAVE_ITIMERSPEC) 532# endif
550 struct sigevent sigev; 533 if (timerfd < 0)
551 sigev.sigev_notify = SIGEV_SIGNAL; 534 {
552 sigev.sigev_signo = SIGALRM; 535 struct sigevent sigev;
553 sigev.sigev_value.sival_ptr = &alarm_timer; 536 sigev.sigev_notify = SIGEV_SIGNAL;
554 special_timer_available 537 sigev.sigev_signo = SIGALRM;
555 = timer_create (CLOCK_REALTIME, &sigev, &alarm_timer) == 0; 538 sigev.sigev_value.sival_ptr = &alarm_timer;
556#endif /* HAVE_TIMERFD */ 539 alarm_timer_ok
557#ifdef HAVE_CLOCK_GETRES 540 = timer_create (CLOCK_REALTIME, &sigev, &alarm_timer) == 0;
558 if (clock_getres (CLOCK_REALTIME, &resolution)) 541 }
559 resolution = invalid_timespec (); 542#endif
560#endif
561 free_atimers = stopped_atimers = atimers = NULL; 543 free_atimers = stopped_atimers = atimers = NULL;
562 544
563 /* pending_signals is initialized in init_keyboard. */ 545 /* pending_signals is initialized in init_keyboard. */
@@ -567,5 +549,5 @@ init_atimer (void)
567 549
568#ifdef ENABLE_CHECKING 550#ifdef ENABLE_CHECKING
569 defsubr (&Sdebug_timer_check); 551 defsubr (&Sdebug_timer_check);
570#endif 552#endif
571} 553}