aboutsummaryrefslogtreecommitdiffstats
path: root/src/atimer.c
diff options
context:
space:
mode:
authorPaul Eggert2012-09-25 12:18:05 -0700
committerPaul Eggert2012-09-25 12:18:05 -0700
commite26fd2e4a9bdf06d809bdc03db1eb592a4df8177 (patch)
tree0318ab0938ea33132c8699a8007d1d6e3c3a01a3 /src/atimer.c
parenteedec3eec8ea42189032fcde9d5f11a048fa837a (diff)
downloademacs-e26fd2e4a9bdf06d809bdc03db1eb592a4df8177.tar.gz
emacs-e26fd2e4a9bdf06d809bdc03db1eb592a4df8177.zip
Prefer POSIX timers if available.
They avoid a race if the timer is too close to the current time. * atimer.c (alarm_timer, alarm_timer_ok) [SIGEV_SIGNAL]: New static vars. (set_alarm) [SIGEV_SIGNAL]: Use POSIX timers if available. (init_atimer) [SIGEV_SIGAL]: Initialize them.
Diffstat (limited to 'src/atimer.c')
-rw-r--r--src/atimer.c37
1 files changed, 31 insertions, 6 deletions
diff --git a/src/atimer.c b/src/atimer.c
index d3b6c7d8fd3..8bb80445bde 100644
--- a/src/atimer.c
+++ b/src/atimer.c
@@ -40,6 +40,13 @@ static struct atimer *stopped_atimers;
40 40
41static struct atimer *atimers; 41static struct atimer *atimers;
42 42
43/* The alarm timer and whether it was properly initialized, if
44 POSIX timers are available. */
45#ifdef SIGEV_SIGNAL
46static timer_t alarm_timer;
47static bool alarm_timer_ok;
48#endif
49
43/* Block/unblock SIGALRM. */ 50/* Block/unblock SIGALRM. */
44 51
45static void 52static void
@@ -287,14 +294,25 @@ set_alarm (void)
287#ifdef HAVE_SETITIMER 294#ifdef HAVE_SETITIMER
288 struct itimerval it; 295 struct itimerval it;
289#endif 296#endif
297 EMACS_TIME now, interval;
290 298
291 /* Determine s/us till the next timer is ripe. */ 299#ifdef SIGEV_SIGNAL
292 EMACS_TIME now = current_emacs_time (); 300 if (alarm_timer_ok)
301 {
302 struct itimerspec ispec;
303 ispec.it_value = atimers->expiration;
304 ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0;
305 if (timer_settime (alarm_timer, 0, &ispec, 0) == 0)
306 return;
307 }
308#endif
293 309
294 /* Don't set the interval to 0; this disables the timer. */ 310 /* Determine interval till the next timer is ripe.
295 EMACS_TIME interval = (EMACS_TIME_LE (atimers->expiration, now) 311 Don't set the interval to 0; this disables the timer. */
296 ? make_emacs_time (0, 1000 * 1000) 312 now = current_emacs_time ();
297 : sub_emacs_time (atimers->expiration, now)); 313 interval = (EMACS_TIME_LE (atimers->expiration, now)
314 ? make_emacs_time (0, 1000 * 1000)
315 : sub_emacs_time (atimers->expiration, now));
298 316
299#ifdef HAVE_SETITIMER 317#ifdef HAVE_SETITIMER
300 318
@@ -398,6 +416,13 @@ void
398init_atimer (void) 416init_atimer (void)
399{ 417{
400 struct sigaction action; 418 struct sigaction action;
419#ifdef SIGEV_SIGNAL
420 struct sigevent sigev;
421 sigev.sigev_notify = SIGEV_SIGNAL;
422 sigev.sigev_signo = SIGALRM;
423 sigev.sigev_value.sival_ptr = &alarm_timer;
424 alarm_timer_ok = timer_create (CLOCK_REALTIME, &sigev, &alarm_timer) == 0;
425#endif
401 free_atimers = stopped_atimers = atimers = NULL; 426 free_atimers = stopped_atimers = atimers = NULL;
402 /* pending_signals is initialized in init_keyboard.*/ 427 /* pending_signals is initialized in init_keyboard.*/
403 emacs_sigaction_init (&action, handle_alarm_signal); 428 emacs_sigaction_init (&action, handle_alarm_signal);