diff options
| author | Paul Eggert | 2014-07-31 13:17:01 -0700 |
|---|---|---|
| committer | Paul Eggert | 2014-07-31 13:17:01 -0700 |
| commit | 5c6476b48a2d00bef6ada92fa210ac7cd1bc9a77 (patch) | |
| tree | 6f92d25b9731476c9aceab154149f8cf87def1e2 /src | |
| parent | f3655f35ccd5a56c158a5db399c5f168b2e928d0 (diff) | |
| download | emacs-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')
| -rw-r--r-- | src/ChangeLog | 10 | ||||
| -rw-r--r-- | src/atimer.c | 124 |
2 files changed, 63 insertions, 71 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 985e3b33e06..f3ab7f9b990 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,15 @@ | |||
| 1 | 2014-07-31 Paul Eggert <eggert@cs.ucla.edu> | 1 | 2014-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 | ||
| 50 | static struct atimer *atimers; | 45 | static 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 |
| 54 | static int timerfd; | 49 | POSIX timers are available. */ |
| 55 | #elif defined (HAVE_ITIMERSPEC) | ||
| 56 | /* The alarm timer used if POSIX timers are available. */ | ||
| 57 | static timer_t alarm_timer; | 50 | static timer_t alarm_timer; |
| 58 | #endif | 51 | static 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. */ | ||
| 63 | static 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. */ |
| 68 | static struct timespec resolution; | 55 | static int timerfd; |
| 56 | # else | ||
| 57 | enum { 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 *); | |||
| 92 | static struct atimer *append_atimer_lists (struct atimer *, | 82 | static 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. */) | |||
| 543 | void | 526 | void |
| 544 | init_atimer (void) | 527 | init_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 | } |