home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD1.img
/
d2xx
/
d240
/
memlib
/
mwcontrol.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-08-28
|
9KB
|
359 lines
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* |_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];
}
}