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
|
||
|
||
|
||
|