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:
parent
4deafee125
commit
87b3880405
9 changed files with 218 additions and 160 deletions
158
mps/code/cbs.c
158
mps/code/cbs.c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
138
mps/code/land.c
138
mps/code/land.c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue