home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / C / SASC6571.LZX / source / sprofutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-24  |  4.4 KB  |  207 lines

  1. #include <exec/types.h>
  2. #include <exec/memory.h>
  3. #include <time.h>
  4. #include <limits.h>
  5. #include <proto/exec.h>
  6. #include <proto/timer.h>
  7. #include <proto/dos.h>
  8. #include <string.h>
  9. #include <dos.h>
  10.  
  11. #include "sprofpriv.h"
  12.  
  13. #include "constructor.h"
  14.  
  15. #define TimerBase MyTimerBase
  16.  
  17. static struct Library *TimerBase;
  18. static struct MsgPort *SprofPort;
  19. static struct timerequest TimerIO;
  20. static struct EClockVal baseline;
  21. static long E_Freq;
  22. static struct MsgPort *replyport;
  23. static struct Task *process;
  24. static int nummsgout;
  25. static struct EClockVal t0;
  26. static unsigned long overhead;
  27.  
  28.  
  29. static int SendMsg(ULONG clkval, char *id, ULONG flags);
  30. static long TimeStamp(void);
  31. static void TimeRestart(void);
  32.  
  33. /* This is an autotermination function that will run when the program exits. */
  34. /* it cleans up the externs that the profiling code uses.                    */
  35. PROFILE_DESTRUCTOR(Sprof)
  36. {
  37.    SPM msg;
  38.    static int skipme;
  39.    FUNCENTRY
  40.  
  41.    if(skipme) return;
  42.  
  43.    skipme = 1;  // Already called, skip it
  44.  
  45.    if(TimerBase)
  46.    {
  47.       CloseDevice((struct IORequest *)&TimerIO);
  48.       TimerBase = NULL;
  49.    }
  50.  
  51.    if(SprofPort && replyport)
  52.       SendMsg(0, 0, SPROF_TERM);
  53.  
  54.    SprofPort = NULL;
  55.  
  56.    if(replyport)
  57.    {
  58.       while(nummsgout > 0)
  59.       {
  60.          while(!(msg=(SPM)GetMsg(replyport)))
  61.             WaitPort(replyport);
  62.          nummsgout--;
  63.          //BUG(("Freed msg 0x%08lx, new nummsgout=%d\n", msg, nummsgout));
  64.          FreeMem(msg, SIZSPM);
  65.       }
  66.       DeletePort(replyport);
  67.       replyport = NULL;
  68.    }
  69. }
  70.  
  71. /* This is an autoinitialization function that runs before the program starts. */
  72. /* It checks to see if we will be profiling this time around and, if so, sets  */
  73. /* up the global variables that will be required.                              */
  74. PROFILE_CONSTRUCTOR(Sprof)
  75. {
  76.    SPM msg;
  77.    FUNCENTRY
  78.  
  79.    if(!(SprofPort = FindPort(SPROFPORT)))
  80.       return 0;
  81.  
  82.    memset(&TimerIO, 0, sizeof(TimerIO));
  83.  
  84.    if(OpenDevice(TIMERNAME, UNIT_ECLOCK, (struct IORequest *)&TimerIO, 37L))
  85.       return(0);
  86.  
  87.    TimerBase = (struct Library *)TimerIO.tr_node.io_Device;
  88.  
  89.    if(!(replyport = CreatePort(0L, 0L)))
  90.    {
  91.       PROFILE_DESTRUCTOR_NAME(Sprof)();  // Does the necessary cleanup
  92.       return -1;
  93.    }
  94.  
  95.    process = FindTask(NULL);
  96.  
  97.    Forbid();
  98.    if(!(SprofPort = FindPort(SPROFPORT)))
  99.    {
  100.       Permit();
  101.       PROFILE_DESTRUCTOR_NAME(Sprof)();
  102.       return 0;  // OK to run with no profiler
  103.    }
  104.  
  105.    SendMsg(0, 0, SPROF_INIT);  // "Here we are!"
  106.  
  107.    Permit();
  108.  
  109.    while(!(msg = (SPM)GetMsg(replyport))) WaitPort(replyport);
  110.  
  111.    PutMsg(replyport, (struct Message *)msg);  // So we can reuse it later
  112.  
  113.    if(msg->flags == SPROF_DENIED || msg->flags == SPROF_TERM) // He doesn't want us
  114.       PROFILE_DESTRUCTOR_NAME(Sprof)();
  115.  
  116.    /* These needs to go towards the end so the profiler startup */
  117.    /* overhead doesn't count                                    */
  118.    E_Freq = ReadEClock(&baseline) / 1000;
  119.  
  120.    return 0;
  121. }
  122.  
  123.  
  124. static long TimeStamp(void)
  125. {
  126.    ReadEClock(&t0);
  127.  
  128.    /* For now, only use low four bytes. */
  129.    return (long)(t0.ev_lo - baseline.ev_lo - overhead)/E_Freq;
  130. }
  131.  
  132. static void TimeRestart(void)
  133. {
  134.    struct EClockVal t;
  135.  
  136.    ReadEClock(&t);
  137.  
  138.    overhead += (t.ev_lo - t0.ev_lo);
  139. }
  140.  
  141. void __asm _PROLOG(register __a0 char *id)
  142. {
  143.    long t1;
  144.    if(!SprofPort) return;
  145.    t1 = TimeStamp();
  146.    if(!SendMsg(t1, id, SPROF_ENTRY))
  147.       TimeRestart();
  148. }
  149.  
  150. void __asm _EPILOG(register __a0 char *id)
  151. {
  152.    long ts;
  153.    if(!SprofPort) return;
  154.    ts = TimeStamp();
  155.    if(!SendMsg(ts, id, SPROF_EXIT))
  156.       TimeRestart();
  157. }
  158.  
  159. static int SendMsg(ULONG clkval, char *id, ULONG flags)
  160. {
  161.    SPM msg;
  162.  
  163.    if(!(msg = (SPM)GetMsg(replyport)))
  164.    {
  165.       if(!(msg = (SPM)AllocMem(SIZSPM, MEMF_CLEAR)))
  166.       {
  167.          PROFILE_DESTRUCTOR_NAME(Sprof)();
  168.          return -1;
  169.       }
  170.       msg->m.mn_ReplyPort = replyport;
  171.       msg->process = (ULONG)process;
  172.       nummsgout++;
  173.       //BUG(("New msg = 0x%08lx\n", msg));
  174.    }
  175.    else
  176.    {
  177.       if(flags != SPROF_TERM && msg->flags == SPROF_TERM)
  178.       {
  179.          PutMsg(replyport, (struct Message *)msg);  // So it gets freed
  180.          PROFILE_DESTRUCTOR_NAME(Sprof)();
  181.          return -1;
  182.       }
  183.    }
  184.  
  185.    msg->clk = clkval;
  186.    msg->id = id;
  187.    msg->a7 = getreg(REG_A7);
  188.    msg->flags = flags;
  189.    PutMsg(SprofPort, (struct Message *)msg);
  190.    WaitPort(replyport);
  191.    return 0;
  192. }
  193. #if DODEBUG
  194. void bug(char *fmt, ...)
  195. {
  196.    va_list arg;
  197.    char buf[512];
  198.  
  199.    va_start(arg,fmt);
  200.    vsprintf(buf, fmt, arg);
  201.    va_end(arg);
  202.  
  203.    Write(Output(), buf, strlen(buf));
  204. }
  205. #endif
  206.  
  207.