diff options
| author | Paul Eggert | 2012-09-25 12:18:05 -0700 |
|---|---|---|
| committer | Paul Eggert | 2012-09-25 12:18:05 -0700 |
| commit | e26fd2e4a9bdf06d809bdc03db1eb592a4df8177 (patch) | |
| tree | 0318ab0938ea33132c8699a8007d1d6e3c3a01a3 /src/atimer.c | |
| parent | eedec3eec8ea42189032fcde9d5f11a048fa837a (diff) | |
| download | emacs-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.c | 37 |
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 | ||
| 41 | static struct atimer *atimers; | 41 | static 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 | ||
| 46 | static timer_t alarm_timer; | ||
| 47 | static bool alarm_timer_ok; | ||
| 48 | #endif | ||
| 49 | |||
| 43 | /* Block/unblock SIGALRM. */ | 50 | /* Block/unblock SIGALRM. */ |
| 44 | 51 | ||
| 45 | static void | 52 | static 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 | |||
| 398 | init_atimer (void) | 416 | init_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); |