home *** CD-ROM | disk | FTP | other *** search
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * |_o_o|\\ Copyright (c) 1989 The Software Distillery. *
- * |. o.| || All Rights Reserved *
- * | . | || Written by Doug Walker *
- * | o | || The Software Distillery *
- * | . |// 235 Trillingham Lane *
- * ====== Cary, NC 27513 *
- * BBS:(919)-471-6436 *
- \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
- /* This file contains the routines that must be linked in to every pgm */
- /* that wants to use MemWatchIII - MWInit, MWTerm, MWCheck, MWSend, */
- /* MWHold, MWPurge, MWSend */
-
- #include "mempriv.h"
-
- struct MWGlobal mwg = {0L}; /* Make sure the 'flags' field is 0's */
-
- /* Initialization routine - should be called once before any memory */
- /* is allocated */
-
- void MWInit(dbfh, flags)
- BPTR dbfh;
- LONG flags;
- {
- if(mwg.flags & MWF_ACTIVE)
- {
- if(!dbfh && mwg.dbfh) dbfh = mwg.dbfh;
- if(dbfh)
- {
- MSG(dbfh, "MemWatch ERROR: MWInit called twice\n");
- }
-
- return;
- }
-
- memset((char *)&mwg, 0, sizeof(struct MWGlobal));
-
- mwg.flags = flags|MWF_ACTIVE;
-
- if(!(flags & MWF_NOLOG)) mwg.dbfh = (dbfh ? dbfh : Output());
-
- MWSend(MWM_INIT);
-
- mwg.lim[MWT_CHIP] = mwg.lim[MWT_FAST] = 0x7fffffff;
-
- mwg.task = FindTask(0L);
- }
-
- /* Termination routine - should be called after all memory usage is done */
-
- void MWTerm()
- {
- int msgdone = 0;
-
- MWCheck();
-
- MWSend(MWM_TERM);
-
- /* no need to trash the mem we may be about to free for good */
- mwg.flags |= MWF_NOFTRASH;
-
- if(!(mwg.flags & MWF_NOFREE))
- {
- while(mwg.first)
- {
- if(mwg.dbfh)
- {
- if(!msgdone)
- {
- MSG(mwg.dbfh,
- "MemWatch ERROR: The following allocations were not freed:\n");
- msgdone = 1;
- }
- MWPrint(mwg.first, 0, 0, 0);
- }
- MWFreeMem(mwg.first->memory, mwg.first->size, 0);
- }
- }
-
- MWPurge(); /* Really free all mem on the 'free' chain */
-
- memset((char *)&mwg, 0, sizeof(struct MWGlobal));
- }
-
- /* Validity check routine - checks all known allocations for overwrites */
- /* Called from every alloc and free routine, plus when specifically */
- /* invoked */
-
- void MWCheck()
- {
- struct MWAlc *mwa;
- char *tmpchar;
- int error, header, trailer;
-
- if(mwg.flags & MWF_ERROR)
- {
- /* Error already found by external process */
- if(mwg.dbfh)
- MSG(mwg.dbfh,
- "MemWatch ERROR: External process found memory error\n");
- MWHold();
- return;
- }
-
- error = 0;
- for(mwa=mwg.first; mwa; mwa=mwa->next)
- {
- if( (mwa->myflags & MWF_REPMASK) == MWF_REPORTED) continue;
-
- if(header=memcmp((char *)&mwa->header, MWHEADER, 4))
- {
- if(mwg.dbfh) MSG(mwg.dbfh, "MemWatch ERROR: Header trashed\n");
- }
-
- if(trailer=memcmp(mwa->memory+mwa->size, MWTRAILER, 4))
- {
- if(mwg.dbfh) MSG(mwg.dbfh, "MemWatch ERROR: Trailer trashed\n");
- }
-
- if(header || trailer)
- {
- error = 1;
- mwa->myflags |= MWF_REPORTED;
- MWPrint(mwa, 0, 0, 0);
- }
- }
-
- for(mwa=mwg.freed; mwa; mwa=mwa->next)
- {
- if( (mwa->myflags & MWF_REPMASK) == MWF_REPORTED) continue;
-
- for(header=0, tmpchar=mwa->memory;
- header<mwa->size;
- header++, tmpchar++)
- {
- if(*tmpchar != MWFTRASH)
- {
- mwa->myflags |= MWF_REPORTED;
- if(mwg.dbfh)
- {
- error = 1;
- MSG(mwg.dbfh, "MemWatch ERROR: Freed memory modified\n");
- MWPrint(mwa, 0, 0, 0);
- break;
- }
- }
- }
- }
-
- if(error) MWHold();
- }
-
- void MWHold()
- {
- struct MWAlc *mwa;
-
- if(mwg.flags & MWF_EXT)
- {
- if(mwg.dbfh) MSG(mwg.dbfh, "***Process Held By MemWatch***\n");
- MWSend(MWM_KILLME); /* Should never return... */
- }
- mwg.flags &= ~MWF_ERROR; /* But if it does, clear the error flag */
-
- /* If we're attempting to go on, make all the sentinals correct */
- for(mwa=mwg.first; mwa; mwa=mwa->next)
- {
- mwa->myflags = ~MWF_REPMASK;
- memcpy((char *)&mwa->header, MWHEADER, 4);
- memcpy((mwa->memory + mwa->size), MWTRAILER, 4);
- }
-
- for(mwa=mwg.freed; mwa; mwa=mwa->next)
- {
- mwa->myflags = ~MWF_REPMASK;
- memset(mwa->memory, MWFTRASH, mwa->size);
- }
- }
-
- /* MWPurge really frees all memory placed on the 'freed' chain by */
- /* FreeMem() or free() */
-
- void MWPurge()
- {
- struct MWAlc *cur, *next;
-
- for(cur=mwg.freed; cur; cur=next)
- {
- next = cur->next;
- FreeMem(cur, cur->size + sizeof(struct MWAlc));
- }
- mwg.freed = NULL;
- }
-
- /* MWSend communicates with the external MemWatch process */
-
- int MWSend(type)
- int type;
- {
- struct MsgPort *extport;
- struct MWMsg mwmsg;
-
- if(!(mwg.flags & MWF_ACTIVE) ||
- !(mwg.flags & MWF_EXT)) return(1);
-
- if(!(extport = FindPort(MWPORTNAME)) ||
- !(mwmsg.msgpart.mn_ReplyPort = CreatePort(NULL, 0)))
- goto exterror;
-
- mwmsg.msgpart.mn_Length = sizeof(struct MWMsg);
- mwmsg.type = type|MWM_REPLY;
- mwmsg.mwg = &mwg;
- PutMsg(extport, &mwmsg.msgpart);
- WaitPort(mwmsg.msgpart.mn_ReplyPort);
- GetMsg(mwmsg.msgpart.mn_ReplyPort);
- DeletePort(mwmsg.msgpart.mn_ReplyPort);
- if(mwmsg.type != MWM_OK)
- {
- goto exterror;
- }
-
- return(0);
-
- exterror:
- if(mwg.dbfh)
- MSG(mwg.dbfh,
- "MemWatch ERROR: Can't communicate with external process\n");
- mwg.flags &= ~MWF_EXT;
- return(1);
- }
-
- #define ALCMSG \
- "0x00000000 length 00000000 allocated line 00000 file xxxxxxxxxxxxxxx\n"
- /*0 1 2 3 4 5 6*/
- /*0123456789012345678901234567890123456789012345678901234567890*/
- #define ALC_MEM 2
- #define ALC_LEN 18
- #define ALC_LIN 42
- #define ALC_FIL 53
-
- #define FREMSG \
- "Invalid FreeMem call, addr 0x00000000 length 00000000\n"
- /*0 1 2 3 4 5 6*/
- /*0123456789012345678901234567890123456789012345678901234567890*/
- #define FRE_MEM 29
- #define FRE_LEN 45
-
- #define LENMSG \
- "FreeMem called with length 00000000 on the following allocation:\n"
- /*0 1 2 3 4 5 6*/
- /*0123456789012345678901234567890123456789012345678901234567890*/
- #define LEN_LEN 27
-
- #define USEMSG \
- "00000000 bytes in 00000000 allocations\n"
- /*0 1 2 3 4 5 6*/
- /*0123456789012345678901234567890123456789012345678901234567890*/
- #define USE_SIZ 0
- #define USE_ALC 18
-
- #define MAXMSG \
- "Max chip usage = 00000000 bytes; Max fast usage = 00000000 bytes\n\n"
- /*0 1 2 3 4 5 6*/
- /*0123456789012345678901234567890123456789012345678901234567890*/
- #define MAX_CHP 17
- #define MAX_FST 50
-
- #define DIGITS "0123456789ABCDEF"
-
- static void fmtdec(char *, long, LONG);
- static void fmthex(char *, LONG);
-
- static char *msgs[] =
- {
- ALCMSG, FREMSG, LENMSG, USEMSG, MAXMSG
- };
-
- void MWPrint(mwa, msgnum, val1, val2)
- struct MWAlc *mwa;
- int msgnum;
- LONG val1, val2;
- {
- char *buffer;
- int i;
-
- if(!(mwg.flags & MWF_ACTIVE) || !mwg.dbfh) return;
-
- buffer = msgs[msgnum];
-
- switch(msgnum)
- {
- case 0:
- fmthex(msgs[0]+ALC_MEM, (LONG)mwa->memory);
- fmtdec(msgs[0]+ALC_LEN, 8, mwa->size);
- fmtdec(msgs[0]+ALC_LIN, 5, mwa->line);
-
- if( (i = strlen(mwa->file)) > 15) i=15;
- memcpy(msgs[0]+ALC_FIL, mwa->file, i);
- msgs[0][ALC_FIL+i] = '\n';
- msgs[0][ALC_FIL+i+1] = '\0';
- break;
-
- case 1:
- fmthex(msgs[1]+FRE_MEM, val1);
- fmtdec(msgs[1]+FRE_LEN, 8, val2);
- break;
-
- case 2:
- fmtdec(msgs[2]+LEN_LEN, 8, val1);
- break;
-
- case 3:
- fmtdec(msgs[3]+USE_SIZ, 8, val1);
- fmtdec(msgs[3]+USE_ALC, 8, val2);
- break;
-
- case 4:
- fmtdec(msgs[4]+MAX_CHP, 8, val1);
- fmtdec(msgs[4]+MAX_FST, 8, val2);
- break;
-
- default:
- /* What do we do here? Give up, I guess*/
- return;
- }
-
- MSG(mwg.dbfh, buffer);
- }
-
- static void fmtdec(buf, len, val)
- char *buf;
- long len;
- LONG val;
- {
- int i;
- for(i=1; i<=len; i++, val/=10)
- buf[len-i] = (val ? DIGITS[val%10] : ' ');
- }
-
- static void fmthex(buf, val)
- char *buf;
- LONG val;
- {
- int i, j;
- union
- {
- LONG l;
- char c[4];
- } u;
-
- u.l = val;
- for(i=j=0; i<4; i++)
- {
- buf[j++] = DIGITS[(u.c[i]&0xf0)>>4];
- buf[j++] = DIGITS[u.c[i]&0x0f];
- }
- }
-
-