1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-30 04:10:54 -08:00

New generic function landsize returns the total size of ranges in a land (if the land supports it). implement it for all land classes.

The MVFF pool class doesn't have to maintain its free size any more: it can just call LandSize.
Move re-entrancy protection from CBS to Land. This allows us to remove some CBS functions. (But requires some adjustment in failoverDelete.)
In MVFF, do more checking of mvff->total.

Copied from Perforce
 Change: 185569
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2014-04-15 16:35:34 +01:00
parent 4deafee125
commit 87b3880405
9 changed files with 218 additions and 160 deletions

View file

@ -40,43 +40,20 @@ SRCID(cbs, "$Id$");
#define cbsBlockPool(cbs) RVALUE((cbs)->blockPool)
/* cbsEnter, cbsLeave -- Avoid re-entrance
*
* .enter-leave: The callbacks are restricted in what they may call.
* These functions enforce this.
*
* .enter-leave.simple: Simple queries may be called from callbacks.
*/
static void cbsEnter(CBS cbs)
{
/* Don't need to check as always called from interface function. */
AVER(!cbs->inCBS);
cbs->inCBS = TRUE;
return;
}
static void cbsLeave(CBS cbs)
{
/* Don't need to check as always called from interface function. */
AVER(cbs->inCBS);
cbs->inCBS = FALSE;
return;
}
/* CBSCheck -- Check CBS */
Bool CBSCheck(CBS cbs)
{
/* See .enter-leave.simple. */
Land land;
CHECKS(CBS, cbs);
CHECKD(Land, cbsLand(cbs));
land = cbsLand(cbs);
CHECKD(Land, land);
CHECKD(SplayTree, cbsSplay(cbs));
/* nothing to check about treeSize */
CHECKD(Pool, cbs->blockPool);
CHECKL(BoolCheck(cbs->inCBS));
CHECKL(BoolCheck(cbs->ownPool));
CHECKL(SizeIsAligned(cbs->size, LandAlignment(land)));
CHECKL((cbs->size == 0) == (cbs->treeSize == 0));
return TRUE;
}
@ -84,7 +61,6 @@ Bool CBSCheck(CBS cbs)
static Bool CBSBlockCheck(CBSBlock block)
{
/* See .enter-leave.simple. */
UNUSED(block); /* Required because there is no signature */
CHECKL(block != NULL);
/* Can't use CHECKD_NOSIG because TreeEMPTY is NULL. */
@ -277,16 +253,15 @@ static Res cbsInitComm(Land land, ArgList args, SplayUpdateNodeMethod update,
cbs->ownPool = TRUE;
}
cbs->treeSize = 0;
cbs->size = 0;
cbs->blockStructSize = blockStructSize;
cbs->inCBS = TRUE;
METER_INIT(cbs->treeSearch, "size of tree", (void *)cbs);
cbs->sig = CBSSig;
AVERT(CBS, cbs);
cbsLeave(cbs);
return ResOK;
}
@ -309,7 +284,7 @@ static Res cbsInitZoned(Land land, ArgList args)
}
/* CBSFinish -- Finish a CBS structure
/* cbsFinish -- Finish a CBS structure
*
* See <design/land/#function.finish>.
*/
@ -321,7 +296,6 @@ static void cbsFinish(Land land)
AVERT(Land, land);
cbs = cbsOfLand(land);
AVERT(CBS, cbs);
cbsEnter(cbs);
METER_EMIT(&cbs->treeSearch);
@ -333,6 +307,23 @@ static void cbsFinish(Land land)
}
/* cbsSize -- total size of ranges in CBS
*
* See <design/land/#function.size>.
*/
static Size cbsSize(Land land)
{
CBS cbs;
AVERT(Land, land);
cbs = cbsOfLand(land);
AVERT(CBS, cbs);
return cbs->size;
}
/* Node change operators
*
* These four functions are called whenever blocks are created,
@ -343,14 +334,18 @@ static void cbsFinish(Land land)
static void cbsBlockDelete(CBS cbs, CBSBlock block)
{
Bool b;
Size size;
AVERT(CBS, cbs);
AVERT(CBSBlock, block);
size = CBSBlockSize(block);
METER_ACC(cbs->treeSearch, cbs->treeSize);
b = SplayTreeDelete(cbsSplay(cbs), cbsBlockTree(block));
AVER(b); /* expect block to be in the tree */
STATISTIC(--cbs->treeSize);
AVER(cbs->size >= size);
cbs->size -= size;
/* make invalid */
block->limit = block->base;
@ -367,8 +362,10 @@ static void cbsBlockShrunk(CBS cbs, CBSBlock block, Size oldSize)
newSize = CBSBlockSize(block);
AVER(oldSize > newSize);
AVER(cbs->size >= oldSize - newSize);
SplayNodeRefresh(cbsSplay(cbs), cbsBlockTree(block));
cbs->size -= oldSize - newSize;
}
static void cbsBlockGrew(CBS cbs, CBSBlock block, Size oldSize)
@ -382,6 +379,7 @@ static void cbsBlockGrew(CBS cbs, CBSBlock block, Size oldSize)
AVER(oldSize < newSize);
SplayNodeRefresh(cbsSplay(cbs), cbsBlockTree(block));
cbs->size += newSize - oldSize;
}
/* cbsBlockAlloc -- allocate a new block and set its base and limit,
@ -431,12 +429,19 @@ static void cbsBlockInsert(CBS cbs, CBSBlock block)
b = SplayTreeInsert(cbsSplay(cbs), cbsBlockTree(block));
AVER(b);
STATISTIC(++cbs->treeSize);
cbs->size += CBSBlockSize(block);
}
/* cbsInsertIntoTree -- Insert a range into the tree */
/* cbsInsert -- Insert a range into the CBS
*
* See <design/cbs/#functions.cbs.insert>.
*
* .insert.alloc: Will only allocate a block if the range does not
* abut an existing range.
*/
static Res cbsInsertIntoTree(Range rangeReturn, Land land, Range range)
static Res cbsInsert(Range rangeReturn, Land land, Range range)
{
CBS cbs;
Bool b;
@ -533,38 +538,15 @@ fail:
}
/* cbsInsert -- Insert a range into the CBS
/* cbsDelete -- Remove a range from a CBS
*
* See <design/cbs/#functions.cbs.insert>.
* See <design/land/#function.delete>.
*
* .insert.alloc: Will only allocate a block if the range does not
* abut an existing range.
* .delete.alloc: Will only allocate a block if the range splits
* an existing range.
*/
static Res cbsInsert(Range rangeReturn, Land land, Range range)
{
CBS cbs;
Res res;
AVERT(Land, land);
cbs = cbsOfLand(land);
AVERT(CBS, cbs);
cbsEnter(cbs);
AVER(rangeReturn != NULL);
AVERT(Range, range);
AVER(RangeIsAligned(range, LandAlignment(land)));
res = cbsInsertIntoTree(rangeReturn, land, range);
cbsLeave(cbs);
return res;
}
/* cbsDeleteFromTree -- delete blocks from the tree */
static Res cbsDeleteFromTree(Range rangeReturn, Land land, Range range)
static Res cbsDelete(Range rangeReturn, Land land, Range range)
{
CBS cbs;
Res res;
@ -642,35 +624,6 @@ failSplayTreeSearch:
}
/* cbsDelete -- Remove a range from a CBS
*
* See <design/land/#function.delete>.
*
* .delete.alloc: Will only allocate a block if the range splits
* an existing range.
*/
static Res cbsDelete(Range rangeReturn, Land land, Range range)
{
CBS cbs;
Res res;
AVERT(Land, land);
cbs = cbsOfLand(land);
AVERT(CBS, cbs);
cbsEnter(cbs);
AVER(rangeReturn != NULL);
AVERT(Range, range);
AVER(RangeIsAligned(range, LandAlignment(land)));
res = cbsDeleteFromTree(rangeReturn, land, range);
cbsLeave(cbs);
return res;
}
static Res cbsBlockDescribe(CBSBlock block, mps_lib_FILE *stream)
{
Res res;
@ -813,7 +766,6 @@ static void cbsIterate(Land land, LandVisitor visitor,
AVERT(Land, land);
cbs = cbsOfLand(land);
AVERT(CBS, cbs);
cbsEnter(cbs);
AVER(FUNCHECK(visitor));
splay = cbsSplay(cbs);
@ -827,9 +779,6 @@ static void cbsIterate(Land land, LandVisitor visitor,
closure.closureS = closureS;
(void)TreeTraverse(SplayTreeRoot(splay), splay->compare, splay->nodeKey,
cbsIterateVisit, &closure, 0);
cbsLeave(cbs);
return;
}
@ -882,10 +831,10 @@ static void cbsFindDeleteRange(Range rangeReturn, Range oldRangeReturn,
if (callDelete) {
Res res;
res = cbsDeleteFromTree(oldRangeReturn, land, rangeReturn);
res = cbsDelete(oldRangeReturn, land, rangeReturn);
/* Can't have run out of memory, because all our callers pass in
blocks that were just found in the tree, and we only
deleted from one end of the block, so cbsDeleteFromTree did not
deleted from one end of the block, so cbsDelete did not
need to allocate a new block. */
AVER(res == ResOK);
}
@ -905,7 +854,6 @@ static Bool cbsFindFirst(Range rangeReturn, Range oldRangeReturn,
cbs = cbsOfLand(land);
AVERT(CBS, cbs);
AVER(IsLandSubclass(cbsLand(cbs), CBSFastLandClass));
cbsEnter(cbs);
AVER(rangeReturn != NULL);
AVER(oldRangeReturn != NULL);
@ -927,7 +875,6 @@ static Bool cbsFindFirst(Range rangeReturn, Range oldRangeReturn,
size, findDelete);
}
cbsLeave(cbs);
return found;
}
@ -992,7 +939,6 @@ static Bool cbsFindLast(Range rangeReturn, Range oldRangeReturn,
cbs = cbsOfLand(land);
AVERT(CBS, cbs);
AVER(IsLandSubclass(cbsLand(cbs), CBSFastLandClass));
cbsEnter(cbs);
AVER(rangeReturn != NULL);
AVER(oldRangeReturn != NULL);
@ -1014,7 +960,6 @@ static Bool cbsFindLast(Range rangeReturn, Range oldRangeReturn,
size, findDelete);
}
cbsLeave(cbs);
return found;
}
@ -1031,7 +976,6 @@ static Bool cbsFindLargest(Range rangeReturn, Range oldRangeReturn,
cbs = cbsOfLand(land);
AVERT(CBS, cbs);
AVER(IsLandSubclass(cbsLand(cbs), CBSFastLandClass));
cbsEnter(cbs);
AVER(rangeReturn != NULL);
AVER(oldRangeReturn != NULL);
@ -1058,7 +1002,6 @@ static Bool cbsFindLargest(Range rangeReturn, Range oldRangeReturn,
}
}
cbsLeave(cbs);
return found;
}
@ -1101,8 +1044,6 @@ static Res cbsFindInZones(Range rangeReturn, Range oldRangeReturn,
/* It would be nice if there were a neat way to eliminate all runs of
zones in zoneSet too small for size.*/
cbsEnter(cbs);
closure.arena = LandArena(land);
closure.zoneSet = zoneSet;
closure.size = size;
@ -1123,7 +1064,7 @@ static Res cbsFindInZones(Range rangeReturn, Range oldRangeReturn,
RangeInit(&rangeStruct, closure.base, AddrAdd(closure.base, size));
else
RangeInit(&rangeStruct, AddrSub(closure.limit, size), closure.limit);
res = cbsDeleteFromTree(&oldRangeStruct, land, &rangeStruct);
res = cbsDelete(&oldRangeStruct, land, &rangeStruct);
if (res == ResOK) { /* enough memory to split block */
RangeCopy(rangeReturn, &rangeStruct);
RangeCopy(oldRangeReturn, &oldRangeStruct);
@ -1131,7 +1072,6 @@ static Res cbsFindInZones(Range rangeReturn, Range oldRangeReturn,
} else
res = ResFAIL;
cbsLeave(cbs);
return res;
}
@ -1158,7 +1098,6 @@ static Res cbsDescribe(Land land, mps_lib_FILE *stream)
res = WriteF(stream,
"CBS $P {\n", (WriteFP)cbs,
" blockPool: $P\n", (WriteFP)cbsBlockPool(cbs),
" inCBS: $U\n", (WriteFU)cbs->inCBS,
" ownPool: $U\n", (WriteFU)cbs->ownPool,
" treeSize: $U\n", (WriteFU)cbs->treeSize,
NULL);
@ -1187,6 +1126,7 @@ DEFINE_LAND_CLASS(CBSLandClass, class)
class->size = sizeof(CBSStruct);
class->init = cbsInit;
class->finish = cbsFinish;
class->sizeMethod = cbsSize;
class->insert = cbsInsert;
class->delete = cbsDelete;
class->iterate = cbsIterate;

View file

@ -70,6 +70,18 @@ static void failoverFinish(Land land)
}
static Size failoverSize(Land land)
{
Failover fo;
AVERT(Land, land);
fo = failoverOfLand(land);
AVERT(Failover, fo);
return LandSize(fo->primary) + LandSize(fo->secondary);
}
static Res failoverInsert(Range rangeReturn, Land land, Range range)
{
Failover fo;
@ -129,12 +141,18 @@ static Res failoverDelete(Range rangeReturn, Land land, Range range)
AVER(RangesEqual(&oldRange, &dummyRange));
RangeInit(&left, RangeBase(&oldRange), RangeBase(range));
if (!RangeIsEmpty(&left)) {
res = LandInsert(&dummyRange, land, &left);
/* Don't call LandInsert(..., land, ...) here: that would be
* re-entrant and fail the landEnter check. */
res = LandInsert(&dummyRange, fo->primary, &left);
if (res != ResOK && res != ResFAIL)
res = LandInsert(&dummyRange, fo->secondary, &left);
AVER(res == ResOK);
}
RangeInit(&right, RangeLimit(range), RangeLimit(&oldRange));
if (!RangeIsEmpty(&right)) {
res = LandInsert(&dummyRange, land, &right);
res = LandInsert(&dummyRange, fo->primary, &right);
if (res != ResOK && res != ResFAIL)
res = LandInsert(&dummyRange, fo->secondary, &right);
AVER(res == ResOK);
}
}
@ -266,6 +284,7 @@ DEFINE_LAND_CLASS(FailoverLandClass, class)
class->size = sizeof(FailoverStruct);
class->init = failoverInit;
class->finish = failoverFinish;
class->sizeMethod = failoverSize;
class->insert = failoverInsert;
class->delete = failoverDelete;
class->iterate = failoverIterate;

View file

@ -168,8 +168,11 @@ Bool FreelistCheck(Freelist fl)
land = &fl->landStruct;
CHECKD(Land, land);
/* See <design/freelist/#impl.grain.align> */
CHECKL(AlignIsAligned(LandAlignment(land), freelistMinimumAlignment));
CHECKL(AlignIsAligned(freelistAlignment(fl), freelistMinimumAlignment));
CHECKL((fl->list == NULL) == (fl->listSize == 0));
CHECKL((fl->list == NULL) == (fl->size == 0));
CHECKL(SizeIsAligned(fl->size, freelistAlignment(fl)));
return TRUE;
}
@ -192,6 +195,7 @@ static Res freelistInit(Land land, ArgList args)
fl = freelistOfLand(land);
fl->list = NULL;
fl->listSize = 0;
fl->size = 0;
fl->sig = FreelistSig;
AVERT(Freelist, fl);
@ -211,6 +215,17 @@ static void freelistFinish(Land land)
}
static Size freelistSize(Land land)
{
Freelist fl;
AVERT(Land, land);
fl = freelistOfLand(land);
AVERT(Freelist, fl);
return fl->size;
}
/* freelistBlockSetPrevNext -- update list of blocks
*
* If prev and next are both NULL, make the block list empty.
@ -303,6 +318,7 @@ static Res freelistInsert(Range rangeReturn, Land land, Range range)
freelistBlockSetPrevNext(fl, prev, new, +1);
}
fl->size += RangeSize(range);
RangeInit(rangeReturn, base, limit);
return ResOK;
}
@ -360,6 +376,8 @@ static void freelistDeleteFromBlock(Range rangeReturn, Freelist fl,
freelistBlockSetPrevNext(fl, block, new, +1);
}
AVER(fl->size >= RangeSize(range));
fl->size -= RangeSize(range);
RangeInit(rangeReturn, blockBase, blockLimit);
}
@ -426,7 +444,10 @@ static void freelistIterate(Land land, LandVisitor visitor,
cont = (*visitor)(&delete, land, &range, closureP, closureS);
next = FreelistBlockNext(cur);
if (delete) {
Size size = FreelistBlockSize(fl, cur);
freelistBlockSetPrevNext(fl, prev, next, -1);
AVER(fl->size >= size);
fl->size -= size;
} else {
prev = cur;
}
@ -726,6 +747,7 @@ DEFINE_LAND_CLASS(FreelistLandClass, class)
class->size = sizeof(FreelistStruct);
class->init = freelistInit;
class->finish = freelistFinish;
class->sizeMethod = freelistSize;
class->insert = freelistInsert;
class->delete = freelistDelete;
class->iterate = freelistIterate;

View file

@ -26,16 +26,41 @@ Bool FindDeleteCheck(FindDelete findDelete)
}
/* landEnter, landLeave -- Avoid re-entrance
*
* .enter-leave: The visitor function passed to LandIterate is not
* allowed to call methods of that land. These functions enforce this.
*
* .enter-leave.simple: Some simple queries are fine to call from
* visitor functions. These are marked with the tag of this comment.
*/
static void landEnter(Land land)
{
/* Don't need to check as always called from interface function. */
AVER(!land->inLand);
land->inLand = TRUE;
return;
}
static void landLeave(Land land)
{
/* Don't need to check as always called from interface function. */
AVER(land->inLand);
land->inLand = FALSE;
return;
}
/* LandCheck -- check land */
Bool LandCheck(Land land)
{
/* .enter-leave.simple */
CHECKS(Land, land);
CHECKD(LandClass, land->class);
CHECKU(Arena, land->arena);
CHECKL(AlignCheck(land->alignment));
CHECKL(SizeIsAligned(land->size, land->alignment));
/* too expensive to check land->size against contents */
return TRUE;
}
@ -53,7 +78,7 @@ Res LandInit(Land land, LandClass class, Arena arena, Align alignment, void *own
AVERT(LandClass, class);
AVERT(Align, alignment);
land->size = 0;
land->inLand = TRUE;
land->alignment = alignment;
land->arena = arena;
land->class = class;
@ -66,6 +91,7 @@ Res LandInit(Land land, LandClass class, Arena arena, Align alignment, void *own
goto failInit;
EVENT2(LandInit, land, owner);
landLeave(land);
return ResOK;
failInit:
@ -136,6 +162,7 @@ void LandDestroy(Land land)
void LandFinish(Land land)
{
AVERT(Land, land);
landEnter(land);
(*land->class->finish)(land);
@ -143,6 +170,20 @@ void LandFinish(Land land)
}
/* LandSize -- return the total size of ranges in land
*
* See <design/land/#function.size>
*/
Size LandSize(Land land)
{
/* .enter-leave.simple */
AVERT(Land, land);
return (*land->class->sizeMethod)(land);
}
/* LandInsert -- insert range of addresses into land
*
* See <design/land/#function.insert>
@ -151,19 +192,16 @@ void LandFinish(Land land)
Res LandInsert(Range rangeReturn, Land land, Range range)
{
Res res;
Size size;
AVER(rangeReturn != NULL);
AVERT(Land, land);
AVERT(Range, range);
AVER(RangeIsAligned(range, land->alignment));
landEnter(land);
/* rangeReturn is allowed to alias with range, so take size first.
* See <design/land/#.function.insert.alias> */
size = RangeSize(range);
res = (*land->class->insert)(rangeReturn, land, range);
if (res == ResOK)
land->size += size;
landLeave(land);
return res;
}
@ -176,20 +214,16 @@ Res LandInsert(Range rangeReturn, Land land, Range range)
Res LandDelete(Range rangeReturn, Land land, Range range)
{
Res res;
Size size;
AVER(rangeReturn != NULL);
AVERT(Land, land);
AVERT(Range, range);
AVER(RangeIsAligned(range, land->alignment));
landEnter(land);
/* rangeReturn is allowed to alias with range, so take size first.
* See <design/land/#.function.delete.alias> */
size = RangeSize(range);
AVER(land->size >= size);
res = (*land->class->delete)(rangeReturn, land, range);
if (res == ResOK)
land->size -= size;
landLeave(land);
return res;
}
@ -203,8 +237,11 @@ void LandIterate(Land land, LandVisitor visitor, void *closureP, Size closureS)
{
AVERT(Land, land);
AVER(FUNCHECK(visitor));
landEnter(land);
(*land->class->iterate)(land, visitor, closureP, closureS);
landLeave(land);
}
@ -222,14 +259,12 @@ Bool LandFindFirst(Range rangeReturn, Range oldRangeReturn, Land land, Size size
AVERT(Land, land);
AVER(SizeIsAligned(size, land->alignment));
AVER(FindDeleteCheck(findDelete));
landEnter(land);
res = (*land->class->findFirst)(rangeReturn, oldRangeReturn, land, size,
findDelete);
if (res && findDelete != FindDeleteNONE) {
AVER(RangeIsAligned(rangeReturn, land->alignment));
AVER(land->size >= RangeSize(rangeReturn));
land->size -= RangeSize(rangeReturn);
}
landLeave(land);
return res;
}
@ -248,14 +283,12 @@ Bool LandFindLast(Range rangeReturn, Range oldRangeReturn, Land land, Size size,
AVERT(Land, land);
AVER(SizeIsAligned(size, land->alignment));
AVER(FindDeleteCheck(findDelete));
landEnter(land);
res = (*land->class->findLast)(rangeReturn, oldRangeReturn, land, size,
findDelete);
if (res && findDelete != FindDeleteNONE) {
AVER(RangeIsAligned(rangeReturn, land->alignment));
AVER(land->size >= RangeSize(rangeReturn));
land->size -= RangeSize(rangeReturn);
}
landLeave(land);
return res;
}
@ -274,14 +307,12 @@ Bool LandFindLargest(Range rangeReturn, Range oldRangeReturn, Land land, Size si
AVERT(Land, land);
AVER(SizeIsAligned(size, land->alignment));
AVER(FindDeleteCheck(findDelete));
landEnter(land);
res = (*land->class->findLargest)(rangeReturn, oldRangeReturn, land, size,
findDelete);
if (res && findDelete != FindDeleteNONE) {
AVER(RangeIsAligned(rangeReturn, land->alignment));
AVER(land->size >= RangeSize(rangeReturn));
land->size -= RangeSize(rangeReturn);
}
landLeave(land);
return res;
}
@ -301,14 +332,12 @@ Res LandFindInZones(Range rangeReturn, Range oldRangeReturn, Land land, Size siz
AVER(SizeIsAligned(size, land->alignment));
/* AVER(ZoneSet, zoneSet); */
AVERT(Bool, high);
landEnter(land);
res = (*land->class->findInZones)(rangeReturn, oldRangeReturn, land, size,
zoneSet, high);
if (res == ResOK) {
AVER(RangeIsAligned(rangeReturn, land->alignment));
AVER(land->size >= RangeSize(rangeReturn));
land->size -= RangeSize(rangeReturn);
}
landLeave(land);
return res;
}
@ -331,7 +360,7 @@ Res LandDescribe(Land land, mps_lib_FILE *stream)
" (\"$S\")\n", land->class->name,
" arena $P\n", (WriteFP)land->arena,
" align $U\n", (WriteFU)land->alignment,
" align $U\n", (WriteFU)land->size,
" inLand: $U\n", (WriteFU)land->inLand,
NULL);
if (res != ResOK)
return res;
@ -424,6 +453,40 @@ static void landTrivFinish(Land land)
NOOP;
}
static Size landNoSize(Land land)
{
UNUSED(land);
NOTREACHED;
return 0;
}
/* LandSlowSize -- generic size method but slow */
static Bool landSizeVisitor(Bool *deleteReturn, Land land, Range range,
void *closureP, Size closureS)
{
Size *size;
AVER(deleteReturn != NULL);
AVERT(Land, land);
AVERT(Range, range);
AVER(closureP != NULL);
UNUSED(closureS);
size = closureP;
*size += RangeSize(range);
*deleteReturn = FALSE;
return TRUE;
}
Size LandSlowSize(Land land)
{
Size size = 0;
LandIterate(land, landSizeVisitor, &size, 0);
return size;
}
static Res landNoInsert(Range rangeReturn, Land land, Range range)
{
AVER(rangeReturn != NULL);
@ -486,6 +549,7 @@ DEFINE_CLASS(LandClass, class)
class->name = "LAND";
class->size = sizeof(LandStruct);
class->init = landTrivInit;
class->sizeMethod = landNoSize;
class->finish = landTrivFinish;
class->insert = landNoInsert;
class->delete = landNoDelete;

View file

@ -1002,8 +1002,7 @@ extern Size VMMapped(VM vm);
extern Bool LandCheck(Land land);
#define LandArena(land) ((land)->arena)
#define LandAlignment(land) ((land)->alignment)
#define LandSize(land) ((land)->size)
extern Size LandSize(Land land);
extern Res LandInit(Land land, LandClass class, Arena arena, Align alignment, void *owner, ArgList args);
extern Res LandCreate(Land *landReturn, Arena arena, LandClass class, Align alignment, void *owner, ArgList args);
extern void LandDestroy(Land land);
@ -1018,6 +1017,7 @@ extern Res LandFindInZones(Range rangeReturn, Range oldRangeReturn, Land land, S
extern Res LandDescribe(Land land, mps_lib_FILE *stream);
extern void LandFlush(Land dest, Land src);
extern Size LandSlowSize(Land land);
extern Bool LandClassCheck(LandClass class);
extern LandClass LandClassGet(void);
#define LAND_SUPERCLASS(className) ((LandClass)SUPERCLASS(className))

View file

@ -615,6 +615,7 @@ typedef struct LandClassStruct {
ProtocolClassStruct protocol;
const char *name; /* class name string */
size_t size; /* size of outer structure */
LandSizeMethod sizeMethod; /* total size of ranges in land */
LandInitMethod init; /* initialize the land */
LandFinishMethod finish; /* finish the land */
LandInsertMethod insert; /* insert a range into the land */
@ -641,7 +642,7 @@ typedef struct LandStruct {
LandClass class; /* land class structure */
Arena arena; /* owning arena */
Align alignment; /* alignment of addresses */
Size size; /* total size of ranges in land */
Bool inLand; /* prevent reentrance */
} LandStruct;
@ -661,8 +662,8 @@ typedef struct CBSStruct {
STATISTIC_DECL(Count treeSize);
Pool blockPool; /* pool that manages blocks */
Size blockStructSize; /* size of block structure */
Bool inCBS; /* prevent reentrance */
Bool ownPool; /* did we create blockPool? */
Size size; /* total size of ranges in CBS */
/* meters for sizes of search structures at each op */
METER_DECL(treeSearch);
Sig sig; /* .class.end-sig */
@ -703,6 +704,7 @@ typedef struct FreelistStruct {
LandStruct landStruct; /* superclass fields come first */
FreelistBlock list; /* first block in list or NULL if empty */
Count listSize; /* number of blocks in list */
Size size; /* total size of ranges in list */
Sig sig; /* .class.end-sig */
} FreelistStruct;

View file

@ -268,6 +268,7 @@ typedef struct TraceMessageStruct *TraceMessage; /* trace end */
typedef Res (*LandInitMethod)(Land land, ArgList args);
typedef void (*LandFinishMethod)(Land land);
typedef Size (*LandSizeMethod)(Land land);
typedef Res (*LandInsertMethod)(Range rangeReturn, Land land, Range range);
typedef Res (*LandDeleteMethod)(Range rangeReturn, Land land, Range range);
typedef Bool (*LandVisitor)(Bool *deleteReturn, Land land, Range range, void *closureP, Size closureS);

View file

@ -141,6 +141,7 @@ static void MVFFFreeSegs(MVFF mvff, Range range)
* that needs to be read in order to update the Freelist. */
SegFree(seg);
AVER(mvff->total >= RangeSize(&delRange));
mvff->total -= RangeSize(&delRange);
}
@ -502,7 +503,8 @@ static Res MVFFInit(Pool pool, ArgList args)
mvff->total = 0;
res = LandInit(FreelistOfMVFF(mvff), FreelistLandClassGet(), arena, align, mvff, mps_args_none);
res = LandInit(FreelistOfMVFF(mvff), FreelistLandClassGet(), arena, align,
mvff, mps_args_none);
if (res != ResOK)
goto failFreelistInit;
@ -514,7 +516,8 @@ static Res MVFFInit(Pool pool, ArgList args)
MPS_ARGS_BEGIN(foArgs) {
MPS_ARGS_ADD(foArgs, FailoverPrimary, CBSOfMVFF(mvff));
MPS_ARGS_ADD(foArgs, FailoverSecondary, FreelistOfMVFF(mvff));
res = LandInit(FailoverOfMVFF(mvff), FailoverLandClassGet(), arena, align, mvff, foArgs);
res = LandInit(FailoverOfMVFF(mvff), FailoverLandClassGet(), arena, align,
mvff, foArgs);
} MPS_ARGS_END(foArgs);
if (res != ResOK)
goto failFailoverInit;
@ -541,7 +544,6 @@ static void MVFFFinish(Pool pool)
{
MVFF mvff;
Arena arena;
Seg seg;
Ring ring, node, nextNode;
AVERT(Pool, pool);
@ -550,14 +552,17 @@ static void MVFFFinish(Pool pool)
ring = PoolSegRing(pool);
RING_FOR(node, ring, nextNode) {
Size size;
Seg seg;
seg = SegOfPoolRing(node);
AVER(SegPool(seg) == pool);
size = AddrOffset(SegBase(seg), SegLimit(seg));
AVER(size <= mvff->total);
mvff->total -= size;
SegFree(seg);
}
/* Could maintain mvff->total here and check it falls to zero, */
/* but that would just make the function slow. If only we had */
/* a way to do operations only if AVERs are turned on. */
AVER(mvff->total == 0);
arena = PoolArena(pool);
ControlFree(arena, mvff->segPref, sizeof(SegPrefStruct));
@ -719,11 +724,11 @@ static Bool MVFFCheck(MVFF mvff)
CHECKL(mvff->minSegSize >= ArenaAlign(PoolArena(MVFF2Pool(mvff))));
CHECKL(mvff->avgSize > 0); /* see .arg.check */
CHECKL(mvff->avgSize <= mvff->extendBy); /* see .arg.check */
CHECKL(mvff->total >= LandSize(FailoverOfMVFF(mvff)));
CHECKL(SizeIsAligned(mvff->total, ArenaAlign(PoolArena(MVFF2Pool(mvff)))));
CHECKD(CBS, &mvff->cbsStruct);
CHECKD(Freelist, &mvff->flStruct);
CHECKD(Failover, &mvff->foStruct);
CHECKL(mvff->total >= LandSize(FailoverOfMVFF(mvff)));
CHECKL(BoolCheck(mvff->slotHigh));
CHECKL(BoolCheck(mvff->firstFit));
return TRUE;

View file

@ -117,6 +117,11 @@ finish the land structure, and then frees its memory.
_`.function.finish`: ``LandFinish()`` finishes the land structure and
discards any other resources associated with the land.
``void LandSize(Land land)``
_`.function.size`: ``LandSize()`` returns the total size of the ranges
stored in the land.
``Res LandInsert(Range rangeReturn, Land land, Range range)``
_`.function.insert`: If any part of ``range`` is already in the