267 lines
6.4 KiB
C
267 lines
6.4 KiB
C
|
/************************************************************/
|
|||
|
/* Windows Write, Copyright 1985-1992 Microsoft Corporation */
|
|||
|
/************************************************************/
|
|||
|
|
|||
|
#define NOGDICAPMASKS
|
|||
|
#define NOVIRTUALKEYCODES
|
|||
|
#define NOWINMESSAGES
|
|||
|
#define NOWINSTYLES
|
|||
|
#define NOSYSMETRICS
|
|||
|
#define NOMENUS
|
|||
|
#define NOICON
|
|||
|
#define NOKEYSTATE
|
|||
|
#define NOSYSCOMMANDS
|
|||
|
#define NOSHOWWINDOW
|
|||
|
#define NOCTLMGR
|
|||
|
#define NOCLIPBOARD
|
|||
|
#define NOMSG
|
|||
|
#define NOGDI
|
|||
|
#define NOMB
|
|||
|
#define NOSOUND
|
|||
|
#define NOCOMM
|
|||
|
#define NOPEN
|
|||
|
#define NOBRUSH
|
|||
|
#define NOFONT
|
|||
|
#define NOWNDCLASS
|
|||
|
#include <windows.h>
|
|||
|
|
|||
|
#include "mw.h"
|
|||
|
/*
|
|||
|
HeapManage.c - several routines to manage the heap, including changing
|
|||
|
the finger table, compacting the heap in general, and checking the
|
|||
|
heap for consistency.
|
|||
|
It also contains the routines which were once in heapNew.
|
|||
|
*/
|
|||
|
#include "code.h"
|
|||
|
#include "heapDefs.h"
|
|||
|
#include "heapData.h"
|
|||
|
#define NOSTRUNDO
|
|||
|
#define NOSTRMERGE
|
|||
|
#include "str.h"
|
|||
|
#include "macro.h"
|
|||
|
#define NOUAC
|
|||
|
#include "cmddefs.h"
|
|||
|
#include "filedefs.h"
|
|||
|
#include "docdefs.h"
|
|||
|
|
|||
|
#ifdef DEBUG
|
|||
|
int cPageMinReq = 15;
|
|||
|
#else
|
|||
|
#define cPageMinReq (15)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
/* the following statics are used when growing both heap and rgbp etc. */
|
|||
|
static int cwRealRequest; /* heap is grow in blocks, this is the actual request */
|
|||
|
static int cPageIncr; /* count of page buffers to increase */
|
|||
|
static int cwRgbpIncr; /* cw in rgbp to be increment */
|
|||
|
static int cwHashIncr; /* cw in rgibpHash to be increment */
|
|||
|
static int cwBPSIncr; /* cw in mpibpbps to be increment */
|
|||
|
static int cwHeapIncr; /* cw in heap increment */
|
|||
|
|
|||
|
|
|||
|
extern CHAR (*rgbp)[cbSector];
|
|||
|
extern CHAR *rgibpHash;
|
|||
|
extern struct BPS *mpibpbps;
|
|||
|
extern int ibpMax;
|
|||
|
extern int iibpHashMax;
|
|||
|
extern int cwInitStorage;
|
|||
|
extern typeTS tsMruBps;
|
|||
|
|
|||
|
NEAR FGiveupFreeBps(unsigned, int *);
|
|||
|
NEAR FThrowPages(int);
|
|||
|
NEAR GivePages(int);
|
|||
|
NEAR CompressRgbp();
|
|||
|
|
|||
|
FTryGrow(cb)
|
|||
|
unsigned cb;
|
|||
|
{
|
|||
|
int cPage;
|
|||
|
|
|||
|
#define cPageRemain (int)(ibpMax - cPage)
|
|||
|
|
|||
|
if (FGiveupFreeBps(cb, &cPage) &&
|
|||
|
(cPageRemain >= cPageMinReq))
|
|||
|
{
|
|||
|
/* we have enough free pages to give */
|
|||
|
GivePages(cPage);
|
|||
|
}
|
|||
|
else if ((cPageRemain >= cPageMinReq) && FThrowPages(cPage))
|
|||
|
{
|
|||
|
GivePages(cPage);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NEAR FGiveupFreeBps(cb, pCPage)
|
|||
|
unsigned cb;
|
|||
|
int *pCPage;
|
|||
|
{
|
|||
|
/* Return true if we can simply give up certain free pages from rgbp to
|
|||
|
the heap. Return false if all free pages from rgbp still cannot satisfy
|
|||
|
the request
|
|||
|
In any case, pCPage contains the count of pages required */
|
|||
|
|
|||
|
register struct BPS *pbps;
|
|||
|
register int cPage = 0;
|
|||
|
int ibp;
|
|||
|
|
|||
|
#define cbTotalFreed ((cPage*cbSector)+(2*cPage*sizeof(CHAR))+(cPage*sizeof(struct BPS)))
|
|||
|
|
|||
|
for (ibp = 0, pbps = &mpibpbps[0]; ibp < ibpMax; ibp++, pbps++)
|
|||
|
{
|
|||
|
if (pbps->fn == fnNil)
|
|||
|
cPage++;
|
|||
|
}
|
|||
|
|
|||
|
if (cb > cbTotalFreed )
|
|||
|
{
|
|||
|
/* free pages are not enough, find out exactly how many
|
|||
|
pages do we need */
|
|||
|
cPage++;
|
|||
|
while (cb > cbTotalFreed)
|
|||
|
cPage++;
|
|||
|
*pCPage = cPage;
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
/* there are enough free pages to give, find out exactly how many */
|
|||
|
while (cb <= cbTotalFreed)
|
|||
|
cPage--;
|
|||
|
cPage++;
|
|||
|
*pCPage = cPage;
|
|||
|
return(TRUE);
|
|||
|
} /* end of FGiveupFreeBps */
|
|||
|
|
|||
|
|
|||
|
NEAR FThrowPages(cPage)
|
|||
|
int cPage;
|
|||
|
{
|
|||
|
int i;
|
|||
|
register struct BPS *pbps;
|
|||
|
|
|||
|
Assert(cPage > 0);
|
|||
|
|
|||
|
for (i = 0; i < cPage; i++)
|
|||
|
{
|
|||
|
pbps = &mpibpbps[IbpLru(0)];
|
|||
|
if (pbps->fn != fnNil)
|
|||
|
{
|
|||
|
if (pbps->fDirty && !FFlushFn(pbps->fn))
|
|||
|
return(FALSE);
|
|||
|
|
|||
|
/* delete references to old bps in hash table */
|
|||
|
FreeBufferPage(pbps->fn, pbps->pn);
|
|||
|
}
|
|||
|
pbps->ts = ++tsMruBps; /* so that it would not be picked up again as the LRUsed */
|
|||
|
}
|
|||
|
return(TRUE);
|
|||
|
} /* end of FThrowPages */
|
|||
|
|
|||
|
|
|||
|
NEAR GivePages(cPage)
|
|||
|
int cPage;
|
|||
|
{
|
|||
|
register struct BPS *pbpsCur = &mpibpbps[0];
|
|||
|
struct BPS *pbpsUsable = pbpsCur;
|
|||
|
int ibp;
|
|||
|
unsigned cbBps;
|
|||
|
unsigned cbRgbp;
|
|||
|
unsigned cbTotalNew;
|
|||
|
|
|||
|
for (ibp = 0; ibp < ibpMax; pbpsCur++, ibp++)
|
|||
|
{
|
|||
|
/* compressed so that non empty bps are at the low end,
|
|||
|
store ibp in ibpHashNext field (this is important for
|
|||
|
CompressRgbp relies on that), since ibpHashNext is invalid
|
|||
|
after the compress anyway */
|
|||
|
if (pbpsCur->fn != fnNil)
|
|||
|
{
|
|||
|
if (pbpsCur != pbpsUsable)
|
|||
|
{
|
|||
|
bltbyte((CHAR *)pbpsCur, (CHAR *)pbpsUsable,
|
|||
|
sizeof(struct BPS));
|
|||
|
/* reinitialized */
|
|||
|
SetBytes((CHAR*)pbpsCur, 0, sizeof(struct BPS));
|
|||
|
pbpsCur->fn = fnNil;
|
|||
|
pbpsCur->ibpHashNext = ibpNil;
|
|||
|
}
|
|||
|
pbpsUsable->ibpHashNext = ibp;
|
|||
|
pbpsUsable++;
|
|||
|
}
|
|||
|
} /* end of for */
|
|||
|
|
|||
|
/* compressed rgbp, result -- all used pages at the low end */
|
|||
|
CompressRgbp();
|
|||
|
|
|||
|
/* decrease the size of the hash table */
|
|||
|
ibpMax -= cPage;
|
|||
|
iibpHashMax = ibpMax * 2 + 1;
|
|||
|
cbRgbp = ibpMax * cbSector;
|
|||
|
|
|||
|
rgibpHash = (CHAR *)((unsigned)rgbp + cbRgbp);
|
|||
|
/* contents of rgibpHash should be all ibpNil, that is
|
|||
|
taken care in RehashRgibpHash */
|
|||
|
|
|||
|
cbBps = (ibpMax * sizeof(struct BPS) + 1) & ~1;
|
|||
|
bltbyte((CHAR *)mpibpbps, (CHAR *)(mpibpbps = (struct BPS *)
|
|||
|
(((unsigned)rgibpHash + iibpHashMax + 1) & ~1)), cbBps);
|
|||
|
|
|||
|
RehashRgibpHash();
|
|||
|
|
|||
|
cbTotalNew = cbRgbp + cbBps + ((iibpHashMax + 1) & ~1);
|
|||
|
|
|||
|
LocalReAlloc((HANDLE)rgbp, cbTotalNew, LPTR);
|
|||
|
|
|||
|
Assert(rgbp != NULL);
|
|||
|
|
|||
|
} /* end of GivePages */
|
|||
|
|
|||
|
|
|||
|
NEAR CompressRgbp()
|
|||
|
{
|
|||
|
/* compressed so that all non empty pages are moved towards the low end of
|
|||
|
rgbp */
|
|||
|
|
|||
|
register struct BPS *pbps = &mpibpbps[0];
|
|||
|
struct BPS *pbpsLim = &mpibpbps[ibpMax];
|
|||
|
int ibp;
|
|||
|
|
|||
|
for (ibp = 0; pbps < pbpsLim; ibp++, pbps++)
|
|||
|
{
|
|||
|
if (pbps->fn == fnNil)
|
|||
|
continue;
|
|||
|
if (pbps->ibpHashNext != ibp)
|
|||
|
{
|
|||
|
/* find out the location of pages (stored in ibpHashNext field) */
|
|||
|
bltbyte((CHAR *)rgbp[pbps->ibpHashNext], (CHAR *)rgbp[ibp], cbSector);
|
|||
|
}
|
|||
|
pbps->ibpHashNext = ibpNil;
|
|||
|
}
|
|||
|
} /* end of CompressRgbp */
|
|||
|
|
|||
|
|
|||
|
#ifdef DEBUG
|
|||
|
cPageUnused()
|
|||
|
{
|
|||
|
int ibp;
|
|||
|
struct BPS *pbps;
|
|||
|
int cPage = 0;
|
|||
|
|
|||
|
for (ibp = 0, pbps = &mpibpbps[0]; ibp < ibpMax; ibp++, pbps++)
|
|||
|
{
|
|||
|
if (pbps->fn == fnNil)
|
|||
|
cPage++;
|
|||
|
}
|
|||
|
return(cPage);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
|