home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / mint / mint095s / timeout.c < prev    next >
C/C++ Source or Header  |  1993-08-03  |  5KB  |  237 lines

  1. /*
  2. Copyright 1990,1991 Eric R. Smith. All rights reserved.
  3. */
  4.  
  5. #include "mint.h"
  6.  
  7. /*
  8.  * We initialize proc_clock to a very large value so that we don't have
  9.  * to worry about unexpected process switches while starting up
  10.  */
  11.  
  12. short proc_clock = 0x7fff;
  13.  
  14. /* used by filesystems for time/date stamps; updated once per second */
  15. short timestamp, datestamp;
  16.  
  17. extern short in_kernel;    /* in main.c */
  18.  
  19. static void unnapme P_((PROC *));
  20.  
  21. /*
  22.  * addtimeout(long delta, void (*func)()): schedule a timeout for the current
  23.  * process, to take place in "delta" milliseconds. "func" specifies a
  24.  * function to be called at that time; the function is passed as a parameter
  25.  * the process for which the timeout was specified (i.e. the value of
  26.  * curproc at the time addtimeout() was called; note that this is probably
  27.  * *not* the current process when the timeout occurs).
  28.  */
  29.  
  30. TIMEOUT *tlist;
  31.  
  32. #define newtimeout() (TIMEOUT *)kmalloc(SIZEOF(TIMEOUT))
  33. #define disposetimeout(t) kfree(t)
  34.  
  35. TIMEOUT *
  36. addtimeout(delta, func)
  37.     long delta;
  38.     void (*func) P_((PROC *));
  39. {
  40.     TIMEOUT *t, **prev, *cur;
  41.  
  42.     t = newtimeout();
  43.  
  44. /* BUG: we should have some fallback mechanism for timeouts when the
  45.    kernel memory is exhausted
  46.  */
  47.     assert(t);
  48.  
  49.     t->proc = curproc;
  50.     t->func = func;
  51.  
  52.     cur = tlist;
  53.     prev = &tlist;
  54.     while (cur) {
  55.         if (cur->when >= delta) {
  56.             cur->when -= delta;
  57.             t->next = cur;
  58.             t->when = delta;
  59.             *prev = t;
  60.             return t;
  61.         }
  62.         delta -= cur->when;
  63.         prev = &cur->next;
  64.         cur = cur->next;
  65.     }
  66.     assert(delta >= 0);
  67.     t->when = delta;
  68.     t->next = cur;
  69.     *prev = t;
  70.     return t;
  71. }
  72.  
  73. /*
  74.  * cancelalltimeouts(): cancels all pending timeouts for the current
  75.  * process
  76.  */
  77.  
  78. void
  79. cancelalltimeouts()
  80. {
  81.     TIMEOUT *cur, **prev, *old;
  82.     long delta;
  83.  
  84.     cur = tlist;
  85.     prev = &tlist;
  86.     while (cur) {
  87.         if (cur->proc == curproc) {
  88.             delta = cur->when;
  89.             old = cur;
  90.             *prev = cur = cur->next;
  91.             if (cur) cur->when += delta;
  92.             disposetimeout(old);
  93.         }
  94.         else {
  95.             prev = &cur->next;
  96.             cur = cur->next;
  97.         }
  98.     }
  99. }
  100.  
  101. /*
  102.  * Cancel a specific timeout. If the timeout isn't on the list, or isn't
  103.  * for this process, we do nothing; otherwise, we cancel the time out
  104.  * and then free the memory it used. *NOTE*: it's very possible (indeed
  105.  * likely) that "this" was already removed from the list and disposed of
  106.  * by the timeout processing routines, so it's important that we check
  107.  * for it's presence in the list and do absolutely nothing if we don't
  108.  * find it there!
  109.  */
  110.  
  111. void
  112. canceltimeout(this)
  113.     TIMEOUT *this;
  114. {
  115.     TIMEOUT *cur, **prev;
  116.  
  117.     prev = &tlist;
  118.     for (cur = tlist; cur; cur = cur->next) {
  119.         if (cur == this && cur->proc == curproc) {
  120.             *prev = cur->next;
  121.             if (cur->next) {
  122.                 cur->next->when += this->when;
  123.             }
  124.             disposetimeout(this);
  125.             break;
  126.         }
  127.         prev = &cur->next;
  128.     }
  129. }
  130.  
  131. /*
  132.  * timeout: called every 20 ms or so by GEMDOS, this routine
  133.  * is responsible for maintaining process times and such.
  134.  * it should also decrement the "proc_clock" variable, but
  135.  * should *not* take any action when it reaches 0 (the state of the
  136.  * stack is too uncertain, and time is too critical). Instead,
  137.  * a vbl routine checks periodically and if "proc_clock" is 0
  138.  * suspends the current process
  139.  */
  140.  
  141. volatile int our_clock = 1000;
  142.  
  143. void
  144. timeout()
  145. {
  146.     int ms;        /* time between ticks */
  147.  
  148.     ms = *((short *)0x442L);
  149.     if (proc_clock > 0)
  150.         proc_clock--;
  151.  
  152.     our_clock -= ms;
  153.     if (tlist) {
  154.         tlist->when -= ms;
  155.     }
  156.  
  157. #if 0
  158.     /* AKP: I moved this to traps.s */
  159.     if (in_kernel)
  160.         curproc->systime += ms;
  161.     else
  162.         curproc->usrtime += ms;
  163. #endif
  164. }
  165.  
  166. /*
  167.  * sleep() calls this routine to check on alarms and other sorts
  168.  * of time-outs on every context switch.
  169.  */
  170.  
  171. void
  172. checkalarms()
  173. {
  174.     extern long searchtime;        /* in dosdir.c */
  175.     PROC *p;
  176.     long delta;
  177.     void (*evnt) P_((PROC *));
  178.     TIMEOUT *old;
  179.  
  180. /* do the once per second things */
  181.     while (our_clock < 0) {
  182.         our_clock += 1000;
  183.         timestamp = Tgettime();
  184.         datestamp = Tgetdate();
  185.         searchtime++;
  186.         reset_priorities();
  187.     }
  188.  
  189. /* see if there are outstanding timeout requests to do */
  190.     while (tlist && ((delta = tlist->when) <= 0)) {
  191.         p = tlist->proc;
  192.         TRACE("doing timeout code for pid %d", p->pid);
  193.         evnt = tlist->func;
  194.         old = tlist;
  195.         tlist = tlist->next;
  196.         disposetimeout(old);
  197.     /* call the timeout function */
  198.         (*evnt)(p);
  199.  
  200. /* if delta < 0, it's possible that the time has come for the next timeout
  201.    to occur */
  202.         if (tlist)
  203.             tlist->when += delta;
  204.     }
  205. }
  206.  
  207. /*
  208.  * nap(n): nap for n milliseconds. Used in loops where we're waiting for
  209.  * an event. If we expect the event *very* soon, we should use yield
  210.  * instead.
  211.  * NOTE: we may not sleep for exactly n milliseconds; signals can wake
  212.  * us earlier, and the vagaries of process scheduling may cause us to
  213.  * oversleep...
  214.  */
  215.  
  216. static void
  217. unnapme(p)
  218.     PROC *p;
  219. {
  220.     if (p->wait_q == SELECT_Q && p->wait_cond == (long)&nap) {
  221.         rm_q(SELECT_Q, p);
  222.         add_q(READY_Q, p);
  223.         p->wait_cond = 0;
  224.     }
  225. }
  226.  
  227. void
  228. nap(n)
  229.     unsigned n;
  230. {
  231.     TIMEOUT *t;
  232.  
  233.     t = addtimeout((long)n, unnapme);
  234.     sleep(SELECT_Q, (long)&nap);
  235.     canceltimeout(t);
  236. }
  237.