home *** CD-ROM | disk | FTP | other *** search
/ 17 Bit Software 3: The Continuation / 17-Bit_The_Continuation_Disc.iso / amigan / amigan 5 / memwatch / memwatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-27  |  9.8 KB  |  225 lines

  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  2. /* |_o_o|\\ Copyright (c) 1986 The Software Distillery.  All Rights Reserved */
  3. /* |. o.| || This program may not be distributed without the permission of   */
  4. /* | .  | || the authors.                                          BBS:      */
  5. /* | o  | ||   Dave Baker    Ed Burnette        Stan Chow    (919)-471-6436  */
  6. /* |  . |//    Jay Denebeim  Gordon Keener      Jack Rouse        Voice:     */
  7. /* ======      John Toebes   Mary Ellen Toebes  Doug Walker  (919)-469-4210  */ 
  8. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  9. /* This program watches the first 0x100 bytes of memory for random trashing, */
  10. /* attempts repair of the damage and then puts up an alert indicating the    */
  11. /* damage that was done.  Many thanks to EA for suggesting this program at   */
  12. /* the developer's conference.                                               */
  13. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  14.  
  15. /* * * * * * * * * INCLUDE FILES * * * * * * * * * * * */
  16. #include <exec/types.h>
  17. #include <exec/nodes.h>
  18. #include <exec/lists.h>
  19. #include <exec/memory.h>
  20. #include <exec/ports.h>
  21. #include <exec/libraries.h>
  22. #include <exec/io.h>
  23. #include <exec/tasks.h>
  24. #include <exec/execbase.h>
  25. #include <exec/devices.h>
  26. #include <devices/timer.h>
  27. #include <intuition/intuition.h>
  28. #include <libraries/dosextens.h>
  29.  
  30. /* * * * * * * * * * * STRUCTURES * * * * * * * * * * * * */
  31. typedef struct stomped
  32.    {
  33.    long data;           /* value that was thrown into address wildly */
  34.    long address;        /* address that was changed */
  35.    } STOMPED;
  36.  
  37. /* * * * * * * * * * * CONSTANTS * * * * * * * * * * * * */
  38. #define TIMEINTERVAL 2500L      /* in micro seconds */
  39. #define LOWLIMIT     20L        /* smallest safe interval */
  40. #define BANNER "\x9B0;33mMemWatch\x9B0m by John Toebes - Copyright © 1986 The Software Distillery\n 235 Trillingham Ln, Cary NC 27511   BBS:(919)-471-6436\n"
  41. #define BANNER1 "Usage: \x9B1mRUN MemWatch\x9B0m [n]\nWhere n is the optional interval between watch checks (Default 2500ms)\n"
  42.  
  43. /* * * * * * * * * * * EXTERNAL ROUTINES * * * * * * * * * */
  44. struct IntuitionBase *IntuitionBase = NULL;
  45. extern APTR             AllocMem(long, long);
  46. /* ok so I lied about these tasks - it is true as long as we are working with */
  47. /* DOS processes */
  48. extern struct Process  *FindTask(char *);
  49. extern void SetTaskPri(struct Process *, long);
  50. extern long OpenDevice(char *, long, struct IORequest*, long);
  51. extern void SaveMem();
  52. extern int ValidateMem(struct stomped *);
  53. int DOSBase;
  54.  
  55. /* * * * * * * * * * * Alert definition structure* * * * * * * * * */
  56. /* we want to display the message:                                 */
  57. /* Someone stepped on Low memory $nnnnnnnn with $nnnnnnnn cccc!    */
  58. /*         Press either Mouse button to continue                   */
  59. /* 345678901234567890123456789012345678901234567890123456789012    */
  60. /*        11111111112222222222333333333344444444445555555555666    */
  61. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  62. #define ALERTHEIGHT 25          /* height of alert in pixals */
  63. #define ADDR_OFF 34             /* location of address substitution */
  64. #define DATA_OFF 49        /* Location of data val substitution */
  65. #define CHAR_OFF 58        /* Location of data text substitution */
  66. static char AlertString[] = {
  67. 0, 84,                          /* 2 byte x absolute offset of first string */
  68. 10,                             /* 1 byte y absolute offset of first string */
  69. 'S', 'o', 'm', 'e', 'o', 'n', 'e', ' ',         /* first message string */
  70. 'S', 't', 'e', 'p', 'p', 'e', 'd', ' ',
  71. 'o', 'n', ' ', 'L', 'o', 'w', ' ',
  72. 'm', 'e', 'm', 'o', 'r', 'y', ' ',
  73. '$', 'h', 'h', 'h', 'h', 'h', 'h', 'h', 'h', ' ', /* address we substitute */
  74. 'w', 'i', 't', 'h', ' ',
  75. '$', 'h', 'h', 'h', 'h', 'h', 'h', 'h', 'h', ' ', /* data we substitute */
  76. 'c', 'c', 'c', 'c', '!',                          /* chars we substitute */
  77. 0,                                              /* null terminator on string */
  78. 1,                              /* flag to indicate another alert string */
  79. 0, 164,                         /* 2 byte x absolute offset of second string */
  80. 18,                             /* 1 byte y absolute offset of second string */
  81. 'P', 'r', 'e', 's', 's', ' ',                   /* second message string */
  82. 'e', 'i', 't', 'h', 'e', 'r', ' ',
  83. 'M', 'o', 'u', 's', 'e', ' ',
  84. 'B', 'u', 't', 't', 'o', 'n', ' ',
  85. 't', 'o', ' ', 
  86. 'c', 'o', 'n', 't', 'i', 'n', 'u', 'e',
  87. 0,                                              /* null terminator on string */
  88. 0 };                            /* flag to indicate no more strings */
  89.  
  90. /************************************************************************/
  91. /* The main program to watch the memory                                 */
  92. /************************************************************************/
  93. void _main(cmd)
  94. char *cmd;
  95.    {
  96.    register struct timerequest *timerreq = NULL;
  97.                                     /* request structure for timer waits*/
  98.    struct stomped rslt;             /* information on memory stomps */
  99.    register int i;                  /* general index variable */
  100.    register long v;                 /* temporary for formatting display */
  101.    register long interval = TIMEINTERVAL;
  102.                                     /* how long to wait between checks */
  103.    register char *p;                /* display formatting index */
  104.    /* NOTE: The declarations for i anv v MUST come before that of interval */
  105.    /* because DOIO trashes D6 and D7 which are the first ones selected for */
  106.    /* register variables.  It doesn't matter if i and v are trashed but    */
  107.    /* interval MUST be maintained across the lifetime of the loop          */
  108.  
  109.    /* if we were run from CLI then output our banner and process parameters */
  110.    if (cmd)
  111.       {
  112.       /* get our default output device */
  113.       v = Output();
  114.  
  115.       /* display our copyright */
  116.       Write(v, BANNER, sizeof(BANNER));
  117.  
  118.       /* skip over any leading spaces in the command line */
  119.       while(*cmd == ' ')
  120.          cmd++;
  121.  
  122.       /* now see if they gave us a number to control the interval of checking */
  123.       interval = 0;
  124.  
  125.       while ((*cmd >= '0') && (*cmd <= '9'))
  126.          interval = ((short)interval*(short)10) + *cmd++ - '0';
  127.  
  128.       /* if they gave us nothing (or something we didn't parse well */
  129.       /* such as a VERY large number or just plain trash, give them a */
  130.       /* short usage message for the program */
  131.       if (interval <= 0)
  132.          Write(v, BANNER1, sizeof(BANNER1));
  133.  
  134.       /* now do the magic that allows the window to be closed */
  135.       if (v != Input())
  136.          Close(Input());
  137.       Close(v);
  138.  
  139.       /* just incase we got a very low number (or a 0) from the command line */
  140.       /* apply a minimum rule to keep from killing the system performance */
  141.       /* note that since tasks switch at about every 20mili seconds or so */
  142.       /* (not sure where that information is from) making it less than 20000 */
  143.       /* really isn't much of a gain (but it sure feels nice) */
  144.       if (interval < LOWLIMIT) interval = LOWLIMIT;
  145.       }
  146.  
  147.    /* now we are ready to go - push up our priority with the best of them */
  148.    SetTaskPri( FindTask(NULL), 20);
  149.  
  150.    /* open up intuition - we only use this for the alert but we must do it */
  151.    /* anyway */
  152.    if ((IntuitionBase = (struct IntuitionBase *)
  153.                         OpenLibrary("intuition.library", 0)) == NULL)
  154.       goto abort;
  155.  
  156.    /* create a request structure to send the messages with */
  157.    if ((timerreq = (struct timerequest *)
  158.                     AllocMem(sizeof(struct timerequest),
  159.                              MEMF_CLEAR | MEMF_PUBLIC)) == NULL)
  160.       goto abort;
  161.  
  162.    /* fill in the struture with what we are dealing with */
  163.    timerreq->tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  164.    timerreq->tr_node.io_Message.mn_Node.ln_Pri = 0;
  165.    timerreq->tr_node.io_Message.mn_ReplyPort = &(FindTask(NULL)->pr_MsgPort);
  166.  
  167.    /* and open us a timer.  Note that we are using VBLANK since it is the */
  168.    /* lowest system overhead.  We are not critical on the timing and only */
  169.    /* want to run as often as possible without killing the system */
  170.    if (OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest*)timerreq, 0))
  171.       goto abort;
  172.  
  173.    /* let our assembler stub squirel away a copy of the low memory */
  174.    SaveMem();
  175.  
  176.    /* go until they hit us with a ^C - kind of a simple way to stop it */
  177.    while(!(SetSignal(0,0) & SIGBREAKF_CTRL_C))
  178.       {
  179.       /* Use the timer to wait our required number of seconds */
  180.       timerreq->tr_node.io_Command = TR_ADDREQUEST;
  181.       timerreq->tr_time.tv_secs =  0;           /* seconds */
  182.       timerreq->tr_time.tv_micro = interval;    /* micro seconds */
  183.       DoIO(timerreq);
  184.  
  185.       /* Now have our buddy check and fix any memory */
  186.       /* if something was wrong, he will tell us about it */
  187.       if (ValidateMem(&rslt))
  188.          {
  189.          /* format the failure data to be displayed */
  190.          *(long *)(&AlertString[CHAR_OFF]) = rslt.data;
  191.  
  192.          /* replace any nulls so they don't screw up the message */
  193.          for (i=CHAR_OFF; i<CHAR_OFF+4; i++)
  194.             if (!AlertString[i]) AlertString[i] = '.';
  195.  
  196.          /* format the address for them */
  197.          p = &AlertString[ADDR_OFF+7];
  198.          v = rslt.address;
  199.          for (i = 7; i>= 0; i--)
  200.             {
  201.             *p-- = "0123456789ABCDEF"[v&15];
  202.             v >>= 4;
  203.             }
  204.  
  205.          /* format the data value for them */
  206.          p = &AlertString[DATA_OFF+7];
  207.          v = rslt.data;
  208.          for (i = 7; i>= 0; i--)
  209.             {
  210.             *p-- = "0123456789ABCDEF"[v&15];
  211.             v >>= 4;
  212.             }
  213.  
  214.          /* put up a requester to indicate it failed */
  215.          DisplayAlert(0xBADC0DE, AlertString, ALERTHEIGHT);
  216.          }
  217.       }
  218.  
  219.    CloseDevice(timerreq);
  220. abort:
  221.    if (timerreq != NULL) FreeMem (timerreq, sizeof(struct timerequest));
  222.    if (IntuitionBase != NULL) CloseLibrary(IntuitionBase);
  223.    XCEXIT(-1);
  224.    }
  225.