windows-nt/Source/XPSP1/NT/sdktools/m4/mem.c
2020-09-26 16:20:57 +08:00

206 lines
4.5 KiB
C

/*****************************************************************************
*
* mem.c
*
* Low-level memory management.
*
*****************************************************************************/
#include "m4.h"
#ifdef DEBUG
AR g_arHead = { parHead, parHead };
#define cbExtra (offsetof(AR, rgb)+1)
#else
#define cbExtra 0
#endif
#ifdef DEBUG
/*****************************************************************************
*
* InsertPar
*
* Insert an arena record onto the list.
*
*****************************************************************************/
void InsertPar(PAR par)
{
par->parPrev = parHead;
par->parNext = parHead->parNext;
parHead->parNext->parPrev = par;
parHead->parNext = par;
}
/*****************************************************************************
*
* UnlinkPar
*
* Unlink an arena from the chain.
*
*****************************************************************************/
void STDCALL
UnlinkPar(PAR par)
{
Assert(par->parNext->parPrev == par);
Assert(par->parPrev->parNext == par);
par->parNext->parPrev = par->parPrev;
par->parPrev->parNext = par->parNext;
D(par->rgb[par->cb] = 0xFF);
D(par->tm = (TM)-1);
}
/*****************************************************************************
*
* InitParCb
*
* Initialize the arena fields that will be asserted later.
*
*****************************************************************************/
void STDCALL
InitParCb(PAR par, CB cb)
{
par->cb = cb;
par->rgb[cb] = 0xCC; /* Overflow at end */
par->tm = g_tmNow; /* Underflow at beginning */
}
/*****************************************************************************
*
* AssertPar
*
* Check that the arena is still okay.
*
*****************************************************************************/
void STDCALL
AssertPar(PCAR par)
{
Assert(par->rgb[par->cb] == 0xCC); /* Overflow at end */
Assert(par->tm == g_tmNow); /* Underflow at beginning */
Assert(par->parNext->parPrev == par);
Assert(par->parPrev->parNext == par);
}
/*****************************************************************************
*
* MemCheck
*
* Walk the entire list of memory arenas, making sure all is well.
*
*****************************************************************************/
void STDCALL
MemCheck(void)
{
PAR par;
for (par = parHead->parNext; par != parHead; par = par->parNext) {
AssertPar(par);
}
}
#else
#define InsertPar(par)
#define UnlinkPar(par)
#define InitParCb(par, cb)
#define MemCheck()
#endif
/*****************************************************************************
*
* FreePv
*
* Free an arbitrary hunk of memory.
*
* The incoming pointer really is the rgb of an arena.
*
*****************************************************************************/
void STDCALL
FreePv(PVOID pv)
{
MemCheck();
if (pv) {
PAR par = parPv(pv);
AssertPar(par);
UnlinkPar(par);
#ifdef DEBUG
if (par->cb >= 4) {
par->rgb[3]++; /* Kill the signature */
}
#endif
_FreePv(par);
}
MemCheck();
}
/*****************************************************************************
*
* pvAllocCb
*
* Allocate a hunk of memory.
*
* We really allocate an arena, but return the rgb.
*
* We allow allocation of zero bytes, which allocates nothing and returns
* NULL.
*
*****************************************************************************/
PVOID STDCALL
pvAllocCb(CB cb)
{
PAR par;
MemCheck();
if (cb) {
par = _pvAllocCb(cb + cbExtra);
if (par) {
InitParCb(par, cb);
InsertPar(par);
} else {
Die("out of memory");
}
MemCheck();
return &par->rgb;
} else {
return 0;
}
}
/*****************************************************************************
*
* pvReallocPvCb
*
* Change the size of a hunk of memory.
*
*****************************************************************************/
PVOID STDCALL
pvReallocPvCb(PVOID pv, CB cb)
{
MemCheck();
if (pv) {
PAR par = parPv(pv);
Assert(cb);
AssertPar(par);
UnlinkPar(par);
par = _pvReallocPvCb(par, cb + cbExtra);
if (par) {
InitParCb(par, cb);
InsertPar(par);
} else {
Die("out of memory");
}
MemCheck();
return &par->rgb;
} else {
return pvAllocCb(cb);
}
}