home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Moscow ML 1.42 / src / !runtime / runtime.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-18  |  6.4 KB  |  300 lines  |  [TEXT/R*ch]

  1. /* runtime.c  */
  2.  
  3. #include "config.h"
  4.  
  5. #include "runtime.h"
  6.  
  7. #ifdef macintosh
  8.  
  9. /* 23Nov93  e */
  10. /* 16Mar94  e  -- revised to not abuse time manager (!) */
  11. /* 31Aug95  e  -- revised to abuse time manager less (!) */
  12. /* 05Sep95  e  -- added mosml required stuff: gettimeofday, e_getrusage */
  13.  
  14. /* Keeping track of time spent
  15.  - in gc
  16.  - in multifinder
  17.  - overall since startup
  18. */
  19.  
  20. #include <Timer.h>
  21. #include <stdlib.h>
  22.  
  23. #include <time.h>
  24. #include <utime.h>
  25.  
  26. #include "alloc.h"
  27. #include "fail.h"
  28. #include "memory.h"
  29. #include "debugger.h"
  30. #include "mlvalues.h"
  31. #include "freelist.h"
  32. #include "gc.h"
  33. #include "major_gc.h"
  34.  
  35. /* */
  36.  
  37. #define qRunTimes 8 /* must be at least three for: total, gc, mutlifinder */
  38.  
  39. #define aMILLION (1000000L)
  40.  
  41. #if GENERATINGPOWERPC
  42. #pragma options align=mac68k
  43. #endif
  44.  
  45. typedef struct tinfuRec
  46. {
  47.   TMTask TMTask;
  48.   short filler;
  49.   unsigned long  acc_secs;
  50.     signed long acc_usecs;
  51. } tinfuRec, *tinfuPtr;
  52.  
  53. #if GENERATINGPOWERPC
  54. #pragma options align=reset
  55. #endif
  56.  
  57. static tinfuRec gTimeInfo[qRunTimes];
  58.  
  59. #define TIMe(n) (gTimeInfo[n].TMTask)
  60.  
  61. /* 09Jan95 e */
  62.  
  63. static TimerUPP tmt_handlerUPP = NULL;
  64.  
  65. #if powerc
  66. static pascal void tmt_handler(TMTaskPtr a1)
  67. {
  68.   ((tinfuPtr )a1)->acc_secs++;
  69.   PrimeTime((QElemPtr )a1, -aMILLION);
  70. }
  71. #else
  72. #ifndef __MWERKS__
  73. static pascal void tmt_handler(void)
  74. {
  75.   asm
  76.   {
  77.     ADDQ.L #1, tinfuRec.acc_secs(a1)
  78.     MOVE.L A1, A0
  79.     MOVE.L #-aMILLION, D0
  80.     DC.W 0xA05A ; PrimeTime
  81.   }
  82. }
  83. #else
  84. asm static pascal void tmt_handler(void)
  85. {
  86.     ADDQ.L #1, 0x18(A1) // tinfuRec.acc_secs(a1)
  87.     MOVE.L A1, A0
  88.     MOVE.L #-aMILLION, D0
  89.     DC.W 0xA05A // PrimeTime
  90.     RTS
  91. }
  92. #endif
  93. #endif
  94.  
  95. static void cancel_timers(void)
  96. { int i;
  97.   for ( i = 0; i < qRunTimes; i++ )
  98.     // always! 31Aug95 e -- if (TIMe(i).tmAddr != NULL && TIMe(i).qType < 0 )
  99.     { RmvTime((QElemPtr )&TIMe(i));
  100.       TIMe(i).tmAddr = NULL;
  101.     }
  102. }
  103.  
  104. static time_t systime_init;
  105.  
  106. void init_timers(void)
  107. { int i;
  108.   if (tmt_handlerUPP == NULL) tmt_handlerUPP = NewTimerProc(tmt_handler);
  109.   for ( i = 0; i < qRunTimes; i++ )
  110.     if (TIMe(i).tmAddr == NULL)
  111.     { TIMe(i).tmAddr = tmt_handlerUPP;
  112.       // only 0, 31Aug95 e -- InsXTime((QElemPtr )&TIMe(i));
  113.       if ( i == 0 )
  114.       { _atexit(cancel_timers);
  115.         InsXTime((QElemPtr )&TIMe(0));
  116.         systime_init = time(NULL);
  117.         PrimeTime((QElemPtr )&TIMe(0), -aMILLION);
  118.       }
  119.     }
  120. }
  121.  
  122. void beg_runtime(int i)
  123. { tinfuPtr p;
  124.   if ( 0 >= i || i >= qRunTimes ) Debugger(); /* coding error */
  125.   p = &gTimeInfo[i];
  126.   p->TMTask.tmWakeUp = 0;
  127.   p->TMTask.tmReserved = 0;
  128.   InsXTime((QElemPtr )&(p->TMTask));
  129.   PrimeTime((QElemPtr )&(p->TMTask), -aMILLION);
  130. }
  131.  
  132. void acc_runtime(int i)
  133. { tinfuPtr p;
  134.   if ( 0 > i || i >= qRunTimes ) Debugger(); /* coding error */
  135.   p = &gTimeInfo[i];
  136.   RmvTime((QElemPtr )&(p->TMTask));
  137.   p->acc_usecs += aMILLION + p->TMTask.tmCount;
  138.   if (p->acc_usecs >= aMILLION)
  139.   {
  140.     p->acc_secs += 1;
  141.     p->acc_usecs -= aMILLION;
  142.   }
  143.   else if (p->acc_usecs < 0)
  144.   {
  145.     p->acc_secs -= 1;
  146.     p->acc_usecs += aMILLION;
  147.   }
  148. }
  149.  
  150. static double double_zero = (double )0;
  151.  
  152. value get_timer(value x)                          /* ML */
  153. {
  154.   unsigned int i = Long_val(x);
  155.   tinfuPtr p;
  156.  
  157.   if ( 0 > i || i >= qRunTimes) return copy_double(double_zero);
  158.   p = &gTimeInfo[i];
  159.   if (i == 0)
  160.   {
  161.     RmvTime((QElemPtr )&(p->TMTask));
  162.     p->acc_usecs = aMILLION + p->TMTask.tmCount;
  163.     InsXTime((QElemPtr )&(p->TMTask));
  164.     PrimeTime((QElemPtr )&(p->TMTask), 0);
  165.   }
  166.   return copy_double(p->acc_secs + (p->acc_usecs / (double )aMILLION));
  167. }
  168.  
  169. value beg_timer(value x)                          /* ML */
  170. {
  171.   unsigned int i = Long_val(x);
  172.  
  173.   if (i >= qRunTimes || i <= 2) return Val_false;
  174.   beg_runtime(i);
  175.   return Val_true;
  176. }
  177.  
  178. value end_timer(value x)                          /* ML */
  179. {
  180.   unsigned int i = Long_val(x);
  181.  
  182.   if (i >= qRunTimes || i <= 2) return Val_false;
  183.   acc_runtime(i);
  184.   return Val_true;
  185. }
  186.  
  187. value clr_timer(value x)                          /* ML */
  188. {
  189.   unsigned int i = Long_val(x);
  190.   tinfuPtr p;
  191.  
  192.   if (i >= qRunTimes || i <= 2) return Val_false;
  193.   p = &gTimeInfo[i];
  194.   p->acc_secs  = 0;
  195.   p->acc_usecs = 0;
  196.   return Val_true;
  197. }
  198.  
  199. /* runtime stats */
  200.  
  201. value e_getrusage( void )
  202. {
  203.   tinfuPtr p;
  204.   unsigned long rts, sts, gts, uts;
  205.            long rtu, stu, gtu, utu;
  206.   value res = alloc (6, 0);
  207.   /* snapshot run timer */
  208.   p = &gTimeInfo[0];
  209.   RmvTime((QElemPtr )&(p->TMTask));
  210.   rts = p->acc_secs;            // elapsed time
  211.   rtu = p->acc_usecs + aMILLION + p->TMTask.tmCount;
  212.   InsXTime((QElemPtr )&(p->TMTask));
  213.   PrimeTime((QElemPtr )&(p->TMTask), 0);
  214.   /* compute "user" time */
  215.   gts = gTimeInfo[1].acc_secs;  // gc time
  216.   gtu = gTimeInfo[1].acc_usecs;
  217.   sts = gTimeInfo[2].acc_secs;  // multifinder time
  218.   stu = gTimeInfo[2].acc_usecs;
  219.   uts = (rts - sts) - gts;
  220.   utu = (rtu - stu) - gtu;
  221.   while (utu < 0)         { utu += aMILLION; uts -= 1; }
  222.   while (utu >= aMILLION) { utu -= aMILLION; uts += 1; }
  223.   /* pathological case at startup really fries mosml... */
  224.   if (uts > 0x3FFFFFFF)
  225.   {
  226.     uts = 0;
  227.     utu = 1;
  228.   }
  229.   /* fill in SML record */
  230.   Field (res, 0) = Val_long (gts);  // "gc"
  231.   Field (res, 1) = Val_long (gtu);
  232.   Field (res, 2) = Val_long (sts);  // "system"
  233.   Field (res, 3) = Val_long (stu);
  234.   Field (res, 4) = Val_long (uts);  // "user"
  235.   Field (res, 5) = Val_long (utu);
  236.   return res;
  237. }
  238.  
  239. /* end of MacOS specific code */
  240.  
  241. #else
  242.  
  243. /* DOS, Unix */
  244.  
  245. #include <sys/times.h>    
  246. #include <sys/time.h>
  247. #include <sys/resource.h>
  248. #include <unistd.h>   
  249.  
  250. struct mosml_timeval gc_time = { (long) 0, (long) 0 };
  251.  
  252. void beg_gc_time(void)
  253. {
  254. #if defined(hpux) || defined(__svr4__)
  255.   struct tms buffer;
  256.  
  257.   long persec = sysconf(_SC_CLK_TCK);
  258.   times(&buffer);
  259.   gc_time.tv_sec  -= buffer.tms_utime / persec;
  260.   gc_time.tv_usec -= (buffer.tms_utime % persec) * (1000000 / persec);
  261. #else
  262.   struct rusage rusages;
  263.  
  264.   getrusage(RUSAGE_SELF, &rusages);
  265.   gc_time.tv_sec  -= rusages.ru_utime.tv_sec;
  266.   gc_time.tv_usec -= rusages.ru_utime.tv_usec;
  267. #endif
  268.  
  269.   if (gc_time.tv_usec < 0) {
  270.     gc_time.tv_usec += 1000000;
  271.     gc_time.tv_sec  -= 1;
  272.   }
  273. }
  274.  
  275. void end_gc_time(void)
  276. {
  277. #if defined(hpux) || defined(__svr4__)
  278.   struct tms buffer;
  279.  
  280.   long persec = sysconf(_SC_CLK_TCK);
  281.   times(&buffer);
  282.   gc_time.tv_sec  += buffer.tms_utime / persec;
  283.   gc_time.tv_usec += (buffer.tms_utime % persec) * (1000000 / persec);
  284. #else
  285.   struct rusage rusages;
  286.  
  287.   getrusage(RUSAGE_SELF, &rusages);
  288.   gc_time.tv_sec  += rusages.ru_utime.tv_sec;
  289.   gc_time.tv_usec += rusages.ru_utime.tv_usec;
  290. #endif
  291.  
  292.   if (gc_time.tv_usec >= 1000000) {
  293.     gc_time.tv_usec -= 1000000;
  294.     gc_time.tv_sec  += 1;
  295.   }
  296.  
  297. }
  298.  
  299. #endif
  300.