home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Moscow ML 1.31 / source code / mosml / src / !runtime / runtime.c < prev   
Encoding:
C/C++ Source or Header  |  1995-10-21  |  6.4 KB  |  299 lines  |  [TEXT/R*ch]

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