atimer.c 13.8 KB
Newer Older
Gerd Moellmann's avatar
Gerd Moellmann committed
1
/* Asynchronous timers.
Paul Eggert's avatar
Paul Eggert committed
2
   Copyright (C) 2000-2015 Free Software Foundation, Inc.
Gerd Moellmann's avatar
Gerd Moellmann committed
3 4 5

This file is part of GNU Emacs.

6
GNU Emacs is free software: you can redistribute it and/or modify
Gerd Moellmann's avatar
Gerd Moellmann committed
7
it under the terms of the GNU General Public License as published by
8 9
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gerd Moellmann's avatar
Gerd Moellmann committed
10 11 12 13 14 15 16

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
17
along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
18 19

#include <config.h>
20
#include <stdio.h>
21

22 23 24 25 26
#include "lisp.h"
#include "syssignal.h"
#include "systime.h"
#include "blockinput.h"
#include "atimer.h"
Gerd Moellmann's avatar
Gerd Moellmann committed
27 28
#include <unistd.h>

29
#ifdef HAVE_TIMERFD
30
#include <errno.h>
31 32
# include <sys/timerfd.h>
#endif
33

Gerd Moellmann's avatar
Gerd Moellmann committed
34 35 36 37
/* Free-list of atimer structures.  */

static struct atimer *free_atimers;

38 39 40 41 42
/* List of currently not running timers due to a call to
   lock_atimer.  */

static struct atimer *stopped_atimers;

Gerd Moellmann's avatar
Gerd Moellmann committed
43 44 45 46 47
/* List of active atimers, sorted by expiration time.  The timer that
   will become ripe next is always at the front of this list.  */

static struct atimer *atimers;

48 49 50
#ifdef HAVE_ITIMERSPEC
/* The alarm timer and whether it was properly initialized, if
   POSIX timers are available.  */
51
static timer_t alarm_timer;
52
static bool alarm_timer_ok;
53

54 55 56 57 58 59
# ifdef HAVE_TIMERFD
/* File descriptor for timer, or -1 if it could not be created.  */
static int timerfd;
# else
enum { timerfd = -1 };
# endif
60 61
#endif

Pavel Janík's avatar
Pavel Janík committed
62
/* Block/unblock SIGALRM.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
63

Paul Eggert's avatar
Paul Eggert committed
64
static void
65
block_atimers (sigset_t *oldset)
Paul Eggert's avatar
Paul Eggert committed
66 67 68 69
{
  sigset_t blocked;
  sigemptyset (&blocked);
  sigaddset (&blocked, SIGALRM);
70
  sigaddset (&blocked, SIGINT);
71
  pthread_sigmask (SIG_BLOCK, &blocked, oldset);
Paul Eggert's avatar
Paul Eggert committed
72 73
}
static void
74
unblock_atimers (sigset_t const *oldset)
Paul Eggert's avatar
Paul Eggert committed
75
{
76
  pthread_sigmask (SIG_SETMASK, oldset, 0);
Paul Eggert's avatar
Paul Eggert committed
77
}
Gerd Moellmann's avatar
Gerd Moellmann committed
78 79 80

/* Function prototypes.  */

81 82 83 84
static void set_alarm (void);
static void schedule_atimer (struct atimer *);
static struct atimer *append_atimer_lists (struct atimer *,
                                           struct atimer *);
Gerd Moellmann's avatar
Gerd Moellmann committed
85

86
/* Start a new atimer of type TYPE.  TIMESTAMP specifies when the timer is
Gerd Moellmann's avatar
Gerd Moellmann committed
87 88 89 90
   ripe.  FN is the function to call when the timer fires.
   CLIENT_DATA is stored in the client_data member of the atimer
   structure returned and so made available to FN when it is called.

91
   If TYPE is ATIMER_ABSOLUTE, TIMESTAMP is the absolute time at which the
Gerd Moellmann's avatar
Gerd Moellmann committed
92 93
   timer fires.

94
   If TYPE is ATIMER_RELATIVE, the timer is ripe TIMESTAMP seconds in the
Gerd Moellmann's avatar
Gerd Moellmann committed
95 96 97 98
   future.

   In both cases, the timer is automatically freed after it has fired.

99
   If TYPE is ATIMER_CONTINUOUS, the timer fires every TIMESTAMP seconds.
Gerd Moellmann's avatar
Gerd Moellmann committed
100 101 102 103 104

   Value is a pointer to the atimer started.  It can be used in calls
   to cancel_atimer; don't free it yourself.  */

