summaryrefslogtreecommitdiff
path: root/src/atimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/atimer.c')
-rw-r--r--src/atimer.c47
1 files changed, 32 insertions, 15 deletions
diff --git a/src/atimer.c b/src/atimer.c
index 9b198675ab4..df35603f324 100644
--- a/src/atimer.c
+++ b/src/atimer.c
@@ -305,18 +305,34 @@ set_alarm (void)
#ifdef HAVE_ITIMERSPEC
if (0 <= timerfd || alarm_timer_ok)
{
+ bool exit = false;
struct itimerspec ispec;
ispec.it_value = atimers->expiration;
ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0;
+ if (alarm_timer_ok
+ && timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0) == 0)
+ exit = true;
+
+ /* Don't start both timerfd and POSIX timers on Cygwin; this
+ causes a slowdown (bug#51734). Prefer POSIX timers
+ because the timerfd notifications aren't delivered while
+ Emacs is busy, which prevents things like the hourglass
+ pointer from being displayed reliably (bug#19776). */
+# ifdef CYGWIN
+ if (exit)
+ return;
+# endif
+
# ifdef HAVE_TIMERFD
- if (timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0)
+ if (0 <= timerfd
+ && timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0)
{
add_timer_wait_descriptor (timerfd);
- return;
+ exit = true;
}
# endif
- if (alarm_timer_ok
- && timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0) == 0)
+
+ if (exit)
return;
}
#endif
@@ -333,9 +349,8 @@ set_alarm (void)
memset (&it, 0, sizeof it);
it.it_value = make_timeval (interval);
setitimer (ITIMER_REAL, &it, 0);
-#else /* not HAVE_SETITIMER */
- alarm (max (interval.tv_sec, 1));
#endif /* not HAVE_SETITIMER */
+ alarm (max (interval.tv_sec, 1));
}
}
@@ -583,15 +598,17 @@ init_atimer (void)
timerfd = (egetenv ("EMACS_IGNORE_TIMERFD") || have_buggy_timerfd () ? -1 :
timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC));
# endif
- if (timerfd < 0)
- {
- struct sigevent sigev;
- sigev.sigev_notify = SIGEV_SIGNAL;
- sigev.sigev_signo = SIGALRM;
- sigev.sigev_value.sival_ptr = &alarm_timer;
- alarm_timer_ok
- = timer_create (CLOCK_REALTIME, &sigev, &alarm_timer) == 0;
- }
+ /* We're starting the alarms even if we have timerfd, because
+ timerfd events do not fire while Emacs Lisp is busy and doesn't
+ call thread_select. This might or might not mean that the
+ timerfd code doesn't really give us anything and should be
+ removed, see discussion in bug#19776. */
+ struct sigevent sigev;
+ sigev.sigev_notify = SIGEV_SIGNAL;
+ sigev.sigev_signo = SIGALRM;
+ sigev.sigev_value.sival_ptr = &alarm_timer;
+ alarm_timer_ok
+ = timer_create (CLOCK_REALTIME, &sigev, &alarm_timer) == 0;
#endif
free_atimers = stopped_atimers = atimers = NULL;