aboutsummaryrefslogtreecommitdiffstats
path: root/src/atimer.c
diff options
context:
space:
mode:
authorPaul Eggert2014-07-31 13:17:01 -0700
committerPaul Eggert2014-07-31 13:17:01 -0700
commit5c6476b48a2d00bef6ada92fa210ac7cd1bc9a77 (patch)
tree6f92d25b9731476c9aceab154149f8cf87def1e2 /src/atimer.c
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.
Diffstat (limited to 'src/atimer.c')
-rw-r--r--src/atimer.c124
1 files changed, 53 insertions, 71 deletions
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}