struct atimer *
105 106
start_atimer (enum atimer_type type, struct timespec timestamp,
	      atimer_callback fn, void *client_data)
Gerd Moellmann's avatar
Gerd Moellmann committed
107 108
{
  struct atimer *t;
109
  sigset_t oldset;
Gerd Moellmann's avatar
Gerd Moellmann committed
110

111 112
  /* Round TIMESTAMP up to the next full second if we don't have itimers.  */
#ifndef HAVE_SETITIMER
113 114
  if (timestamp.tv_nsec != 0 && timestamp.tv_sec < TYPE_MAXIMUM (time_t))
    timestamp = make_timespec (timestamp.tv_sec + 1, 0);
Gerd Moellmann's avatar
Gerd Moellmann committed
115 116 117 118 119 120 121 122 123 124
#endif /* not HAVE_SETITIMER */

  /* Get an atimer structure from the free-list, or allocate
     a new one.  */
  if (free_atimers)
    {
      t = free_atimers;
      free_atimers = t->next;
    }
  else
Dmitry Antipov's avatar
Dmitry Antipov committed
125
    t = xmalloc (sizeof *t);
Gerd Moellmann's avatar
Gerd Moellmann committed
126 127

  /* Fill the atimer structure.  */
128
  memset (t, 0, sizeof *t);
Gerd Moellmann's avatar
Gerd Moellmann committed
129 130 131 132
  t->type = type;
  t->fn = fn;
  t->client_data = client_data;

133
  block_atimers (&oldset);
Gerd Moellmann's avatar
Gerd Moellmann committed
134 135 136 137 138

  /* Compute the timer's expiration time.  */
  switch (type)
    {
    case ATIMER_ABSOLUTE:
139
      t->expiration = timestamp;
Gerd Moellmann's avatar
Gerd Moellmann committed
140
      break;
141

Gerd Moellmann's avatar
Gerd Moellmann committed
142
    case ATIMER_RELATIVE:
143
      t->expiration = timespec_add (current_timespec (), timestamp);
Gerd Moellmann's avatar
Gerd Moellmann committed
144
      break;
145

Gerd Moellmann's avatar
Gerd Moellmann committed
146
    case ATIMER_CONTINUOUS:
147
      t->expiration = timespec_add (current_timespec (), timestamp);
148
      t->interval = timestamp;
Gerd Moellmann's avatar
Gerd Moellmann committed
149 150 151 152 153
      break;
    }

  /* Insert the timer in the list of active atimers.  */
  schedule_atimer (t);
154
  unblock_atimers (&oldset);
Gerd Moellmann's avatar
Gerd Moellmann committed
155 156 157

  /* Arrange for a SIGALRM at the time the next atimer is ripe.  */
  set_alarm ();
158

Gerd Moellmann's avatar
Gerd Moellmann committed
159 160 161 162 163 164 165
  return t;
}


/* Cancel and free atimer TIMER.  */

void
166
cancel_atimer (struct atimer *timer)
Gerd Moellmann's avatar
Gerd Moellmann committed
167
{
168
  int i;
169
  sigset_t oldset;
170

171
  block_atimers (&oldset);
Gerd Moellmann's avatar
Gerd Moellmann committed
172

173
  for (i = 0; i < 2; ++i)
174
    {
175 176
      struct atimer *t, *prev;
      struct atimer **list = i ? &stopped_atimers : &atimers;
177

178
      /* See if TIMER is active or stopped.  */
179
      for (t = *list, prev = NULL; t && t != timer; prev = t, t = t->next)
180 181
	;

Juanma Barranquero's avatar
Juanma Barranquero committed
182 183 184
      /* If it is, take it off its list, and put in on the free-list.
	 We don't bother to arrange for setting a different alarm time,
	 since a too early one doesn't hurt.  */
185 186 187 188 189 190
      if (t)
	{
	  if (prev)
	    prev->next = t->next;
	  else
	    *list = t->next;
191

192 193
	  t->next = free_atimers;
	  free_atimers = t;
194
	  break;
195
	}
Gerd Moellmann's avatar
Gerd Moellmann committed
196 197
    }

198
  unblock_atimers (&oldset);
Gerd Moellmann's avatar
Gerd Moellmann committed
199 200 201
}


