home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / programming / gnuc / library / rcs / ix_timer.c,v < prev    next >
Encoding:
Text File  |  1992-08-09  |  4.9 KB  |  201 lines

  1. head    1.2;
  2. access;
  3. symbols
  4.     version39-41:1.1;
  5. locks;
  6. comment    @ *  @;
  7.  
  8.  
  9. 1.2
  10. date    92.08.09.20.56.37;    author amiga;    state Exp;
  11. branches;
  12. next    1.1;
  13.  
  14. 1.1
  15. date    92.05.14.19.55.40;    author mwild;    state Exp;
  16. branches;
  17. next    ;
  18.  
  19.  
  20. desc
  21. @timer interrupt
  22. @
  23.  
  24.  
  25. 1.2
  26. log
  27. @import sysbase
  28. @
  29. text
  30. @/*
  31.  *  This file is part of ixemul.library for the Amiga.
  32.  *  Copyright (C) 1991, 1992  Markus M. Wild
  33.  *
  34.  *  This library is free software; you can redistribute it and/or
  35.  *  modify it under the terms of the GNU Library General Public
  36.  *  License as published by the Free Software Foundation; either
  37.  *  version 2 of the License, or (at your option) any later version.
  38.  *
  39.  *  This library is distributed in the hope that it will be useful,
  40.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  41.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  42.  *  Library General Public License for more details.
  43.  *
  44.  *  You should have received a copy of the GNU Library General Public
  45.  *  License along with this library; if not, write to the Free
  46.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  47.  *
  48.  *  $Id: ix_timer.c,v 1.1 1992/05/14 19:55:40 mwild Exp $
  49.  *
  50.  *  $Log: ix_timer.c,v $
  51.  *  Revision 1.1  1992/05/14  19:55:40  mwild
  52.  *  Initial revision
  53.  *
  54.  */
  55.  
  56. #define KERNEL
  57. #include "ixemul.h"
  58.  
  59. #undef DEBUG
  60.  
  61. /*
  62.  * this is the interrupt code that distributes those itimer signals and
  63.  * collects resource information
  64.  */
  65.  
  66. /*
  67.  * For all you "moralists" out there in Amiga land...
  68.  * This code uses exec private information about how the stack frame looks
  69.  * like inside an interrupt. However, this information is used read-only, and
  70.  * it really doesn't matter whether it will be wrong in the future, in that
  71.  * case system-time will be measured in other ways, but so what ? ;-))
  72.  */
  73.  
  74. /* executing in ROM is considered "system" ... */
  75. #define is_user(pc) (pc < 0xf80000 || pc > 0xffffff)
  76. extern int _dos20;
  77. extern struct ExecBase *SysBase;
  78.  
  79. int ix_timer (char *foobar, ...) __attribute__ ((interrupt));
  80.  
  81. /*
  82.  * by specifying the function as taking varargs parameter, we force gcc
  83.  * to generate a framepointer...
  84.  */
  85.  
  86. int
  87. ix_timer (char *foobar, ...)
  88. {
  89.   register struct Task    *t_pass    asm ("a1");
  90.   struct Task        *me;
  91.   struct user        *p;
  92.   /* not necessarily "me" */
  93.   struct Task        *current_task    = SysBase->ThisTask;
  94.   u_int            current_pc;
  95.   register u_int    a5 asm ("a5");
  96.   u_int            sp;
  97.   struct itimerval    *tim;
  98.   
  99.   me = t_pass;
  100.   p = (struct user *) me->tc_TrapData;
  101.  
  102.   /* find out value of sp on invocation of this function. This is easy,
  103.    * since gcc generates a 
  104.    *   link a5,#..
  105.    * at the beginning. So we find sp with a5+4
  106.    */
  107.   sp = a5+4;
  108.  
  109.   tim = p->u_timer;
  110.  
  111.   /* The main work. Decrement the timers, and if they hit zero, generate
  112.    * the approprate signal */
  113.  
  114.   /* real timer counts in real time */
  115.   if (timerisset (&tim->it_value) && !itimerdecr (tim, ITIMER_RESOLUTION))
  116.     _psignal (me, SIGALRM);
  117.   ++tim;
  118.  
  119.   /* virtual timer only counts, when current_task == me AND the task is
  120.    * not executing in system time. To get at the current PC, remember (or learn;-))
  121.    * that the stack in an interrupt handler looks like follows:
  122.    *   0(sp)  rts into ExitIntr
  123.    *   4(sp),8(sp),12(sp),16(sp),20(sp),24(sp) -> d0/d1/a0/a1/a5/a6
  124.    *    now the stuff for the correct rte instruction
  125.    *   28(sp) -> SR
  126.    *   30(sp) -> PC <- that's what we're interested in
  127.    */
  128.   if (_dos20)
  129.     current_pc = *(u_int *)(sp + 46);    /* heuristics for 2.0.. */
  130.   else
  131.     current_pc = *(u_int *)(sp + 30);
  132.  
  133.   if ((me == current_task) && is_user (current_pc) && timerisset(&tim->it_value) &&
  134.       !itimerdecr (tim, ITIMER_RESOLUTION))
  135.     _psignal (me, SIGVTALRM);
  136.   ++tim;
  137.  
  138.   /* profiling timer, runs while this process is executing, no matter
  139.    * whether in system time or not */
  140.   if ((me == current_task) &&timerisset(&tim->it_value) &&
  141.       !itimerdecr (tim, ITIMER_RESOLUTION))
  142.     _psignal (me, SIGPROF);
  143.  
  144.   /* now that we're done with the timers, if this is our task executing,
  145.    * update it's rusage fields */
  146.   if (me == current_task)
  147.     {
  148.       struct timeval *tv;
  149.       tv = is_user (current_pc) ? &p->u_ru.ru_utime : &p->u_ru.ru_stime;
  150.       tv->tv_usec += ITIMER_RESOLUTION;
  151.       if (tv->tv_usec >= 1000000)
  152.     {
  153.       tv->tv_usec -= 1000000; /* - is much cheaper than % */
  154.       tv->tv_sec ++;
  155.     }
  156.     }
  157.  
  158.   if (p->u_prof.pr_scale)
  159.     {
  160. #ifdef DEBUG
  161.     static int counter = 0;
  162.     
  163.     if ((counter++ & 31) == 0)
  164.       {
  165.         int i;
  166.             kprintf ("$%lx ", current_pc);
  167.             for (i = 0; i < 48; i++)
  168.               if (i % 8 == 0)
  169.                 kprintf ("$%lx: $%lx ", i, *((u_int *)sp + i));
  170.               else if (i % 8 == 7)
  171.                 kprintf ("$%lx\n", *((u_int *)sp + i));
  172.           else
  173.                 kprintf ("$%lx ", *((u_int *)sp + i));
  174.             counter = 1;
  175.       }
  176. #endif
  177.  
  178.       addupc (current_pc, &p->u_prof, 1);
  179.     }
  180.  
  181.   return 0;
  182. }
  183. @
  184.  
  185.  
  186. 1.1
  187. log
  188. @Initial revision
  189. @
  190. text
  191. @d19 1
  192. a19 1
  193.  *  $Id$
  194. d21 4
  195. a24 1
  196.  *  $Log$
  197. d48 1
  198. a59 1
  199.   struct ExecBase     *SysBase    = *(void **)4;
  200. @
  201.