X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/2ab329f3b5d52a39f0a45c3d9c129f1c19560142..1271626ab5d345cdfcd9aca1c528f6ed6152ef96:/src/atimer.c diff --git a/src/atimer.c b/src/atimer.c index 5dbd807872..d98ddac017 100644 --- a/src/atimer.c +++ b/src/atimer.c @@ -1,5 +1,5 @@ /* Asynchronous timers. - Copyright (C) 2000-2012 Free Software Foundation, Inc. + Copyright (C) 2000-2014 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -40,13 +40,12 @@ static struct atimer *stopped_atimers; static struct atimer *atimers; -/* Non-zero means alarm signal handler has found ripe timers but - interrupt_input_blocked was non-zero. In this case, timer - functions are not called until the next UNBLOCK_INPUT because timer - functions are expected to call X, and X cannot be assumed to be - reentrant. */ - -int pending_atimers; +/* The alarm timer and whether it was properly initialized, if + POSIX timers are available. */ +#ifdef HAVE_ITIMERSPEC +static timer_t alarm_timer; +static bool alarm_timer_ok; +#endif /* Block/unblock SIGALRM. */ @@ -95,17 +94,16 @@ static struct atimer *append_atimer_lists (struct atimer *, to cancel_atimer; don't free it yourself. */ struct atimer * -start_atimer (enum atimer_type type, EMACS_TIME timestamp, atimer_callback fn, - void *client_data) +start_atimer (enum atimer_type type, struct timespec timestamp, + atimer_callback fn, void *client_data) { struct atimer *t; /* Round TIME up to the next full second if we don't have itimers. */ #ifndef HAVE_SETITIMER - if (EMACS_NSECS (timestamp) != 0 - && EMACS_SECS (timestamp) < TYPE_MAXIMUM (time_t)) - timestamp = make_emacs_time (EMACS_SECS (timestamp) + 1, 0); + if (timestamp.tv_nsec != 0 && timestamp.tv_sec < TYPE_MAXIMUM (time_t)) + timestamp = make_timespec (timestamp.tv_sec + 1, 0); #endif /* not HAVE_SETITIMER */ /* Get an atimer structure from the free-list, or allocate @@ -134,11 +132,11 @@ start_atimer (enum atimer_type type, EMACS_TIME timestamp, atimer_callback fn, break; case ATIMER_RELATIVE: - t->expiration = add_emacs_time (current_emacs_time (), timestamp); + t->expiration = timespec_add (current_timespec (), timestamp); break; case ATIMER_CONTINUOUS: - t->expiration = add_emacs_time (current_emacs_time (), timestamp); + t->expiration = timespec_add (current_timespec (), timestamp); t->interval = timestamp; break; } @@ -251,7 +249,7 @@ stop_other_atimers (struct atimer *t) /* Run all timers again, if some have been stopped with a call to stop_other_atimers. */ -static void +void run_all_atimers (void) { if (stopped_atimers) @@ -275,16 +273,6 @@ run_all_atimers (void) } -/* A version of run_all_atimers suitable for a record_unwind_protect. */ - -Lisp_Object -unwind_stop_other_atimers (Lisp_Object dummy) -{ - run_all_atimers (); - return Qnil; -} - - /* Arrange for a SIGALRM to arrive when the next timer is ripe. */ static void @@ -295,14 +283,25 @@ set_alarm (void) #ifdef HAVE_SETITIMER struct itimerval it; #endif + struct timespec now, interval; - /* Determine s/us till the next timer is ripe. */ - EMACS_TIME now = current_emacs_time (); +#ifdef HAVE_ITIMERSPEC + if (alarm_timer_ok) + { + struct itimerspec ispec; + ispec.it_value = atimers->expiration; + ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0; + if (timer_settime (alarm_timer, 0, &ispec, 0) == 0) + return; + } +#endif - /* Don't set the interval to 0; this disables the timer. */ - EMACS_TIME interval = (EMACS_TIME_LE (atimers->expiration, now) - ? make_emacs_time (0, 1000 * 1000) - : sub_emacs_time (atimers->expiration, now)); + /* Determine interval till the next timer is ripe. + Don't set the interval to 0; this disables the timer. */ + now = current_timespec (); + interval = (timespec_cmp (atimers->expiration, now) <= 0 + ? make_timespec (0, 1000 * 1000) + : timespec_sub (atimers->expiration, now)); #ifdef HAVE_SETITIMER @@ -310,7 +309,7 @@ set_alarm (void) it.it_value = make_timeval (interval); setitimer (ITIMER_REAL, &it, 0); #else /* not HAVE_SETITIMER */ - alarm (max (EMACS_SECS (interval), 1)); + alarm (max (interval.tv_sec, 1)); #endif /* not HAVE_SETITIMER */ } } @@ -326,7 +325,7 @@ schedule_atimer (struct atimer *t) struct atimer *a = atimers, *prev = NULL; /* Look for the first atimer that is ripe after T. */ - while (a && EMACS_TIME_GT (t->expiration, a->expiration)) + while (a && timespec_cmp (a->expiration, t->expiration) < 0) prev = a, a = a->next; /* Insert T in front of the atimer found, if any. */ @@ -341,22 +340,17 @@ schedule_atimer (struct atimer *t) static void run_timers (void) { - EMACS_TIME now; + struct timespec now = current_timespec (); - while (atimers - && (pending_atimers = interrupt_input_blocked) == 0 - && (now = current_emacs_time (), - EMACS_TIME_LE (atimers->expiration, now))) + while (atimers && timespec_cmp (atimers->expiration, now) <= 0) { - struct atimer *t; - - t = atimers; + struct atimer *t = atimers; atimers = atimers->next; t->fn (t); if (t->type == ATIMER_CONTINUOUS) { - t->expiration = add_emacs_time (now, t->interval); + t->expiration = timespec_add (now, t->interval); schedule_atimer (t); } else @@ -366,16 +360,7 @@ run_timers (void) } } - if (! atimers) - pending_atimers = 0; - - if (pending_atimers) - pending_signals = 1; - else - { - pending_signals = interrupt_input_pending; - set_alarm (); - } + set_alarm (); } @@ -385,23 +370,16 @@ run_timers (void) static void handle_alarm_signal (int sig) { - pending_atimers = 1; pending_signals = 1; } -static void -deliver_alarm_signal (int sig) -{ - handle_on_main_thread (sig, handle_alarm_signal); -} - -/* Call alarm signal handler for pending timers. */ +/* Do pending timers. */ void do_pending_atimers (void) { - if (pending_atimers) + if (atimers) { block_atimers (); run_timers (); @@ -417,12 +395,7 @@ void turn_on_atimers (bool on) { if (on) - { - struct sigaction action; - emacs_sigaction_init (&action, deliver_alarm_signal); - sigaction (SIGALRM, &action, 0); - set_alarm (); - } + set_alarm (); else alarm (0); } @@ -432,9 +405,15 @@ void init_atimer (void) { struct sigaction action; +#ifdef HAVE_ITIMERSPEC + 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; - pending_atimers = 0; /* pending_signals is initialized in init_keyboard.*/ - emacs_sigaction_init (&action, deliver_alarm_signal); + emacs_sigaction_init (&action, handle_alarm_signal); sigaction (SIGALRM, &action, 0); }