202
/* Append two lists of atimers LIST_1 and LIST_2 and return the
203 204 205
   result list.  */

static struct atimer *
206
append_atimer_lists (struct atimer *list_1, struct atimer *list_2)
207
{
208 209 210 211
  if (list_1 == NULL)
    return list_2;
  else if (list_2 == NULL)
    return list_1;
212 213 214
  else
    {
      struct atimer *p;
215

216
      for (p = list_1; p->next; p = p->next)
217
	;
218 219
      p->next = list_2;
      return list_1;
220 221 222 223 224
    }
}


/* Stop all timers except timer T.  T null means stop all timers.  */
225 226

void
227
stop_other_atimers (struct atimer *t)
228
{
229 230
  sigset_t oldset;
  block_atimers (&oldset);
231

232 233
  if (t)
    {
234
      struct atimer *p, *prev;
235

236
      /* See if T is active.  */
237
      for (p = atimers, prev = NULL; p && p != t; prev = p, p = p->next)
238 239 240 241 242 243 244 245 246 247 248 249 250
	;

      if (p == t)
	{
	  if (prev)
	    prev->next = t->next;
	  else
	    atimers = t->next;
	  t->next = NULL;
	}
      else
	/* T is not active.  Let's handle this like T == 0.  */
	t = NULL;
251
    }
252

253
  stopped_atimers = append_atimer_lists (atimers, stopped_atimers);
254
  atimers = t;
255
  unblock_atimers (&oldset);
256 257 258 259 260 261
}


/* Run all timers again, if some have been stopped with a call to
   stop_other_atimers.  */

262
void
263
run_all_atimers (void)
264 265 266 267
{
  if (stopped_atimers)
    {
      struct atimer *t = atimers;
268
      struct atimer *next;
269
      sigset_t oldset;
270

271
      block_atimers (&oldset);
272 273
      atimers = stopped_atimers;
      stopped_atimers = NULL;
274

275 276 277 278 279 280
      while (t)
	{
	  next = t->next;
	  schedule_atimer (t);
	  t = next;
	}
281

282
      unblock_atimers (&oldset);
283 284 285 286
    }
}


Gerd Moellmann's avatar
Gerd Moellmann committed
287 288 289
/* Arrange for a SIGALRM to arrive when the next timer is ripe.  */

static void
290
set_alarm (void)
Gerd Moellmann's avatar
Gerd Moellmann committed
291 292 293 294 295 296
{
  if (atimers)
    {
#ifdef HAVE_SETITIMER
      struct itimerval it;
#endif
297
      struct timespec now, interval;
Gerd Moellmann's avatar
Gerd Moellmann committed
298

299 300
#ifdef HAVE_ITIMERSPEC
      if (0 <= timerfd || alarm_timer_ok)
301 302 303 304
	{
	  struct itimerspec ispec;
	  ispec.it_value = atimers->expiration;
	  ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0;
305 306
# ifdef HAVE_TIMERFD
	  if (timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0)
307 308
	    {
	      add_timer_wait_descriptor (timerfd);
309
	      return;
310
	    }
311 312 313
# endif
	  if (alarm_timer_ok
	      && timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0) == 0)
314 315
	    return;
	}
316
#endif
Gerd Moellmann's avatar
Gerd Moellmann committed
317

318 319
      /* Determine interval till the next timer is ripe.
	 Don't set the interval to 0; this disables the timer.  */
320 321 322 323
      now = current_timespec ();
      interval = (timespec_cmp (atimers->expiration, now) <= 0
		  ? make_timespec (0, 1000 * 1000)
		  : timespec_sub (atimers->expiration, now));
324 325

#ifdef HAVE_SETITIMER
326

327
      memset (&it, 0, sizeof it);
328
      it.it_value = make_timeval (interval);
Gerd Moellmann's avatar
Gerd Moellmann committed
329 330
      setitimer (ITIMER_REAL, &it, 0);
#else /* not HAVE_SETITIMER */
331
      alarm (max (interval.tv_sec, 1));
Gerd Moellmann's avatar
Gerd Moellmann committed
332 333 334 335 336 337 338 339 340 341
#endif /* not HAVE_SETITIMER */
    }
}


/* Insert timer T into the list of active atimers `atimers', keeping
   the list sorted by expiration time.  T must not be in this list
   already.  */

