(linenum→info "unix/slp.c:2238")

emacs/22.1/src/atimer.c

    1: /* Asynchronous timers.
    2:    Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005,
    3:                  2006, 2007  Free Software Foundation, Inc.
    4: 
    5: This file is part of GNU Emacs.
    6: 
    7: GNU Emacs is free software; you can redistribute it and/or modify
    8: it under the terms of the GNU General Public License as published by
    9: the Free Software Foundation; either version 2, or (at your option)
   10: any later version.
   11: 
   12: GNU Emacs is distributed in the hope that it will be useful,
   13: but WITHOUT ANY WARRANTY; without even the implied warranty of
   14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15: GNU General Public License for more details.
   16: 
   17: You should have received a copy of the GNU General Public License
   18: along with GNU Emacs; see the file COPYING.  If not, write to
   19: the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   20: Boston, MA 02110-1301, USA.  */
   21: 
   22: #include <config.h>
   23: #include <signal.h>
   24: #include <stdio.h>
   25: #include <lisp.h>
   26: #include <syssignal.h>
   27: #include <systime.h>
   28: #include <blockinput.h>
   29: #include <atimer.h>
   30: 
   31: #ifdef HAVE_UNISTD_H
   32: #include <unistd.h>
   33: #endif
   34: 
   35: #ifdef HAVE_SYS_TIME_H
   36: #include <sys/time.h>
   37: #endif
   38: 
   39: /* Free-list of atimer structures.  */
   40: 
   41: static struct atimer *free_atimers;
   42: 
   43: /* List of currently not running timers due to a call to
   44:    lock_atimer.  */
   45: 
   46: static struct atimer *stopped_atimers;
   47: 
   48: /* List of active atimers, sorted by expiration time.  The timer that
   49:    will become ripe next is always at the front of this list.  */
   50: 
   51: static struct atimer *atimers;
   52: 
   53: /* Non-zero means alarm_signal_handler has found ripe timers but
   54:    interrupt_input_blocked was non-zero.  In this case, timer
   55:    functions are not called until the next UNBLOCK_INPUT because timer
   56:    functions are expected to call X, and X cannot be assumed to be
   57:    reentrant.  */
   58: 
   59: int pending_atimers;
   60: 
   61: /* Block/unblock SIGALRM.  */
   62: 
   63: #define BLOCK_ATIMERS   sigblock (sigmask (SIGALRM))
   64: #define UNBLOCK_ATIMERS sigunblock (sigmask (SIGALRM))
   65: 
   66: /* Function prototypes.  */
   67: 
   68: static void set_alarm P_ ((void));
   69: static void schedule_atimer P_ ((struct atimer *));
   70: static struct atimer *append_atimer_lists P_ ((struct atimer *,
   71:                                                struct atimer *));
   72: SIGTYPE alarm_signal_handler ();
   73: 
   74: 
   75: /* Start a new atimer of type TYPE.  TIME specifies when the timer is
   76:    ripe.  FN is the function to call when the timer fires.
   77:    CLIENT_DATA is stored in the client_data member of the atimer
   78:    structure returned and so made available to FN when it is called.
   79: 
   80:    If TYPE is ATIMER_ABSOLUTE, TIME is the absolute time at which the
   81:    timer fires.
   82: 
   83:    If TYPE is ATIMER_RELATIVE, the timer is ripe TIME s/us in the
   84:    future.
   85: 
   86:    In both cases, the timer is automatically freed after it has fired.
   87: 
   88:    If TYPE is ATIMER_CONTINUOUS, the timer fires every TIME s/us.
   89: 
   90:    Value is a pointer to the atimer started.  It can be used in calls
   91:    to cancel_atimer; don't free it yourself.  */
   92: 
   93: struct atimer *
   94: start_atimer (type, time, fn, client_data)
   95:      enum atimer_type type;
   96:      EMACS_TIME time;
   97:      atimer_callback fn;
   98:      void *client_data;
   99: {
  100:   struct atimer *t;
  101: 
  102:   /* Round TIME up to the next full second if we don't have
  103:      itimers.  */
  104: #ifndef HAVE_SETITIMER
  105:   if (EMACS_USECS (time) != 0)
  106:     {
  107:       EMACS_SET_USECS (time, 0);
  108:       EMACS_SET_SECS (time, EMACS_SECS (time) + 1);
  109:     }
  110: #endif /* not HAVE_SETITIMER */
  111: 
  112:   /* Get an atimer structure from the free-list, or allocate
  113:      a new one.  */
  114:   if (free_atimers)
  115:     {
  116:       t = free_atimers;
  117:       free_atimers = t->next;
  118:     }
  119:   else
  120:     t = (struct atimer *) xmalloc (sizeof *t);
  121: 
  122:   /* Fill the atimer structure.  */
  123:   bzero (t, sizeof *t);
  124:   t->type = type;
  125:   t->fn = fn;
  126:   t->client_data = client_data;
  127: 
  128:   BLOCK_ATIMERS;
  129: 
  130:   /* Compute the timer's expiration time.  */
  131:   switch (type)
  132:     {
  133:     case ATIMER_ABSOLUTE:
  134:       t->expiration = time;
  135:       break;
  136: 
  137:     case ATIMER_RELATIVE:
  138:       EMACS_GET_TIME (t->expiration);
  139:       EMACS_ADD_TIME (t->expiration, t->expiration, time);
  140:       break;
  141: 
  142:     case ATIMER_CONTINUOUS:
  143:       EMACS_GET_TIME (t->expiration);
  144:       EMACS_ADD_TIME (t->expiration, t->expiration, time);
  145:       t->interval = time;
  146:       break;
  147:     }
  148: 
  149:   /* Insert the timer in the list of active atimers.  */
  150:   schedule_atimer (t);
  151:   UNBLOCK_ATIMERS;
  152: 
  153:   /* Arrange for a SIGALRM at the time the next atimer is ripe.  */
  154:   set_alarm ();
  155: 
  156:   return t;
  157: }
  158: 
  159: 
  160: /* Cancel and free atimer TIMER.  */
  161: 
  162: void
  163: cancel_atimer (timer)
  164:      struct atimer *timer;
  165: {
  166:   int i;
  167: 
  168:   BLOCK_ATIMERS;
  169: 
  170:   for (i = 0; i < 2; ++i)
  171:     {
  172:       struct atimer *t, *prev;
  173:       struct atimer **list = i ? &stopped_atimers : &atimers;
  174: 
  175:       /* See if TIMER is active or stopped.  */
  176:       for (t = *list, prev = NULL; t && t != timer; prev = t, t = t->next)
  177:         ;
  178: 
  179:       /* If it is, take it off the its list, and put in on the
  180:          free-list.  We don't bother to arrange for setting a
  181:          different alarm time, since a too early one doesn't hurt.  */
  182:       if (t)
  183:         {
  184:           if (prev)
  185:             prev->next = t->next;
  186:           else
  187:             *list = t->next;
  188: 
  189:           t->next = free_atimers;
  190:           free_atimers = t;
  191:           break;
  192:         }
  193:     }
  194: 
  195:   UNBLOCK_ATIMERS;
  196: }
  197: 
  198: 
  199: /* Append two lists of atimers LIST1 and LIST2 and return the
  200:    result list.  */
  201: 
  202: static struct atimer *
  203: append_atimer_lists (list1, list2)
  204:      struct atimer *list1, *list2;
  205: {
  206:   if (list1 == NULL)
  207:     return list2;
  208:   else if (list2 == NULL)
  209:     return list1;
  210:   else
  211:     {
  212:       struct atimer *p;
  213: 
  214:       for (p = list1; p->next; p = p->next)
  215:         ;
  216:       p->next = list2;
  217:       return list1;
  218:     }
  219: }
  220: 
  221: 
  222: /* Stop all timers except timer T.  T null means stop all timers.  */
  223: 
  224: void
  225: stop_other_atimers (t)
  226:      struct atimer *t;
  227: {
  228:   BLOCK_ATIMERS;
  229: 
  230:   if (t)
  231:     {
  232:       struct atimer *p, *prev;
  233: 
  234:       /* See if T is active.  */
  235:       for (p = atimers, prev = NULL; p && p != t; prev = p, p = p->next)
  236:         ;
  237: 
  238:       if (p == t)
  239:         {
  240:           if (prev)
  241:             prev->next = t->next;
  242:           else
  243:             atimers = t->next;
  244:           t->next = NULL;
  245:         }
  246:       else
  247:         /* T is not active.  Let's handle this like T == 0.  */
  248:         t = NULL;
  249:     }
  250: 
  251:   stopped_atimers = append_atimer_lists (atimers, stopped_atimers);
  252:   atimers = t;
  253:   UNBLOCK_ATIMERS;
  254: }
  255: 
  256: 
  257: /* Run all timers again, if some have been stopped with a call to
  258:    stop_other_atimers.  */
  259: 
  260: void
  261: run_all_atimers ()
  262: {
  263:   if (stopped_atimers)
  264:     {
  265:       struct atimer *t = atimers;
  266:       struct atimer *next;
  267: 
  268:       BLOCK_ATIMERS;
  269:       atimers = stopped_atimers;
  270:       stopped_atimers = NULL;
  271: 
  272:       while (t)
  273:         {
  274:           next = t->next;
  275:           schedule_atimer (t);
  276:           t = next;
  277:         }
  278: 
  279:       UNBLOCK_ATIMERS;
  280:     }
  281: }
  282: 
  283: 
  284: /* A version of run_all_timers suitable for a record_unwind_protect.  */
  285: 
  286: Lisp_Object
  287: unwind_stop_other_atimers (dummy)
  288:      Lisp_Object dummy;
  289: {
  290:   run_all_atimers ();
  291:   return Qnil;
  292: }
  293: 
  294: 
  295: /* Arrange for a SIGALRM to arrive when the next timer is ripe.  */
  296: 
  297: static void
  298: set_alarm ()
  299: {
  300: #if defined (USG) && !defined (POSIX_SIGNALS)
  301:   /* USG systems forget handlers when they are used;
  302:      must reestablish each time.  */
  303:   signal (SIGALRM, alarm_signal_handler);
  304: #endif /* USG */
  305: 
  306:   if (atimers)
  307:     {
  308:       EMACS_TIME now, time;
  309: #ifdef HAVE_SETITIMER
  310:       struct itimerval it;
  311: #endif
  312: 
  313:       /* Determine s/us till the next timer is ripe.  */
  314:       EMACS_GET_TIME (now);
  315:       EMACS_SUB_TIME (time, atimers->expiration, now);
  316: 
  317: #ifdef HAVE_SETITIMER
  318:       /* Don't set the interval to 0; this disables the timer.  */
  319:       if (EMACS_TIME_LE (atimers->expiration, now))
  320:         {
  321:           EMACS_SET_SECS (time, 0);
  322:           EMACS_SET_USECS (time, 1000);
  323:         }
  324: 
  325:       bzero (&it, sizeof it);
  326:       it.it_value = time;
  327:       setitimer (ITIMER_REAL, &it, 0);
  328: #else /* not HAVE_SETITIMER */
  329:       alarm (max (EMACS_SECS (time), 1));
  330: #endif /* not HAVE_SETITIMER */
  331:     }
  332: }
  333: 
  334: 
  335: /* Insert timer T into the list of active atimers `atimers', keeping
  336:    the list sorted by expiration time.  T must not be in this list
  337:    already.  */
  338: 
  339: static void
  340: schedule_atimer (t)
  341:      struct atimer *t;
  342: {
  343:   struct atimer *a = atimers, *prev = NULL;
  344: 
  345:   /* Look for the first atimer that is ripe after T.  */
  346:   while (a && EMACS_TIME_GT (t->expiration, a->expiration))
  347:     prev = a, a = a->next;
  348: 
  349:   /* Insert T in front of the atimer found, if any.  */
  350:   if (prev)
  351:     prev->next = t;
  352:   else
  353:     atimers = t;
  354: 
  355:   t->next = a;
  356: }
  357: 
  358: 
  359: /* Signal handler for SIGALRM.  SIGNO is the signal number, i.e.
  360:    SIGALRM.  */
  361: 
  362: SIGTYPE
  363: alarm_signal_handler (signo)
  364:      int signo;
  365: {
  366:   EMACS_TIME now;
  367: 
  368:   SIGNAL_THREAD_CHECK (signo);
  369: 
  370:   EMACS_GET_TIME (now);
  371:   pending_atimers = 0;
  372: 
  373:   while (atimers
  374:          && (pending_atimers = interrupt_input_blocked) == 0
  375:          && EMACS_TIME_LE (atimers->expiration, now))
  376:     {
  377:       struct atimer *t;
  378: 
  379:       t = atimers;
  380:       atimers = atimers->next;
  381: #ifndef MAC_OSX
  382:       t->fn (t);
  383: #endif
  384: 
  385:       if (t->type == ATIMER_CONTINUOUS)
  386:         {
  387:           EMACS_ADD_TIME (t->expiration, now, t->interval);
  388:           schedule_atimer (t);
  389:         }
  390:       else
  391:         {
  392:           t->next = free_atimers;
  393:           free_atimers = t;
  394:         }
  395: #ifdef MAC_OSX
  396:       /* Fix for Ctrl-G.  Perhaps this should apply to all platforms. */
  397:       t->fn (t); 
  398: #endif
  399: 
  400:       EMACS_GET_TIME (now);
  401:     }
  402: 
  403:   if (! pending_atimers)
  404:     set_alarm ();
  405: }
  406: 
  407: 
  408: /* Call alarm_signal_handler for pending timers.  */
  409: 
  410: void
  411: do_pending_atimers ()
  412: {
  413:   if (pending_atimers)
  414:     {
  415:       BLOCK_ATIMERS;
  416:       alarm_signal_handler (SIGALRM);
  417:       UNBLOCK_ATIMERS;
  418:     }
  419: }
  420: 
  421: 
  422: /* Turn alarms on/off.  This seems to be temporarily necessary on
  423:    some systems like HPUX (see process.c).  */
  424: 
  425: void
  426: turn_on_atimers (on)
  427:      int on;
  428: {
  429:   if (on)
  430:     {
  431:       signal (SIGALRM, alarm_signal_handler);
  432:       set_alarm ();
  433:     }
  434:   else
  435:     alarm (0);
  436: }
  437: 
  438: 
  439: void
  440: init_atimer ()
  441: {
  442:   free_atimers = atimers = NULL;
  443:   pending_atimers = 0;
  444:   signal (SIGALRM, alarm_signal_handler);
  445: }
  446: 
  447: /* arch-tag: e6308261-eec6-404b-89fb-6e5909518d70
  448:    (do not change this comment) */
Syntax (Markdown)