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

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