static void
342
schedule_atimer (struct atimer *t)
Gerd Moellmann's avatar
Gerd Moellmann committed
343 344 345 346
{
  struct atimer *a = atimers, *prev = NULL;

  /* Look for the first atimer that is ripe after T.  */
347
  while (a && timespec_cmp (a->expiration, t->expiration) < 0)
Gerd Moellmann's avatar
Gerd Moellmann committed
348 349 350 351 352 353 354
    prev = a, a = a->next;

  /* Insert T in front of the atimer found, if any.  */
  if (prev)
    prev->next = t;
  else
    atimers = t;
355

Gerd Moellmann's avatar
Gerd Moellmann committed
356 357 358
  t->next = a;
}

359
static void
360
run_timers (void)
Gerd Moellmann's avatar
Gerd Moellmann committed
361
{
362
  struct timespec now = current_timespec ();
363

364
  while (atimers && timespec_cmp (atimers->expiration, now) <= 0)
Gerd Moellmann's avatar
Gerd Moellmann committed
365
    {
366
      struct atimer *t = atimers;
Gerd Moellmann's avatar
Gerd Moellmann committed
367 368
      atimers = atimers->next;
      t->fn (t);
369

Gerd Moellmann's avatar
Gerd Moellmann committed
370 371
      if (t->type == ATIMER_CONTINUOUS)
	{
372
	  t->expiration = timespec_add (now, t->interval);
Gerd Moellmann's avatar
Gerd Moellmann committed
373 374 375 376 377 378 379 380
	  schedule_atimer (t);
	}
      else
	{
	  t->next = free_atimers;
	  free_atimers = t;
	}
    }
381

382
  set_alarm ();
Gerd Moellmann's avatar
Gerd Moellmann committed
383 384 385
}


386 387 388
/* Signal handler for SIGALRM.  SIGNO is the signal number, i.e.
   SIGALRM.  */

389 390
static void
handle_alarm_signal (int sig)
391
{
392
  pending_signals = 1;
393 394
}

395 396
#ifdef HAVE_TIMERFD

397 398 399
/* Called from wait_reading_process_output when FD, which
   should be equal to TIMERFD, is available for reading.  */

400 401 402
void
timerfd_callback (int fd, void *arg)
{
403
  ptrdiff_t nbytes;
404
  uint64_t expirations;
405 406

  eassert (fd == timerfd);
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
  nbytes = emacs_read (fd, &expirations, sizeof (expirations));

  if (nbytes == sizeof (expirations))
    {
      /* Timer should expire just once.  */
      eassert (expirations == 1);
      do_pending_atimers ();
    }
  else if (nbytes < 0)
    /* For some not yet known reason, we may get weird event and no
       data on timer descriptor.  This can break Gnus at least, see:
       http://lists.gnu.org/archive/html/emacs-devel/2014-07/msg00503.html.  */
    eassert (errno == EAGAIN);
  else
    /* I don't know what else can happen with this descriptor.  */
    emacs_abort ();
423 424 425
}

#endif /* HAVE_TIMERFD */
426

427
/* Do pending timers.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
428 429

void
430
do_pending_atimers (void)
Gerd Moellmann's avatar
Gerd Moellmann committed
431
{
432
  if (atimers)
Gerd Moellmann's avatar
Gerd Moellmann committed
433
    {
434 435
      sigset_t oldset;
      block_atimers (&oldset);
436
      run_timers ();
437
      unblock_atimers (&oldset);
Gerd Moellmann's avatar
Gerd Moellmann committed
438 439 440 441 442 443 444 445
    }
}


/* Turn alarms on/off.  This seems to be temporarily necessary on
   some systems like HPUX (see process.c).  */

void
446
turn_on_atimers (bool on)
Gerd Moellmann's avatar
Gerd Moellmann committed
447 448
{
  if (on)
449
    set_alarm ();
Gerd Moellmann's avatar
Gerd Moellmann committed
450
  else
451
    {
452 453 454 455 456 457 458 459 460
#ifdef HAVE_ITIMERSPEC
      struct itimerspec ispec;
      memset (&ispec, 0, sizeof ispec);
      if (alarm_timer_ok)
	timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0);
# ifdef HAVE_TIMERFD
      timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0);
# endif
#endif
461 462
      alarm (0);
    }
Gerd Moellmann's avatar
Gerd Moellmann committed
463 464
}

