root/src/atimer.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. block_atimers
  2. unblock_atimers
  3. start_atimer
  4. cancel_atimer
  5. append_atimer_lists
  6. stop_other_atimers
  7. run_all_atimers
  8. set_alarm
  9. schedule_atimer
  10. run_timers
  11. handle_alarm_signal
  12. timerfd_callback
  13. do_pending_atimers
  14. turn_on_atimers
  15. debug_timer_callback
  16. DEFUN
  17. have_buggy_timerfd
  18. init_atimer

     1 /* Asynchronous timers.
     2    Copyright (C) 2000-2023 Free Software Foundation, Inc.
     3 
     4 This file is part of GNU Emacs.
     5 
     6 GNU Emacs is free software: you can redistribute it and/or modify
     7 it under the terms of the GNU General Public License as published by
     8 the Free Software Foundation, either version 3 of the License, or (at
     9 your option) any later version.
    10 
    11 GNU Emacs is distributed in the hope that it will be useful,
    12 but WITHOUT ANY WARRANTY; without even the implied warranty of
    13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14 GNU General Public License for more details.
    15 
    16 You should have received a copy of the GNU General Public License
    17 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    18 
    19 #include <config.h>
    20 
    21 #ifdef WINDOWSNT
    22 #define raise(s) w32_raise(s)
    23 #endif
    24 
    25 #include "lisp.h"
    26 #include "keyboard.h"
    27 #include "syssignal.h"
    28 #include "systime.h"
    29 #include "atimer.h"
    30 #include <unistd.h>
    31 
    32 #ifdef HAVE_TIMERFD
    33 #include <errno.h>
    34 #include <sys/timerfd.h>
    35 # ifdef CYGWIN
    36 # include <sys/utsname.h>
    37 # endif
    38 #endif
    39 
    40 #ifdef MSDOS
    41 #include "msdos.h"
    42 #endif
    43 
    44 /* Free-list of atimer structures.  */
    45 
    46 static struct atimer *free_atimers;
    47 
    48 /* List of currently not running timers due to a call to
    49    lock_atimer.  */
    50 
    51 static struct atimer *stopped_atimers;
    52 
    53 /* List of active atimers, sorted by expiration time.  The timer that
    54    will become ripe next is always at the front of this list.  */
    55 
    56 static struct atimer *atimers;
    57 
    58 #ifdef HAVE_ITIMERSPEC
    59 /* The alarm timer and whether it was properly initialized, if
    60    POSIX timers are available.  */
    61 static timer_t alarm_timer;
    62 static bool alarm_timer_ok;
    63 
    64 # ifdef HAVE_TIMERFD
    65 /* File descriptor for timer, or -1 if it could not be created.  */
    66 static int timerfd;
    67 # else
    68 enum { timerfd = -1 };
    69 # endif
    70 #endif
    71 
    72 /* Block/unblock SIGALRM.  */
    73 
    74 static void
    75 block_atimers (sigset_t *oldset)
    76 {
    77   sigset_t blocked;
    78   sigemptyset (&blocked);
    79   sigaddset (&blocked, SIGALRM);
    80   sigaddset (&blocked, SIGINT);
    81   pthread_sigmask (SIG_BLOCK, &blocked, oldset);
    82 }
    83 static void
    84 unblock_atimers (sigset_t const *oldset)
    85 {
    86   pthread_sigmask (SIG_SETMASK, oldset, 0);
    87 }
    88 
    89 /* Function prototypes.  */
    90 
    91 static void set_alarm (void);
    92 static void schedule_atimer (struct atimer *);
    93 static struct atimer *append_atimer_lists (struct atimer *,
    94                                            struct atimer *);
    95 
    96 /* Start a new atimer of type TYPE.  TIMESTAMP specifies when the timer is
    97    ripe.  FN is the function to call when the timer fires.
    98    CLIENT_DATA is stored in the client_data member of the atimer
    99    structure returned and so made available to FN when it is called.
   100 
   101    If TYPE is ATIMER_ABSOLUTE, TIMESTAMP is the absolute time at which the
   102    timer fires.
   103 
   104    If TYPE is ATIMER_RELATIVE, the timer is ripe TIMESTAMP seconds in the
   105    future.
   106 
   107    In both cases, the timer is automatically freed after it has fired.
   108 
   109    If TYPE is ATIMER_CONTINUOUS, the timer fires every TIMESTAMP seconds.
   110 
   111    Value is a pointer to the atimer started.  It can be used in calls
   112    to cancel_atimer; don't free it yourself.  */
   113 
   114 struct atimer *
   115 start_atimer (enum atimer_type type, struct timespec timestamp,
   116               atimer_callback fn, void *client_data)
   117 {
   118   struct atimer *t;
   119   sigset_t oldset;
   120 
   121   /* Round TIMESTAMP up to the next full second if we don't have itimers.  */
   122 #if ! (defined HAVE_ITIMERSPEC || defined HAVE_SETITIMER)
   123   if (timestamp.tv_nsec != 0 && timestamp.tv_sec < TYPE_MAXIMUM (time_t))
   124     timestamp = make_timespec (timestamp.tv_sec + 1, 0);
   125 #endif
   126 
   127   /* Get an atimer structure from the free-list, or allocate
   128      a new one.  */
   129   if (free_atimers)
   130     {
   131       t = free_atimers;
   132       free_atimers = t->next;
   133     }
   134   else
   135     t = xmalloc (sizeof *t);
   136 
   137   /* Fill the atimer structure.  */
   138   memset (t, 0, sizeof *t);
   139   t->type = type;
   140   t->fn = fn;
   141   t->client_data = client_data;
   142 
   143   block_atimers (&oldset);
   144 
   145   /* Compute the timer's expiration time.  */
   146   switch (type)
   147     {
   148     case ATIMER_ABSOLUTE:
   149       t->expiration = timestamp;
   150       break;
   151 
   152     case ATIMER_RELATIVE:
   153       t->expiration = timespec_add (current_timespec (), timestamp);
   154       break;
   155 
   156     case ATIMER_CONTINUOUS:
   157       t->expiration = timespec_add (current_timespec (), timestamp);
   158       t->interval = timestamp;
   159       break;
   160     }
   161 
   162   /* Insert the timer in the list of active atimers.  */
   163   schedule_atimer (t);
   164   unblock_atimers (&oldset);
   165 
   166   /* Arrange for a SIGALRM at the time the next atimer is ripe.  */
   167   set_alarm ();
   168 
   169   return t;
   170 }
   171 
   172 
   173 /* Cancel and free atimer TIMER.  */
   174 
   175 void
   176 cancel_atimer (struct atimer *timer)
   177 {
   178   int i;
   179   sigset_t oldset;
   180 
   181   block_atimers (&oldset);
   182 
   183   for (i = 0; i < 2; ++i)
   184     {
   185       struct atimer *t, *prev;
   186       struct atimer **list = i ? &stopped_atimers : &atimers;
   187 
   188       /* See if TIMER is active or stopped.  */
   189       for (t = *list, prev = NULL; t && t != timer; prev = t, t = t->next)
   190         ;
   191 
   192       /* If it is, take it off its list, and put in on the free-list.
   193          We don't bother to arrange for setting a different alarm time,
   194          since a too early one doesn't hurt.  */
   195       if (t)
   196         {
   197           if (prev)
   198             prev->next = t->next;
   199           else
   200             *list = t->next;
   201 
   202           t->next = free_atimers;
   203           free_atimers = t;
   204           break;
   205         }
   206     }
   207 
   208   unblock_atimers (&oldset);
   209 }
   210 
   211 
   212 /* Append two lists of atimers LIST_1 and LIST_2 and return the
   213    result list.  */
   214 
   215 static struct atimer *
   216 append_atimer_lists (struct atimer *list_1, struct atimer *list_2)
   217 {
   218   if (list_1 == NULL)
   219     return list_2;
   220   else if (list_2 == NULL)
   221     return list_1;
   222   else
   223     {
   224       struct atimer *p;
   225 
   226       for (p = list_1; p->next; p = p->next)
   227         ;
   228       p->next = list_2;
   229       return list_1;
   230     }
   231 }
   232 
   233 
   234 /* Stop all timers except timer T.  T null means stop all timers.  */
   235 
   236 void
   237 stop_other_atimers (struct atimer *t)
   238 {
   239   sigset_t oldset;
   240   block_atimers (&oldset);
   241 
   242   if (t)
   243     {
   244       struct atimer *p, *prev;
   245 
   246       /* See if T is active.  */
   247       for (p = atimers, prev = NULL; p && p != t; prev = p, p = p->next)
   248         ;
   249 
   250       if (p == t)
   251         {
   252           if (prev)
   253             prev->next = t->next;
   254           else
   255             atimers = t->next;
   256           t->next = NULL;
   257         }
   258       else
   259         /* T is not active.  Let's handle this like T == 0.  */
   260         t = NULL;
   261     }
   262 
   263   stopped_atimers = append_atimer_lists (atimers, stopped_atimers);
   264   atimers = t;
   265   unblock_atimers (&oldset);
   266 }
   267 
   268 
   269 /* Run all timers again, if some have been stopped with a call to
   270    stop_other_atimers.  */
   271 
   272 void
   273 run_all_atimers (void)
   274 {
   275   if (stopped_atimers)
   276     {
   277       struct atimer *t = atimers;
   278       struct atimer *next;
   279       sigset_t oldset;
   280 
   281       block_atimers (&oldset);
   282       atimers = stopped_atimers;
   283       stopped_atimers = NULL;
   284 
   285       while (t)
   286         {
   287           next = t->next;
   288           schedule_atimer (t);
   289           t = next;
   290         }
   291 
   292       unblock_atimers (&oldset);
   293     }
   294 }
   295 
   296 
   297 /* Arrange for a SIGALRM to arrive when the next timer is ripe.  */
   298 
   299 static void
   300 set_alarm (void)
   301 {
   302   if (atimers)
   303     {
   304 #ifdef HAVE_ITIMERSPEC
   305       if (0 <= timerfd || alarm_timer_ok)
   306         {
   307           bool exit = false;
   308           struct itimerspec ispec;
   309           ispec.it_value = atimers->expiration;
   310           ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0;
   311           if (alarm_timer_ok
   312               && timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0) == 0)
   313             exit = true;
   314 
   315           /* Don't start both timerfd and POSIX timers on Cygwin; this
   316              causes a slowdown (bug#51734).  Prefer POSIX timers
   317              because the timerfd notifications aren't delivered while
   318              Emacs is busy, which prevents things like the hourglass
   319              pointer from being displayed reliably (bug#19776). */
   320 # ifdef CYGWIN
   321           if (exit)
   322             return;
   323 # endif
   324 
   325 # ifdef HAVE_TIMERFD
   326           if (0 <= timerfd
   327               && timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0)
   328             {
   329               add_timer_wait_descriptor (timerfd);
   330               exit = true;
   331             }
   332 # endif
   333 
   334           if (exit)
   335             return;
   336         }
   337 #endif
   338 
   339       /* Determine interval till the next timer is ripe.  */
   340       struct timespec now = current_timespec ();
   341       if (timespec_cmp (atimers->expiration, now) <= 0)
   342         {
   343           /* Timer is (over)due -- just trigger the signal right way.  */
   344           raise (SIGALRM);
   345         }
   346       else
   347         {
   348           struct timespec interval = timespec_sub (atimers->expiration, now);
   349 
   350 #ifdef HAVE_SETITIMER
   351           struct itimerval it = {.it_value = make_timeval (interval)};
   352           setitimer (ITIMER_REAL, &it, 0);
   353 #else
   354           alarm (max (interval.tv_sec, 1));
   355 #endif
   356         }
   357     }
   358 }
   359 
   360 
   361 /* Insert timer T into the list of active atimers `atimers', keeping
   362    the list sorted by expiration time.  T must not be in this list
   363    already.  */
   364 
   365 static void
   366 schedule_atimer (struct atimer *t)
   367 {
   368   struct atimer *a = atimers, *prev = NULL;
   369 
   370   /* Look for the first atimer that is ripe after T.  */
   371   while (a && timespec_cmp (a->expiration, t->expiration) < 0)
   372     prev = a, a = a->next;
   373 
   374   /* Insert T in front of the atimer found, if any.  */
   375   if (prev)
   376     prev->next = t;
   377   else
   378     atimers = t;
   379 
   380   t->next = a;
   381 }
   382 
   383 static void
   384 run_timers (void)
   385 {
   386   struct timespec now = current_timespec ();
   387 
   388   while (atimers && timespec_cmp (atimers->expiration, now) <= 0)
   389     {
   390       struct atimer *t = atimers;
   391       atimers = atimers->next;
   392       t->fn (t);
   393 
   394       if (t->type == ATIMER_CONTINUOUS)
   395         {
   396           t->expiration = timespec_add (now, t->interval);
   397           schedule_atimer (t);
   398         }
   399       else
   400         {
   401           t->next = free_atimers;
   402           free_atimers = t;
   403         }
   404     }
   405 
   406   set_alarm ();
   407 }
   408 
   409 
   410 /* Signal handler for SIGALRM.  SIGNO is the signal number, i.e.
   411    SIGALRM.  */
   412 
   413 static void
   414 handle_alarm_signal (int sig)
   415 {
   416   pending_signals = 1;
   417 }
   418 
   419 #ifdef HAVE_TIMERFD
   420 
   421 /* Called from wait_reading_process_output when FD, which
   422    should be equal to TIMERFD, is available for reading.  */
   423 
   424 void
   425 timerfd_callback (int fd, void *arg)
   426 {
   427   ptrdiff_t nbytes;
   428   uint64_t expirations;
   429 
   430   eassert (fd == timerfd);
   431   nbytes = emacs_read (fd, &expirations, sizeof (expirations));
   432 
   433   if (nbytes == sizeof (expirations))
   434     {
   435       /* Timer should expire just once.  */
   436       eassert (expirations == 1);
   437       do_pending_atimers ();
   438     }
   439   else if (nbytes < 0)
   440     /* For some not yet known reason, we may get weird event and no
   441        data on timer descriptor.  This can break Gnus at least, see:
   442        https://lists.gnu.org/r/emacs-devel/2014-07/msg00503.html.  */
   443     eassert (errno == EAGAIN);
   444   else
   445     /* I don't know what else can happen with this descriptor.  */
   446     emacs_abort ();
   447 }
   448 
   449 #endif /* HAVE_TIMERFD */
   450 
   451 /* Do pending timers.  */
   452 
   453 void
   454 do_pending_atimers (void)
   455 {
   456   if (atimers)
   457     {
   458       sigset_t oldset;
   459       block_atimers (&oldset);
   460       run_timers ();
   461       unblock_atimers (&oldset);
   462     }
   463 }
   464 
   465 
   466 /* Turn alarms on/off.  This seems to be temporarily necessary on
   467    some systems like HPUX (see process.c).  */
   468 
   469 void
   470 turn_on_atimers (bool on)
   471 {
   472   if (on)
   473     set_alarm ();
   474   else
   475     {
   476 #ifdef HAVE_ITIMERSPEC
   477       struct itimerspec ispec;
   478       memset (&ispec, 0, sizeof ispec);
   479       if (alarm_timer_ok)
   480         timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0);
   481 # ifdef HAVE_TIMERFD
   482       timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0);
   483 # endif
   484 #endif
   485       alarm (0);
   486     }
   487 }
   488 
   489 /* This is intended to use from automated tests.  */
   490 
   491 #ifdef ENABLE_CHECKING
   492 
   493 #define MAXTIMERS 10
   494 
   495 struct atimer_result
   496 {
   497   /* Time when we expect this timer to trigger.  */
   498   struct timespec expected;
   499 
   500   /* Timer status: -1 if not triggered, 0 if triggered
   501      too early or too late, 1 if triggered timely.  */
   502   int intime;
   503 };
   504 
   505 static void
   506 debug_timer_callback (struct atimer *t)
   507 {
   508   struct timespec now = current_timespec ();
   509   struct atimer_result *r = (struct atimer_result *) t->client_data;
   510   int result = timespec_cmp (now, r->expected);
   511 
   512   if (result < 0)
   513     /* Too early.  */
   514     r->intime = 0;
   515   else if (result >= 0)
   516     {
   517       bool intime = true;
   518 #if defined HAVE_ITIMERSPEC || defined HAVE_SETITIMER
   519       struct timespec delta = timespec_sub (now, r->expected);
   520       /* Too late if later than expected + 0.02s.  FIXME:
   521          this should depend from system clock resolution.  */
   522       intime = timespec_cmp (delta, make_timespec (0, 20000000)) <= 0;
   523 #endif
   524       r->intime = intime;
   525     }
   526 }
   527 
   528 DEFUN ("debug-timer-check", Fdebug_timer_check, Sdebug_timer_check, 0, 0, 0,
   529        doc: /* Run internal self-tests to check timers subsystem.
   530 Return t if all self-tests are passed, nil otherwise.  */)
   531   (void)
   532 {
   533   int i, ok;
   534   struct atimer *timer;
   535   struct atimer_result *results[MAXTIMERS];
   536   struct timespec t = make_timespec (0, 0);
   537 
   538   /* Arm MAXTIMERS relative timers to trigger with 0.1s intervals.  */
   539   for (i = 0; i < MAXTIMERS; i++)
   540     {
   541       results[i] = xmalloc (sizeof (struct atimer_result));
   542       t = timespec_add (t, make_timespec (0, 100000000));
   543       results[i]->expected = timespec_add (current_timespec (), t);
   544       results[i]->intime = -1;
   545       timer = start_atimer (ATIMER_RELATIVE, t,
   546                             debug_timer_callback, results[i]);
   547     }
   548 
   549 #ifdef HAVE_TIMERFD
   550   /* Wait for 1s but process timers.  */
   551   wait_reading_process_output (1, 0, 0, false, Qnil, NULL, 0);
   552 #else
   553   /* If timerfd is not supported, wait_reading_process_output won't
   554      pay attention to timers that expired, and the callbacks won't be
   555      called.  So we need to run the expired timers' callbacks by
   556      hand.  */
   557   /* Wait 1.2 sec for the timers to expire.  */
   558   struct timespec tend =
   559     timespec_add (current_timespec (), make_timespec (1, 200000000));
   560 
   561   while (timespec_cmp (current_timespec (), tend) < 0)
   562     {
   563       /* Wait for 5 msec between iterations.  */
   564       wait_reading_process_output (0, 5000000, 0, false, Qnil, NULL, 0);
   565       if (pending_signals)
   566         do_pending_atimers ();
   567     }
   568 #endif
   569   /* Shut up the compiler by "using" this variable.  */
   570   (void) timer;
   571 
   572   for (i = 0, ok = 0; i < MAXTIMERS; i++)
   573     ok += results[i]->intime, xfree (results[i]);
   574 
   575   return ok == MAXTIMERS ? Qt : Qnil;
   576 }
   577 
   578 #endif /* ENABLE_CHECKING */
   579 
   580 /* Cygwin has the timerfd interface starting with release 3.0.0, but
   581    it is buggy until release 3.0.2. */
   582 #ifdef HAVE_TIMERFD
   583 static bool
   584 have_buggy_timerfd (void)
   585 {
   586 # ifdef CYGWIN
   587   struct utsname name;
   588   return uname (&name) < 0 || strverscmp (name.release, "3.0.2") < 0;
   589 # else
   590   return false;
   591 # endif
   592 }
   593 #endif
   594 
   595 void
   596 init_atimer (void)
   597 {
   598 #ifdef HAVE_ITIMERSPEC
   599 # ifdef HAVE_TIMERFD
   600   /* Until this feature is considered stable, you can ask to not use it.  */
   601   timerfd = (egetenv ("EMACS_IGNORE_TIMERFD") || have_buggy_timerfd () ? -1 :
   602              timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC));
   603 # endif
   604   /* We're starting the alarms even if we have timerfd, because
   605      timerfd events do not fire while Emacs Lisp is busy and doesn't
   606      call thread_select.  This might or might not mean that the
   607      timerfd code doesn't really give us anything and should be
   608      removed, see discussion in bug#19776.  */
   609   struct sigevent sigev;
   610   sigev.sigev_notify = SIGEV_SIGNAL;
   611   sigev.sigev_signo = SIGALRM;
   612   sigev.sigev_value.sival_ptr = &alarm_timer;
   613   alarm_timer_ok
   614     = timer_create (CLOCK_REALTIME, &sigev, &alarm_timer) == 0;
   615 #endif
   616   free_atimers = stopped_atimers = atimers = NULL;
   617 
   618   /* pending_signals is initialized in init_keyboard.  */
   619   struct sigaction action;
   620   emacs_sigaction_init (&action, handle_alarm_signal);
   621   sigaction (SIGALRM, &action, 0);
   622 
   623 #ifdef ENABLE_CHECKING
   624   if (!initialized)
   625     defsubr (&Sdebug_timer_check);
   626 #endif
   627 }

/* [<][>][^][v][top][bottom][index][help] */