465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
/* This is intended to use from automated tests.  */

#ifdef ENABLE_CHECKING

#define MAXTIMERS 10

struct atimer_result
{
  /* Time when we expect this timer to trigger.  */
  struct timespec expected;

  /* Timer status: -1 if not triggered, 0 if triggered
     too early or too late, 1 if triggered timely.  */
  int intime;
};

static void
debug_timer_callback (struct atimer *t)
{
  struct timespec now = current_timespec ();
  struct atimer_result *r = (struct atimer_result *) t->client_data;
  int result = timespec_cmp (now, r->expected);

  if (result < 0)
    /* Too early.  */
    r->intime = 0;
  else if (result >= 0)
    {
493
#ifdef HAVE_SETITIMER
494
      struct timespec delta = timespec_sub (now, r->expected);
495
      /* Too late if later than expected + 0.02s.  FIXME:
496
	 this should depend from system clock resolution.  */
497
      if (timespec_cmp (delta, make_timespec (0, 20000000)) > 0)
498 499
	r->intime = 0;
      else
500
#endif /* HAVE_SETITIMER */
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
	r->intime = 1;
    }
}

DEFUN ("debug-timer-check", Fdebug_timer_check, Sdebug_timer_check, 0, 0, 0,
       doc: /* Run internal self-tests to check timers subsystem.
Return t if all self-tests are passed, nil otherwise.  */)
  (void)
{
  int i, ok;
  struct atimer *timer;
  struct atimer_result *results[MAXTIMERS];
  struct timespec t = make_timespec (0, 0);

  /* Arm MAXTIMERS relative timers to trigger with 0.1s intervals.  */
  for (i = 0; i < MAXTIMERS; i++)
    {
      results[i] = xmalloc (sizeof (struct atimer_result));
      t = timespec_add (t, make_timespec (0, 100000000));
      results[i]->expected = timespec_add (current_timespec (), t);
      results[i]->intime = -1;
      timer = start_atimer (ATIMER_RELATIVE, t,
			    debug_timer_callback, results[i]);
    }

526
#ifdef HAVE_TIMERFD
527 528
  /* Wait for 1s but process timers.  */
  wait_reading_process_output (1, 0, 0, false, Qnil, NULL, 0);
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
#else
  /* If timerfd is not supported, wait_reading_process_output won't
     pay attention to timers that expired, and the callbacks won't be
     called.  So we need to run the expired timers' callbacks by
     hand.  */
  /* Wait 1.2 sec for the timers to expire.  */
  struct timespec tend =
    timespec_add (current_timespec (), make_timespec (1, 200000000));

  while (timespec_cmp (current_timespec (), tend) < 0)
    {
      /* Wait for 5 msec between iterations.  */
      wait_reading_process_output (0, 5000000, 0, false, Qnil, NULL, 0);
      if (pending_signals)
	do_pending_atimers ();
    }
#endif
546 547 548 549 550 551 552 553 554 555
  /* Shut up the compiler by "using" this variable.  */
  (void) timer;

  for (i = 0, ok = 0; i < MAXTIMERS; i++)
    ok += results[i]->intime, xfree (results[i]);

  return ok == MAXTIMERS ? Qt : Qnil;
}

#endif /* ENABLE_CHECKING */
Gerd Moellmann's avatar
Gerd Moellmann committed
556 557

void
558
init_atimer (void)
Gerd Moellmann's avatar
Gerd Moellmann committed
559
{
560 561
#ifdef HAVE_ITIMERSPEC
# ifdef HAVE_TIMERFD
562 563 564
  /* Until this feature is considered stable, you can ask to not use it.  */
  timerfd = (egetenv ("EMACS_IGNORE_TIMERFD") ? -1 :
	     timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC));
565 566 567 568 569 570 571 572 573 574 575
# 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;
    }
#endif
576
  free_atimers = stopped_atimers = atimers = NULL;
577 578 579

  /* pending_signals is initialized in init_keyboard.  */
  struct sigaction action;
580
  emacs_sigaction_init (&action, handle_alarm_signal);
Paul Eggert's avatar
Paul Eggert committed
581
  sigaction (SIGALRM, &action, 0);
582 583 584

#ifdef ENABLE_CHECKING
  defsubr (&Sdebug_timer_check);
585
#endif
Gerd Moellmann's avatar
Gerd Moellmann committed
586
}