mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-30 12:21:25 -08:00
Turn freelist into a land class.
Copied from Perforce Change: 185155 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
5314260bc8
commit
b409ae89f6
19 changed files with 492 additions and 534 deletions
|
|
@ -26,7 +26,7 @@ SRCID(cbs, "$Id$");
|
|||
#define CBSBlockSize(block) AddrOffset((block)->base, (block)->limit)
|
||||
|
||||
|
||||
#define cbsOfLand(land) ((CBS)(land))
|
||||
#define cbsOfLand(land) PARENT(CBSStruct, landStruct, land)
|
||||
#define cbsSplay(cbs) (&((cbs)->splayTreeStruct))
|
||||
#define cbsOfSplay(_splay) PARENT(CBSStruct, splayTreeStruct, _splay)
|
||||
#define cbsBlockTree(block) (&((block)->treeStruct))
|
||||
|
|
@ -720,7 +720,7 @@ static Res cbsSplayNodeDescribe(Tree tree, mps_lib_FILE *stream)
|
|||
|
||||
typedef struct CBSIterateClosure {
|
||||
Land land;
|
||||
LandVisitor iterate;
|
||||
LandVisitor visitor;
|
||||
void *closureP;
|
||||
Size closureS;
|
||||
} CBSIterateClosure;
|
||||
|
|
@ -732,12 +732,16 @@ static Bool cbsIterateVisit(Tree tree, void *closureP, Size closureS)
|
|||
CBSBlock cbsBlock;
|
||||
Land land = closure->land;
|
||||
CBS cbs = cbsOfLand(land);
|
||||
Bool delete = FALSE;
|
||||
Bool cont = TRUE;
|
||||
|
||||
UNUSED(closureS);
|
||||
|
||||
cbsBlock = cbsBlockOfTree(tree);
|
||||
RangeInit(&range, CBSBlockBase(cbsBlock), CBSBlockLimit(cbsBlock));
|
||||
if (!closure->iterate(land, &range, closure->closureP, closure->closureS))
|
||||
cont = (*closure->visitor)(&delete, land, &range, closure->closureP, closure->closureS);
|
||||
AVER(!delete);
|
||||
if (!cont)
|
||||
return FALSE;
|
||||
METER_ACC(cbs->treeSearch, cbs->treeSize);
|
||||
return TRUE;
|
||||
|
|
@ -762,7 +766,7 @@ static void cbsIterate(Land land, LandVisitor visitor,
|
|||
METER_ACC(cbs->treeSearch, cbs->treeSize);
|
||||
|
||||
closure.land = land;
|
||||
closure.iterate = visitor;
|
||||
closure.visitor = visitor;
|
||||
closure.closureP = closureP;
|
||||
closure.closureS = closureS;
|
||||
(void)TreeTraverse(SplayTreeRoot(splay), splay->compare, splay->nodeKey,
|
||||
|
|
|
|||
|
|
@ -280,11 +280,11 @@ TEST_TARGETS=\
|
|||
djbench \
|
||||
exposet0 \
|
||||
expt825 \
|
||||
fbmtest \
|
||||
finalcv \
|
||||
finaltest \
|
||||
fotest \
|
||||
gcbench \
|
||||
landtest \
|
||||
locbwcss \
|
||||
lockcov \
|
||||
locusss \
|
||||
|
|
@ -452,9 +452,6 @@ $(PFM)/$(VARIETY)/exposet0: $(PFM)/$(VARIETY)/exposet0.o \
|
|||
$(PFM)/$(VARIETY)/expt825: $(PFM)/$(VARIETY)/expt825.o \
|
||||
$(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/fbmtest: $(PFM)/$(VARIETY)/fbmtest.o \
|
||||
$(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/finalcv: $(PFM)/$(VARIETY)/finalcv.o \
|
||||
$(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
|
|
@ -467,6 +464,9 @@ $(PFM)/$(VARIETY)/fotest: $(PFM)/$(VARIETY)/fotest.o \
|
|||
$(PFM)/$(VARIETY)/gcbench: $(PFM)/$(VARIETY)/gcbench.o \
|
||||
$(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/landtest: $(PFM)/$(VARIETY)/landtest.o \
|
||||
$(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/locbwcss: $(PFM)/$(VARIETY)/locbwcss.o \
|
||||
$(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
|
|
|
|||
|
|
@ -158,9 +158,6 @@ $(PFM)\$(VARIETY)\exposet0.exe: $(PFM)\$(VARIETY)\exposet0.obj \
|
|||
$(PFM)\$(VARIETY)\expt825.exe: $(PFM)\$(VARIETY)\expt825.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\fbmtest.exe: $(PFM)\$(VARIETY)\fbmtest.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\finalcv.exe: $(PFM)\$(VARIETY)\finalcv.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
|
||||
|
||||
|
|
@ -170,6 +167,9 @@ $(PFM)\$(VARIETY)\finaltest.exe: $(PFM)\$(VARIETY)\finaltest.obj \
|
|||
$(PFM)\$(VARIETY)\fotest.exe: $(PFM)\$(VARIETY)\fotest.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\landtest.exe: $(PFM)\$(VARIETY)\landtest.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\locbwcss.exe: $(PFM)\$(VARIETY)\locbwcss.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
|
||||
|
||||
|
|
|
|||
|
|
@ -66,10 +66,10 @@ TEST_TARGETS=\
|
|||
bttest.exe \
|
||||
exposet0.exe \
|
||||
expt825.exe \
|
||||
fbmtest.exe \
|
||||
finalcv.exe \
|
||||
finaltest.exe \
|
||||
fotest.exe \
|
||||
landtest.exe \
|
||||
locbwcss.exe \
|
||||
lockcov.exe \
|
||||
lockutw3.exe \
|
||||
|
|
|
|||
|
|
@ -12,10 +12,14 @@
|
|||
SRCID(freelist, "$Id$");
|
||||
|
||||
|
||||
#define freelistOfLand(land) PARENT(FreelistStruct, landStruct, land)
|
||||
#define freelistAlignment(fl) LandAlignment(&fl->landStruct)
|
||||
|
||||
|
||||
typedef union FreelistBlockUnion {
|
||||
struct {
|
||||
FreelistBlock next; /* tagged with low bit 1 */
|
||||
/* limit is (char *)this + fl->alignment */
|
||||
/* limit is (char *)this + freelistAlignment(fl) */
|
||||
} small;
|
||||
struct {
|
||||
FreelistBlock next;
|
||||
|
|
@ -50,7 +54,7 @@ static Addr FreelistBlockLimit(Freelist fl, FreelistBlock block)
|
|||
{
|
||||
AVERT(Freelist, fl);
|
||||
if (FreelistBlockIsSmall(block)) {
|
||||
return AddrAdd(FreelistBlockBase(block), fl->alignment);
|
||||
return AddrAdd(FreelistBlockBase(block), freelistAlignment(fl));
|
||||
} else {
|
||||
return block->large.limit;
|
||||
}
|
||||
|
|
@ -104,7 +108,7 @@ static void FreelistBlockSetLimit(Freelist fl, FreelistBlock block, Addr limit)
|
|||
|
||||
AVERT(Freelist, fl);
|
||||
AVERT(FreelistBlock, block);
|
||||
AVER(AddrIsAligned(limit, fl->alignment));
|
||||
AVER(AddrIsAligned(limit, freelistAlignment(fl)));
|
||||
AVER(FreelistBlockBase(block) < limit);
|
||||
|
||||
size = AddrOffset(block, limit);
|
||||
|
|
@ -127,9 +131,9 @@ static FreelistBlock FreelistBlockInit(Freelist fl, Addr base, Addr limit)
|
|||
|
||||
AVERT(Freelist, fl);
|
||||
AVER(base != NULL);
|
||||
AVER(AddrIsAligned(base, fl->alignment));
|
||||
AVER(AddrIsAligned(base, freelistAlignment(fl)));
|
||||
AVER(base < limit);
|
||||
AVER(AddrIsAligned(limit, fl->alignment));
|
||||
AVER(AddrIsAligned(limit, freelistAlignment(fl)));
|
||||
|
||||
block = (FreelistBlock)base;
|
||||
block->small.next = FreelistTagSet(NULL);
|
||||
|
|
@ -141,21 +145,34 @@ static FreelistBlock FreelistBlockInit(Freelist fl, Addr base, Addr limit)
|
|||
|
||||
Bool FreelistCheck(Freelist fl)
|
||||
{
|
||||
Land land;
|
||||
CHECKS(Freelist, fl);
|
||||
land = &fl->landStruct;
|
||||
CHECKL(LandCheck(land));
|
||||
/* See <design/freelist/#impl.grain.align> */
|
||||
CHECKL(AlignIsAligned(fl->alignment, freelistMinimumAlignment));
|
||||
CHECKL(AlignIsAligned(LandAlignment(land), freelistMinimumAlignment));
|
||||
CHECKL((fl->list == NULL) == (fl->listSize == 0));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
Res FreelistInit(Freelist fl, Align alignment)
|
||||
static Res freelistInit(Land land, ArgList args)
|
||||
{
|
||||
Freelist fl;
|
||||
LandClass super;
|
||||
Res res;
|
||||
|
||||
AVERT(Land, land);
|
||||
super = LAND_SUPERCLASS(FreelistLandClass);
|
||||
res = (*super->init)(land, args);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
/* See <design/freelist/#impl.grain> */
|
||||
if (!AlignIsAligned(alignment, freelistMinimumAlignment))
|
||||
if (!AlignIsAligned(LandAlignment(land), freelistMinimumAlignment))
|
||||
return ResPARAM;
|
||||
|
||||
fl->alignment = alignment;
|
||||
fl = freelistOfLand(land);
|
||||
fl->list = NULL;
|
||||
fl->listSize = 0;
|
||||
|
||||
|
|
@ -165,8 +182,12 @@ Res FreelistInit(Freelist fl, Align alignment)
|
|||
}
|
||||
|
||||
|
||||
void FreelistFinish(Freelist fl)
|
||||
static void freelistFinish(Land land)
|
||||
{
|
||||
Freelist fl;
|
||||
|
||||
AVERT(Land, land);
|
||||
fl = freelistOfLand(land);
|
||||
AVERT(Freelist, fl);
|
||||
fl->sig = SigInvalid;
|
||||
fl->list = NULL;
|
||||
|
|
@ -200,16 +221,19 @@ static void freelistBlockSetPrevNext(Freelist fl, FreelistBlock prev,
|
|||
}
|
||||
|
||||
|
||||
Res FreelistInsert(Range rangeReturn, Freelist fl, Range range)
|
||||
static Res freelistInsert(Range rangeReturn, Land land, Range range)
|
||||
{
|
||||
Freelist fl;
|
||||
FreelistBlock prev, cur, next, new;
|
||||
Addr base, limit;
|
||||
Bool coalesceLeft, coalesceRight;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
fl = freelistOfLand(land);
|
||||
AVERT(Freelist, fl);
|
||||
AVERT(Range, range);
|
||||
AVER(RangeIsAligned(range, fl->alignment));
|
||||
AVER(RangeIsAligned(range, freelistAlignment(fl)));
|
||||
|
||||
base = RangeBase(range);
|
||||
limit = RangeLimit(range);
|
||||
|
|
@ -281,7 +305,7 @@ static void freelistDeleteFromBlock(Range rangeReturn, Freelist fl,
|
|||
AVER(rangeReturn != NULL);
|
||||
AVERT(Freelist, fl);
|
||||
AVERT(Range, range);
|
||||
AVER(RangeIsAligned(range, fl->alignment));
|
||||
AVER(RangeIsAligned(range, freelistAlignment(fl)));
|
||||
AVER(prev == NULL || FreelistBlockNext(prev) == block);
|
||||
AVERT(FreelistBlock, block);
|
||||
AVER(FreelistBlockBase(block) <= RangeBase(range));
|
||||
|
|
@ -319,12 +343,15 @@ static void freelistDeleteFromBlock(Range rangeReturn, Freelist fl,
|
|||
}
|
||||
|
||||
|
||||
Res FreelistDelete(Range rangeReturn, Freelist fl, Range range)
|
||||
static Res freelistDelete(Range rangeReturn, Land land, Range range)
|
||||
{
|
||||
Freelist fl;
|
||||
FreelistBlock prev, cur, next;
|
||||
Addr base, limit;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
fl = freelistOfLand(land);
|
||||
AVERT(Freelist, fl);
|
||||
AVERT(Range, range);
|
||||
|
||||
|
|
@ -357,13 +384,16 @@ Res FreelistDelete(Range rangeReturn, Freelist fl, Range range)
|
|||
}
|
||||
|
||||
|
||||
void FreelistIterate(Freelist fl, FreelistIterateMethod iterate,
|
||||
void *closureP, Size closureS)
|
||||
static void freelistIterate(Land land, LandVisitor visitor,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
Freelist fl;
|
||||
FreelistBlock prev, cur, next;
|
||||
|
||||
AVERT(Land, land);
|
||||
fl = freelistOfLand(land);
|
||||
AVERT(Freelist, fl);
|
||||
AVER(FUNCHECK(iterate));
|
||||
AVER(FUNCHECK(visitor));
|
||||
|
||||
prev = NULL;
|
||||
cur = fl->list;
|
||||
|
|
@ -372,7 +402,7 @@ void FreelistIterate(Freelist fl, FreelistIterateMethod iterate,
|
|||
RangeStruct range;
|
||||
Bool cont;
|
||||
RangeInit(&range, FreelistBlockBase(cur), FreelistBlockLimit(fl, cur));
|
||||
cont = (*iterate)(&delete, &range, closureP, closureS);
|
||||
cont = (*visitor)(&delete, land, &range, closureP, closureS);
|
||||
next = FreelistBlockNext(cur);
|
||||
if (delete) {
|
||||
freelistBlockSetPrevNext(fl, prev, next, -1);
|
||||
|
|
@ -405,7 +435,7 @@ static void freelistFindDeleteFromBlock(Range rangeReturn, Range oldRangeReturn,
|
|||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(Freelist, fl);
|
||||
AVER(SizeIsAligned(size, fl->alignment));
|
||||
AVER(SizeIsAligned(size, freelistAlignment(fl)));
|
||||
AVERT(FindDelete, findDelete);
|
||||
AVER(prev == NULL || FreelistBlockNext(prev) == block);
|
||||
AVERT(FreelistBlock, block);
|
||||
|
|
@ -445,15 +475,18 @@ static void freelistFindDeleteFromBlock(Range rangeReturn, Range oldRangeReturn,
|
|||
}
|
||||
|
||||
|
||||
Bool FreelistFindFirst(Range rangeReturn, Range oldRangeReturn,
|
||||
Freelist fl, Size size, FindDelete findDelete)
|
||||
static Bool freelistFindFirst(Range rangeReturn, Range oldRangeReturn,
|
||||
Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
Freelist fl;
|
||||
FreelistBlock prev, cur, next;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
fl = freelistOfLand(land);
|
||||
AVERT(Freelist, fl);
|
||||
AVER(SizeIsAligned(size, fl->alignment));
|
||||
AVER(SizeIsAligned(size, freelistAlignment(fl)));
|
||||
AVERT(FindDelete, findDelete);
|
||||
|
||||
prev = NULL;
|
||||
|
|
@ -473,17 +506,20 @@ Bool FreelistFindFirst(Range rangeReturn, Range oldRangeReturn,
|
|||
}
|
||||
|
||||
|
||||
Bool FreelistFindLast(Range rangeReturn, Range oldRangeReturn,
|
||||
Freelist fl, Size size, FindDelete findDelete)
|
||||
static Bool freelistFindLast(Range rangeReturn, Range oldRangeReturn,
|
||||
Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
Freelist fl;
|
||||
Bool found = FALSE;
|
||||
FreelistBlock prev, cur, next;
|
||||
FreelistBlock foundPrev = NULL, foundCur = NULL;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
fl = freelistOfLand(land);
|
||||
AVERT(Freelist, fl);
|
||||
AVER(SizeIsAligned(size, fl->alignment));
|
||||
AVER(SizeIsAligned(size, freelistAlignment(fl)));
|
||||
AVERT(FindDelete, findDelete);
|
||||
|
||||
prev = NULL;
|
||||
|
|
@ -507,15 +543,18 @@ Bool FreelistFindLast(Range rangeReturn, Range oldRangeReturn,
|
|||
}
|
||||
|
||||
|
||||
Bool FreelistFindLargest(Range rangeReturn, Range oldRangeReturn,
|
||||
Freelist fl, Size size, FindDelete findDelete)
|
||||
static Bool freelistFindLargest(Range rangeReturn, Range oldRangeReturn,
|
||||
Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
Freelist fl;
|
||||
Bool found = FALSE;
|
||||
FreelistBlock prev, cur, next;
|
||||
FreelistBlock bestPrev = NULL, bestCur = NULL;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
fl = freelistOfLand(land);
|
||||
AVERT(Freelist, fl);
|
||||
AVERT(FindDelete, findDelete);
|
||||
|
||||
|
|
@ -541,19 +580,21 @@ Bool FreelistFindLargest(Range rangeReturn, Range oldRangeReturn,
|
|||
}
|
||||
|
||||
|
||||
/* freelistDescribeIterateMethod -- Iterate method for
|
||||
* FreelistDescribe. Writes a decription of the range into the stream
|
||||
* pointed to by 'closureP'.
|
||||
/* freelistDescribeVisitor -- visitor method for freelistDescribe.
|
||||
*
|
||||
* Writes a decription of the range into the stream pointed to by
|
||||
* closureP.
|
||||
*/
|
||||
static Bool freelistDescribeIterateMethod(Bool *deleteReturn, Range range,
|
||||
void *closureP, Size closureS)
|
||||
static Bool freelistDescribeVisitor(Bool *deleteReturn, Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
Res res;
|
||||
mps_lib_FILE *stream = closureP;
|
||||
|
||||
AVER(deleteReturn != NULL);
|
||||
AVERT(Range, range);
|
||||
AVER(stream != NULL);
|
||||
if (deleteReturn == NULL) return FALSE;
|
||||
if (!TESTT(Land, land)) return FALSE;
|
||||
if (!TESTT(Range, range)) return FALSE;
|
||||
if (stream == NULL) return FALSE;
|
||||
UNUSED(closureS);
|
||||
|
||||
res = WriteF(stream,
|
||||
|
|
@ -562,64 +603,48 @@ static Bool freelistDescribeIterateMethod(Bool *deleteReturn, Range range,
|
|||
" {$U}\n", (WriteFU)RangeSize(range),
|
||||
NULL);
|
||||
|
||||
*deleteReturn = FALSE;
|
||||
return res == ResOK;
|
||||
}
|
||||
|
||||
|
||||
Res FreelistDescribe(Freelist fl, mps_lib_FILE *stream)
|
||||
static Res freelistDescribe(Land land, mps_lib_FILE *stream)
|
||||
{
|
||||
Freelist fl;
|
||||
Res res;
|
||||
|
||||
if (!TESTT(Land, land)) return ResFAIL;
|
||||
fl = freelistOfLand(land);
|
||||
if (!TESTT(Freelist, fl)) return ResFAIL;
|
||||
if (stream == NULL) return ResFAIL;
|
||||
|
||||
res = WriteF(stream,
|
||||
"Freelist $P {\n", (WriteFP)fl,
|
||||
" alignment = $U\n", (WriteFU)fl->alignment,
|
||||
" listSize = $U\n", (WriteFU)fl->listSize,
|
||||
NULL);
|
||||
|
||||
FreelistIterate(fl, freelistDescribeIterateMethod, stream, 0);
|
||||
LandIterate(land, freelistDescribeVisitor, stream, 0);
|
||||
|
||||
res = WriteF(stream, "}\n", NULL);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* freelistFlushIterateMethod -- Iterate method for
|
||||
* FreelistFlushToLand. Attempst to insert the range into the Land.
|
||||
*/
|
||||
static Bool freelistFlushIterateMethod(Bool *deleteReturn, Range range,
|
||||
void *closureP, Size closureS)
|
||||
typedef LandClassStruct FreelistLandClassStruct;
|
||||
|
||||
DEFINE_CLASS(FreelistLandClass, class)
|
||||
{
|
||||
Res res;
|
||||
RangeStruct newRange;
|
||||
Land land;
|
||||
|
||||
AVER(deleteReturn != NULL);
|
||||
AVERT(Range, range);
|
||||
AVER(closureP != NULL);
|
||||
UNUSED(closureS);
|
||||
|
||||
land = closureP;
|
||||
res = LandInsert(&newRange, land, range);
|
||||
if (res == ResOK) {
|
||||
*deleteReturn = TRUE;
|
||||
return TRUE;
|
||||
} else {
|
||||
*deleteReturn = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FreelistFlushToLand(Freelist fl, Land land)
|
||||
{
|
||||
AVERT(Freelist, fl);
|
||||
AVERT(Land, land);
|
||||
|
||||
FreelistIterate(fl, freelistFlushIterateMethod, land, 0);
|
||||
INHERIT_CLASS(class, LandClass);
|
||||
class->name = "FREELIST";
|
||||
class->size = sizeof(FreelistStruct);
|
||||
class->init = freelistInit;
|
||||
class->finish = freelistFinish;
|
||||
class->insert = freelistInsert;
|
||||
class->delete = freelistDelete;
|
||||
class->iterate = freelistIterate;
|
||||
class->findFirst = freelistFindFirst;
|
||||
class->findLast = freelistFindLast;
|
||||
class->findLargest = freelistFindLargest;
|
||||
class->describe = freelistDescribe;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -10,42 +10,10 @@
|
|||
#define freelist_h
|
||||
|
||||
#include "mpmtypes.h"
|
||||
#include "range.h"
|
||||
|
||||
#define FreelistSig ((Sig)0x519F6331) /* SIGnature FREEL */
|
||||
extern Bool FreelistCheck(Freelist freelist);
|
||||
|
||||
typedef struct FreelistStruct *Freelist;
|
||||
typedef union FreelistBlockUnion *FreelistBlock;
|
||||
|
||||
typedef Bool (*FreelistIterateMethod)(Bool *deleteReturn, Range range,
|
||||
void *closureP, Size closureS);
|
||||
|
||||
typedef struct FreelistStruct {
|
||||
Sig sig;
|
||||
Align alignment;
|
||||
FreelistBlock list;
|
||||
Count listSize;
|
||||
} FreelistStruct;
|
||||
|
||||
extern Bool FreelistCheck(Freelist fl);
|
||||
extern Res FreelistInit(Freelist fl, Align alignment);
|
||||
extern void FreelistFinish(Freelist fl);
|
||||
|
||||
extern Res FreelistInsert(Range rangeReturn, Freelist fl, Range range);
|
||||
extern Res FreelistDelete(Range rangeReturn, Freelist fl, Range range);
|
||||
extern Res FreelistDescribe(Freelist fl, mps_lib_FILE *stream);
|
||||
|
||||
extern void FreelistIterate(Freelist abq, FreelistIterateMethod iterate,
|
||||
void *closureP, Size closureS);
|
||||
|
||||
extern Bool FreelistFindFirst(Range rangeReturn, Range oldRangeReturn,
|
||||
Freelist fl, Size size, FindDelete findDelete);
|
||||
extern Bool FreelistFindLast(Range rangeReturn, Range oldRangeReturn,
|
||||
Freelist fl, Size size, FindDelete findDelete);
|
||||
extern Bool FreelistFindLargest(Range rangeReturn, Range oldRangeReturn,
|
||||
Freelist fl, Size size, FindDelete findDelete);
|
||||
|
||||
extern void FreelistFlushToLand(Freelist fl, Land land);
|
||||
extern FreelistLandClass FreelistLandClassGet(void);
|
||||
|
||||
#endif /* freelist.h */
|
||||
|
||||
|
|
|
|||
122
mps/code/land.c
122
mps/code/land.c
|
|
@ -12,6 +12,8 @@
|
|||
SRCID(land, "$Id$");
|
||||
|
||||
|
||||
/* LandCheck -- check land */
|
||||
|
||||
Bool LandCheck(Land land)
|
||||
{
|
||||
CHECKS(Land, land);
|
||||
|
|
@ -20,6 +22,12 @@ Bool LandCheck(Land land)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* LandInit -- initialize land
|
||||
*
|
||||
* See <design/land/#function.init>
|
||||
*/
|
||||
|
||||
Res LandInit(Land land, LandClass class, Arena arena, Align alignment, void *owner, ArgList args)
|
||||
{
|
||||
Res res;
|
||||
|
|
@ -47,6 +55,12 @@ Res LandInit(Land land, LandClass class, Arena arena, Align alignment, void *own
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* LandCreate -- allocate and initialize land
|
||||
*
|
||||
* See <design/land/#function.create>
|
||||
*/
|
||||
|
||||
Res LandCreate(Land *landReturn, Arena arena, LandClass class, Align alignment, void *owner, ArgList args)
|
||||
{
|
||||
Res res;
|
||||
|
|
@ -76,6 +90,12 @@ failAlloc:
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* LandDestroy -- finish and deallocate land
|
||||
*
|
||||
* See <design/land/#function.destroy>
|
||||
*/
|
||||
|
||||
void LandDestroy(Land land)
|
||||
{
|
||||
Arena arena;
|
||||
|
|
@ -89,12 +109,27 @@ void LandDestroy(Land land)
|
|||
ControlFree(arena, land, class->size);
|
||||
}
|
||||
|
||||
|
||||
/* LandFinish -- finish land
|
||||
*
|
||||
* See <design/land/#function.finish>
|
||||
*/
|
||||
|
||||
void LandFinish(Land land)
|
||||
{
|
||||
AVERT(Land, land);
|
||||
|
||||
(*land->class->finish)(land);
|
||||
|
||||
land->sig = SigInvalid;
|
||||
}
|
||||
|
||||
|
||||
/* LandInsert -- insert range of addresses into land
|
||||
*
|
||||
* See <design/land/#function.insert>
|
||||
*/
|
||||
|
||||
Res LandInsert(Range rangeReturn, Land land, Range range)
|
||||
{
|
||||
AVER(rangeReturn != NULL);
|
||||
|
|
@ -105,6 +140,12 @@ Res LandInsert(Range rangeReturn, Land land, Range range)
|
|||
return (*land->class->insert)(rangeReturn, land, range);
|
||||
}
|
||||
|
||||
|
||||
/* LandDelete -- delete range of addresses from land
|
||||
*
|
||||
* See <design/land/#function.delete>
|
||||
*/
|
||||
|
||||
Res LandDelete(Range rangeReturn, Land land, Range range)
|
||||
{
|
||||
AVER(rangeReturn != NULL);
|
||||
|
|
@ -115,6 +156,12 @@ Res LandDelete(Range rangeReturn, Land land, Range range)
|
|||
return (*land->class->delete)(rangeReturn, land, range);
|
||||
}
|
||||
|
||||
|
||||
/* LandIterate -- iterate over isolated ranges of addresses in land
|
||||
*
|
||||
* See <design/land/#function.iterate>
|
||||
*/
|
||||
|
||||
void LandIterate(Land land, LandVisitor visitor, void *closureP, Size closureS)
|
||||
{
|
||||
AVERT(Land, land);
|
||||
|
|
@ -123,6 +170,12 @@ void LandIterate(Land land, LandVisitor visitor, void *closureP, Size closureS)
|
|||
(*land->class->iterate)(land, visitor, closureP, closureS);
|
||||
}
|
||||
|
||||
|
||||
/* LandFindFirst -- find first range of given size
|
||||
*
|
||||
* See <design/land/#function.find.first>
|
||||
*/
|
||||
|
||||
Bool LandFindFirst(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
AVER(rangeReturn != NULL);
|
||||
|
|
@ -135,6 +188,12 @@ Bool LandFindFirst(Range rangeReturn, Range oldRangeReturn, Land land, Size size
|
|||
findDelete);
|
||||
}
|
||||
|
||||
|
||||
/* LandFindLast -- find last range of given size
|
||||
*
|
||||
* See <design/land/#function.find.last>
|
||||
*/
|
||||
|
||||
Bool LandFindLast(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
AVER(rangeReturn != NULL);
|
||||
|
|
@ -147,6 +206,12 @@ Bool LandFindLast(Range rangeReturn, Range oldRangeReturn, Land land, Size size,
|
|||
findDelete);
|
||||
}
|
||||
|
||||
|
||||
/* LandFindLargest -- find largest range of at least given size
|
||||
*
|
||||
* See <design/land/#function.find.largest>
|
||||
*/
|
||||
|
||||
Bool LandFindLargest(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
AVER(rangeReturn != NULL);
|
||||
|
|
@ -159,6 +224,12 @@ Bool LandFindLargest(Range rangeReturn, Range oldRangeReturn, Land land, Size si
|
|||
findDelete);
|
||||
}
|
||||
|
||||
|
||||
/* LandFindInSize -- find range of given size in set of zones
|
||||
*
|
||||
* See <design/land/#function.find.zones>
|
||||
*/
|
||||
|
||||
Res LandFindInZones(Range rangeReturn, Range oldRangeReturn, Land land, Size size, ZoneSet zoneSet, Bool high)
|
||||
{
|
||||
AVER(rangeReturn != NULL);
|
||||
|
|
@ -172,6 +243,12 @@ Res LandFindInZones(Range rangeReturn, Range oldRangeReturn, Land land, Size siz
|
|||
zoneSet, high);
|
||||
}
|
||||
|
||||
|
||||
/* LandDescribe -- describe land for debugging
|
||||
*
|
||||
* See <design/land/#function.describe>
|
||||
*/
|
||||
|
||||
Res LandDescribe(Land land, mps_lib_FILE *stream)
|
||||
{
|
||||
Res res;
|
||||
|
|
@ -198,6 +275,51 @@ Res LandDescribe(Land land, mps_lib_FILE *stream)
|
|||
}
|
||||
|
||||
|
||||
/* landFlushVisitor -- visitor for LandFlush.
|
||||
*
|
||||
* closureP argument is the destination Land. Attempt to insert the
|
||||
* range into the destination.
|
||||
*/
|
||||
static Bool landFlushVisitor(Bool *deleteReturn, Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
Res res;
|
||||
RangeStruct newRange;
|
||||
Land dest;
|
||||
|
||||
AVER(deleteReturn != NULL);
|
||||
AVERT(Range, range);
|
||||
AVER(closureP != NULL);
|
||||
UNUSED(closureS);
|
||||
|
||||
dest = closureP;
|
||||
res = LandInsert(&newRange, land, range);
|
||||
if (res == ResOK) {
|
||||
*deleteReturn = TRUE;
|
||||
return TRUE;
|
||||
} else {
|
||||
*deleteReturn = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* LandFlush -- move ranges from src to dest
|
||||
*
|
||||
* See <design/land/#function.flush>
|
||||
*/
|
||||
|
||||
void LandFlush(Land dest, Land src)
|
||||
{
|
||||
AVERT(Land, dest);
|
||||
AVERT(Land, src);
|
||||
|
||||
LandIterate(src, landFlushVisitor, dest, 0);
|
||||
}
|
||||
|
||||
|
||||
/* LandClassCheck -- check land class */
|
||||
|
||||
Bool LandClassCheck(LandClass class)
|
||||
{
|
||||
CHECKL(ProtocolClassCheck(&class->protocol));
|
||||
|
|
|
|||
|
|
@ -1,19 +1,16 @@
|
|||
/* fbmtest.c: FREE BLOCK MANAGEMENT TEST
|
||||
/* landtest.c: LAND TEST
|
||||
*
|
||||
* $Id$
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* The MPS contains two free block management modules:
|
||||
* The MPS contains two land implementations:
|
||||
*
|
||||
* 1. the CBS (Coalescing Block Structure) module maintains free
|
||||
* blocks in a splay tree for fast access with a cost in storage;
|
||||
* 1. the CBS (Coalescing Block Structure) module maintains blocks in
|
||||
* a splay tree for fast access with a cost in storage;
|
||||
*
|
||||
* 2. the Freelist module maintains free blocks in an address-ordered
|
||||
* 2. the Freelist module maintains blocks in an address-ordered
|
||||
* singly linked list for zero storage overhead with a cost in
|
||||
* performance.
|
||||
*
|
||||
* The two modules present identical interfaces, so we apply the same
|
||||
* test cases to both.
|
||||
*/
|
||||
|
||||
#include "cbs.h"
|
||||
|
|
@ -28,7 +25,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
SRCID(fbmtest, "$Id$");
|
||||
SRCID(landtest, "$Id$");
|
||||
|
||||
|
||||
#define ArraySize ((Size)123456)
|
||||
|
|
@ -43,64 +40,46 @@ static Count NAllocateTried, NAllocateSucceeded, NDeallocateTried,
|
|||
|
||||
static int verbose = 0;
|
||||
|
||||
typedef unsigned FBMType;
|
||||
enum {
|
||||
FBMTypeCBS = 1,
|
||||
FBMTypeFreelist,
|
||||
FBMTypeLimit
|
||||
};
|
||||
|
||||
typedef struct FBMStateStruct {
|
||||
FBMType type;
|
||||
typedef struct TestStateStruct {
|
||||
Align align;
|
||||
BT allocTable;
|
||||
Addr block;
|
||||
union {
|
||||
Land land;
|
||||
Freelist fl;
|
||||
} the;
|
||||
} FBMStateStruct, *FBMState;
|
||||
Land land;
|
||||
} TestStateStruct, *TestState;
|
||||
|
||||
typedef struct CheckFBMClosureStruct {
|
||||
FBMState state;
|
||||
typedef struct CheckTestClosureStruct {
|
||||
TestState state;
|
||||
Addr limit;
|
||||
Addr oldLimit;
|
||||
} CheckFBMClosureStruct, *CheckFBMClosure;
|
||||
} CheckTestClosureStruct, *CheckTestClosure;
|
||||
|
||||
|
||||
static Addr (addrOfIndex)(FBMState state, Index i)
|
||||
static Addr (addrOfIndex)(TestState state, Index i)
|
||||
{
|
||||
return AddrAdd(state->block, (i * state->align));
|
||||
}
|
||||
|
||||
|
||||
static Index (indexOfAddr)(FBMState state, Addr a)
|
||||
static Index (indexOfAddr)(TestState state, Addr a)
|
||||
{
|
||||
return (Index)(AddrOffset(state->block, a) / state->align);
|
||||
}
|
||||
|
||||
|
||||
static void describe(FBMState state) {
|
||||
switch (state->type) {
|
||||
case FBMTypeCBS:
|
||||
die(LandDescribe(state->the.land, mps_lib_get_stdout()), "LandDescribe");
|
||||
break;
|
||||
case FBMTypeFreelist:
|
||||
die(FreelistDescribe(state->the.fl, mps_lib_get_stdout()), "FreelistDescribe");
|
||||
break;
|
||||
default:
|
||||
cdie(0, "invalid state->type");
|
||||
break;
|
||||
}
|
||||
static void describe(TestState state) {
|
||||
die(LandDescribe(state->land, mps_lib_get_stdout()), "LandDescribe");
|
||||
}
|
||||
|
||||
|
||||
static Bool checkCallback(Range range, void *closureP, Size closureS)
|
||||
static Bool checkVisitor(Bool *deleteReturn, Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
Addr base, limit;
|
||||
CheckFBMClosure cl = (CheckFBMClosure)closureP;
|
||||
CheckTestClosure cl = closureP;
|
||||
|
||||
UNUSED(closureS);
|
||||
Insist(deleteReturn != NULL);
|
||||
testlib_unused(land);
|
||||
testlib_unused(closureS);
|
||||
Insist(cl != NULL);
|
||||
|
||||
base = RangeBase(range);
|
||||
|
|
@ -124,42 +103,15 @@ static Bool checkCallback(Range range, void *closureP, Size closureS)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static Bool checkCBSCallback(Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
static void check(TestState state)
|
||||
{
|
||||
UNUSED(land);
|
||||
return checkCallback(range, closureP, closureS);
|
||||
}
|
||||
|
||||
|
||||
static Bool checkFLCallback(Bool *deleteReturn, Range range,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
*deleteReturn = FALSE;
|
||||
return checkCallback(range, closureP, closureS);
|
||||
}
|
||||
|
||||
|
||||
static void check(FBMState state)
|
||||
{
|
||||
CheckFBMClosureStruct closure;
|
||||
CheckTestClosureStruct closure;
|
||||
|
||||
closure.state = state;
|
||||
closure.limit = addrOfIndex(state, ArraySize);
|
||||
closure.oldLimit = state->block;
|
||||
|
||||
switch (state->type) {
|
||||
case FBMTypeCBS:
|
||||
LandIterate(state->the.land, checkCBSCallback, (void *)&closure, 0);
|
||||
break;
|
||||
case FBMTypeFreelist:
|
||||
FreelistIterate(state->the.fl, checkFLCallback, (void *)&closure, 0);
|
||||
break;
|
||||
default:
|
||||
cdie(0, "invalid state->type");
|
||||
return;
|
||||
}
|
||||
LandIterate(state->land, checkVisitor, (void *)&closure, 0);
|
||||
|
||||
if (closure.oldLimit == state->block)
|
||||
Insist(BTIsSetRange(state->allocTable, 0,
|
||||
|
|
@ -245,7 +197,7 @@ static Index lastEdge(BT bt, Size size, Index base)
|
|||
* all either set or reset.
|
||||
*/
|
||||
|
||||
static void randomRange(Addr *baseReturn, Addr *limitReturn, FBMState state)
|
||||
static void randomRange(Addr *baseReturn, Addr *limitReturn, TestState state)
|
||||
{
|
||||
Index base; /* the start of our range */
|
||||
Index end; /* an edge (i.e. different from its predecessor) */
|
||||
|
|
@ -267,7 +219,7 @@ static void randomRange(Addr *baseReturn, Addr *limitReturn, FBMState state)
|
|||
}
|
||||
|
||||
|
||||
static void allocate(FBMState state, Addr base, Addr limit)
|
||||
static void allocate(TestState state, Addr base, Addr limit)
|
||||
{
|
||||
Res res;
|
||||
Index ib, il; /* Indexed for base and limit */
|
||||
|
|
@ -295,25 +247,15 @@ static void allocate(FBMState state, Addr base, Addr limit)
|
|||
total = AddrOffset(outerBase, outerLimit);
|
||||
|
||||
/* TODO: check these values */
|
||||
UNUSED(left);
|
||||
UNUSED(right);
|
||||
UNUSED(total);
|
||||
testlib_unused(left);
|
||||
testlib_unused(right);
|
||||
testlib_unused(total);
|
||||
} else {
|
||||
outerBase = outerLimit = NULL;
|
||||
}
|
||||
|
||||
RangeInit(&range, base, limit);
|
||||
switch (state->type) {
|
||||
case FBMTypeCBS:
|
||||
res = LandDelete(&oldRange, state->the.land, &range);
|
||||
break;
|
||||
case FBMTypeFreelist:
|
||||
res = FreelistDelete(&oldRange, state->the.fl, &range);
|
||||
break;
|
||||
default:
|
||||
cdie(0, "invalid state->type");
|
||||
return;
|
||||
}
|
||||
res = LandDelete(&oldRange, state->land, &range);
|
||||
|
||||
if (verbose) {
|
||||
printf("allocate: [%p,%p) -- %s\n",
|
||||
|
|
@ -335,7 +277,7 @@ static void allocate(FBMState state, Addr base, Addr limit)
|
|||
}
|
||||
|
||||
|
||||
static void deallocate(FBMState state, Addr base, Addr limit)
|
||||
static void deallocate(TestState state, Addr base, Addr limit)
|
||||
{
|
||||
Res res;
|
||||
Index ib, il;
|
||||
|
|
@ -373,23 +315,13 @@ static void deallocate(FBMState state, Addr base, Addr limit)
|
|||
total = AddrOffset(outerBase, outerLimit);
|
||||
|
||||
/* TODO: check these values */
|
||||
UNUSED(left);
|
||||
UNUSED(right);
|
||||
UNUSED(total);
|
||||
testlib_unused(left);
|
||||
testlib_unused(right);
|
||||
testlib_unused(total);
|
||||
}
|
||||
|
||||
RangeInit(&range, base, limit);
|
||||
switch (state->type) {
|
||||
case FBMTypeCBS:
|
||||
res = LandInsert(&freeRange, state->the.land, &range);
|
||||
break;
|
||||
case FBMTypeFreelist:
|
||||
res = FreelistInsert(&freeRange, state->the.fl, &range);
|
||||
break;
|
||||
default:
|
||||
cdie(0, "invalid state->type");
|
||||
return;
|
||||
}
|
||||
res = LandInsert(&freeRange, state->land, &range);
|
||||
|
||||
if (verbose) {
|
||||
printf("deallocate: [%p,%p) -- %s\n",
|
||||
|
|
@ -412,7 +344,7 @@ static void deallocate(FBMState state, Addr base, Addr limit)
|
|||
}
|
||||
|
||||
|
||||
static void find(FBMState state, Size size, Bool high, FindDelete findDelete)
|
||||
static void find(TestState state, Size size, Bool high, FindDelete findDelete)
|
||||
{
|
||||
Bool expected, found;
|
||||
Index expectedBase, expectedLimit;
|
||||
|
|
@ -453,23 +385,12 @@ static void find(FBMState state, Size size, Bool high, FindDelete findDelete)
|
|||
}
|
||||
|
||||
/* TODO: check these values */
|
||||
UNUSED(oldSize);
|
||||
UNUSED(newSize);
|
||||
testlib_unused(oldSize);
|
||||
testlib_unused(newSize);
|
||||
}
|
||||
|
||||
switch (state->type) {
|
||||
case FBMTypeCBS:
|
||||
found = (high ? LandFindLast : LandFindFirst)
|
||||
(&foundRange, &oldRange, state->the.land, size * state->align, findDelete);
|
||||
break;
|
||||
case FBMTypeFreelist:
|
||||
found = (high ? FreelistFindLast : FreelistFindFirst)
|
||||
(&foundRange, &oldRange, state->the.fl, size * state->align, findDelete);
|
||||
break;
|
||||
default:
|
||||
cdie(0, "invalid state->type");
|
||||
return;
|
||||
}
|
||||
found = (high ? LandFindLast : LandFindFirst)
|
||||
(&foundRange, &oldRange, state->land, size * state->align, findDelete);
|
||||
|
||||
if (verbose) {
|
||||
printf("find %s %lu: ", high ? "last" : "first",
|
||||
|
|
@ -505,7 +426,7 @@ static void find(FBMState state, Size size, Bool high, FindDelete findDelete)
|
|||
return;
|
||||
}
|
||||
|
||||
static void test(FBMState state, unsigned n) {
|
||||
static void test(TestState state, unsigned n) {
|
||||
Addr base, limit;
|
||||
unsigned i;
|
||||
Size size;
|
||||
|
|
@ -538,7 +459,7 @@ static void test(FBMState state, unsigned n) {
|
|||
find(state, size, high, findDelete);
|
||||
break;
|
||||
default:
|
||||
cdie(0, "invalid state->type");
|
||||
cdie(0, "invalid rnd(3)");
|
||||
return;
|
||||
}
|
||||
if ((i + 1) % 1000 == 0)
|
||||
|
|
@ -551,14 +472,14 @@ static void test(FBMState state, unsigned n) {
|
|||
extern int main(int argc, char *argv[])
|
||||
{
|
||||
mps_arena_t mpsArena;
|
||||
Arena arena; /* the ANSI arena which we use to allocate the BT */
|
||||
FBMStateStruct state;
|
||||
Arena arena;
|
||||
TestStateStruct state;
|
||||
void *p;
|
||||
Addr dummyBlock;
|
||||
BT allocTable;
|
||||
FreelistStruct flStruct;
|
||||
CBSStruct cbsStruct;
|
||||
Land land = &cbsStruct.landStruct;
|
||||
FreelistStruct flStruct;
|
||||
Land land;
|
||||
Align align;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
|
@ -586,25 +507,26 @@ extern int main(int argc, char *argv[])
|
|||
(char *)dummyBlock + ArraySize);
|
||||
}
|
||||
|
||||
land = &cbsStruct.landStruct;
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, CBSFastFind, TRUE);
|
||||
die((mps_res_t)LandInit(land, CBSLandClassGet(), arena, align, NULL, args),
|
||||
"failed to initialise CBS");
|
||||
} MPS_ARGS_END(args);
|
||||
state.type = FBMTypeCBS;
|
||||
state.align = align;
|
||||
state.block = dummyBlock;
|
||||
state.allocTable = allocTable;
|
||||
state.the.land = land;
|
||||
state.land = land;
|
||||
test(&state, nCBSOperations);
|
||||
LandFinish(land);
|
||||
|
||||
die((mps_res_t)FreelistInit(&flStruct, align),
|
||||
land = &flStruct.landStruct;
|
||||
die((mps_res_t)LandInit(land, FreelistLandClassGet(), arena, align, NULL,
|
||||
mps_args_none),
|
||||
"failed to initialise Freelist");
|
||||
state.type = FBMTypeFreelist;
|
||||
state.the.fl = &flStruct;
|
||||
state.land = land;
|
||||
test(&state, nFLOperations);
|
||||
FreelistFinish(&flStruct);
|
||||
LandFinish(land);
|
||||
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
|
|
@ -1010,6 +1010,7 @@ extern Bool LandFindLast(Range rangeReturn, Range oldRangeReturn, Land land, Siz
|
|||
extern Bool LandFindLargest(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete);
|
||||
extern Res LandFindInZones(Range rangeReturn, Range oldRangeReturn, Land land, Size size, ZoneSet zoneSet, Bool high);
|
||||
extern Res LandDescribe(Land land, mps_lib_FILE *stream);
|
||||
extern void LandFlush(Land dest, Land src);
|
||||
|
||||
extern Bool LandClassCheck(LandClass class);
|
||||
extern LandClass LandClassGet(void);
|
||||
|
|
|
|||
|
|
@ -665,10 +665,28 @@ typedef struct CBSStruct {
|
|||
Bool ownPool; /* did we create blockPool? */
|
||||
/* meters for sizes of search structures at each op */
|
||||
METER_DECL(treeSearch);
|
||||
Sig sig; /* sig at end because embedded */
|
||||
Sig sig; /* .class.end-sig */
|
||||
} CBSStruct;
|
||||
|
||||
|
||||
/* FreelistStruct -- address-ordered freelist
|
||||
*
|
||||
* Freelist is a subclass of Land that maintains a collection of
|
||||
* disjoint ranges in an address-ordered freelist.
|
||||
*
|
||||
* See <code/freelist.c>.
|
||||
*/
|
||||
|
||||
#define FreelistSig ((Sig)0x519F6331) /* SIGnature FREEL */
|
||||
|
||||
typedef struct FreelistStruct {
|
||||
LandStruct landStruct; /* superclass fields come first */
|
||||
FreelistBlock list;
|
||||
Count listSize;
|
||||
Sig sig; /* .class.end-sig */
|
||||
} FreelistStruct;
|
||||
|
||||
|
||||
/* ArenaStruct -- generic arena
|
||||
*
|
||||
* See <code/arena.c>. */
|
||||
|
|
|
|||
|
|
@ -112,10 +112,12 @@ typedef struct StackContextStruct *StackContext;
|
|||
typedef struct RangeStruct *Range; /* <design/range/> */
|
||||
typedef struct LandStruct *Land; /* <design/land/> */
|
||||
typedef struct LandClassStruct *LandClass; /* <design/land/> */
|
||||
typedef unsigned FindDelete; /* <design/land/> */
|
||||
typedef LandClass CBSLandClass; /* <design/cbs/> */
|
||||
typedef struct CBSStruct *CBS; /* <design/cbs/> */
|
||||
typedef LandClass FreelistClass; /* <design/freelist/> */
|
||||
typedef unsigned FindDelete; /* <design/land/> */
|
||||
typedef LandClass FreelistLandClass; /* <design/freelist/> */
|
||||
typedef struct FreelistStruct *Freelist; /* <design/freelist/> */
|
||||
typedef union FreelistBlockUnion *FreelistBlock; /* <code/freelist.c> */
|
||||
|
||||
|
||||
/* Arena*Method -- see <code/mpmst.h#ArenaClassStruct> */
|
||||
|
|
@ -274,7 +276,7 @@ typedef Res (*LandInitMethod)(Land land, ArgList args);
|
|||
typedef void (*LandFinishMethod)(Land land);
|
||||
typedef Res (*LandInsertMethod)(Range rangeReturn, Land land, Range range);
|
||||
typedef Res (*LandDeleteMethod)(Range rangeReturn, Land land, Range range);
|
||||
typedef Bool (*LandVisitor)(Land land, Range range, void *closureP, Size closureS);
|
||||
typedef Bool (*LandVisitor)(Bool *deleteReturn, Land land, Range range, void *closureP, Size closureS);
|
||||
typedef void (*LandIterateMethod)(Land land, LandVisitor visitor, void *closureP, Size closureS);
|
||||
typedef Bool (*LandFindMethod)(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete);
|
||||
typedef Res (*LandFindInZonesMethod)(Range rangeReturn, Range oldRangeReturn, Land land, Size size, ZoneSet zoneSet, Bool high);
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@
|
|||
2291A5DB175CB05F001D4920 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
2291A5DD175CB05F001D4920 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
2291A5E4175CB076001D4920 /* exposet0.c in Sources */ = {isa = PBXBuildFile; fileRef = 2291A5AA175CAA9B001D4920 /* exposet0.c */; };
|
||||
2291A5ED175CB5E2001D4920 /* fbmtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 2291A5E9175CB4EC001D4920 /* fbmtest.c */; };
|
||||
2291A5ED175CB5E2001D4920 /* landtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 2291A5E9175CB4EC001D4920 /* landtest.c */; };
|
||||
22B2BC2E18B6434F00C33E63 /* mps.c in Sources */ = {isa = PBXBuildFile; fileRef = 31A47BA3156C1E130039B1C2 /* mps.c */; };
|
||||
22B2BC3718B6437C00C33E63 /* scheme-advanced.c in Sources */ = {isa = PBXBuildFile; fileRef = 22B2BC2B18B6434000C33E63 /* scheme-advanced.c */; };
|
||||
22FA176916E8D6FC0098B23F /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; };
|
||||
|
|
@ -659,7 +659,7 @@
|
|||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 3114A64B156E9596001E0AA3;
|
||||
remoteInfo = fbmtest;
|
||||
remoteInfo = landtest;
|
||||
};
|
||||
3114A674156E9619001E0AA3 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
|
|
@ -1249,7 +1249,7 @@
|
|||
2291A5BD175CAB2F001D4920 /* awlutth */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = awlutth; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
2291A5D1175CAFCA001D4920 /* expt825 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = expt825; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
2291A5E3175CB05F001D4920 /* exposet0 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = exposet0; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
2291A5E9175CB4EC001D4920 /* fbmtest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fbmtest.c; sourceTree = "<group>"; };
|
||||
2291A5E9175CB4EC001D4920 /* landtest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = landtest.c; sourceTree = "<group>"; };
|
||||
2291A5EA175CB503001D4920 /* abq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abq.h; sourceTree = "<group>"; };
|
||||
2291A5EB175CB53E001D4920 /* range.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = range.c; sourceTree = "<group>"; };
|
||||
2291A5EC175CB53E001D4920 /* range.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = range.h; sourceTree = "<group>"; };
|
||||
|
|
@ -1299,7 +1299,7 @@
|
|||
3114A633156E94DB001E0AA3 /* abqtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = abqtest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3114A63D156E94EA001E0AA3 /* abqtest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abqtest.c; sourceTree = "<group>"; };
|
||||
3114A645156E9525001E0AA3 /* abq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abq.c; sourceTree = "<group>"; };
|
||||
3114A64C156E9596001E0AA3 /* fbmtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fbmtest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3114A64C156E9596001E0AA3 /* landtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = landtest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3114A662156E95D9001E0AA3 /* btcv */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = btcv; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3114A66C156E95EB001E0AA3 /* btcv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = btcv.c; sourceTree = "<group>"; };
|
||||
3114A67C156E9668001E0AA3 /* mv2test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mv2test; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
|
@ -2004,7 +2004,7 @@
|
|||
3114A613156E944A001E0AA3 /* bttest.c */,
|
||||
2291A5AA175CAA9B001D4920 /* exposet0.c */,
|
||||
2291A5AB175CAA9B001D4920 /* expt825.c */,
|
||||
2291A5E9175CB4EC001D4920 /* fbmtest.c */,
|
||||
2291A5E9175CB4EC001D4920 /* landtest.c */,
|
||||
3114A5CD156E9369001E0AA3 /* finalcv.c */,
|
||||
3114A5E5156E93B9001E0AA3 /* finaltest.c */,
|
||||
3124CAC6156BE48D00753214 /* fmtdy.c */,
|
||||
|
|
@ -2100,7 +2100,7 @@
|
|||
3114A605156E9430001E0AA3 /* bttest */,
|
||||
3114A61C156E9485001E0AA3 /* teletest */,
|
||||
3114A633156E94DB001E0AA3 /* abqtest */,
|
||||
3114A64C156E9596001E0AA3 /* fbmtest */,
|
||||
3114A64C156E9596001E0AA3 /* landtest */,
|
||||
3114A662156E95D9001E0AA3 /* btcv */,
|
||||
3114A67C156E9668001E0AA3 /* mv2test */,
|
||||
3114A695156E971B001E0AA3 /* messtest */,
|
||||
|
|
@ -2725,9 +2725,9 @@
|
|||
productReference = 3114A633156E94DB001E0AA3 /* abqtest */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
3114A64B156E9596001E0AA3 /* fbmtest */ = {
|
||||
3114A64B156E9596001E0AA3 /* landtest */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 3114A653156E9596001E0AA3 /* Build configuration list for PBXNativeTarget "fbmtest" */;
|
||||
buildConfigurationList = 3114A653156E9596001E0AA3 /* Build configuration list for PBXNativeTarget "landtest" */;
|
||||
buildPhases = (
|
||||
3114A648156E9596001E0AA3 /* Sources */,
|
||||
3114A649156E9596001E0AA3 /* Frameworks */,
|
||||
|
|
@ -2738,9 +2738,9 @@
|
|||
dependencies = (
|
||||
3114A659156E95B1001E0AA3 /* PBXTargetDependency */,
|
||||
);
|
||||
name = fbmtest;
|
||||
productName = fbmtest;
|
||||
productReference = 3114A64C156E9596001E0AA3 /* fbmtest */;
|
||||
name = landtest;
|
||||
productName = landtest;
|
||||
productReference = 3114A64C156E9596001E0AA3 /* landtest */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
3114A661156E95D9001E0AA3 /* btcv */ = {
|
||||
|
|
@ -3120,7 +3120,7 @@
|
|||
318DA8C31892B0F30089718C /* djbench */,
|
||||
2291A5D3175CB05F001D4920 /* exposet0 */,
|
||||
2291A5C1175CAFCA001D4920 /* expt825 */,
|
||||
3114A64B156E9596001E0AA3 /* fbmtest */,
|
||||
3114A64B156E9596001E0AA3 /* landtest */,
|
||||
3114A5BC156E9315001E0AA3 /* finalcv */,
|
||||
3114A5D5156E93A0001E0AA3 /* finaltest */,
|
||||
224CC78C175E1821002FF81B /* fotest */,
|
||||
|
|
@ -3421,7 +3421,7 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2291A5ED175CB5E2001D4920 /* fbmtest.c in Sources */,
|
||||
2291A5ED175CB5E2001D4920 /* landtest.c in Sources */,
|
||||
3114A672156E95F6001E0AA3 /* testlib.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
@ -3908,7 +3908,7 @@
|
|||
};
|
||||
3114A65B156E95B4001E0AA3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 3114A64B156E9596001E0AA3 /* fbmtest */;
|
||||
target = 3114A64B156E9596001E0AA3 /* landtest */;
|
||||
targetProxy = 3114A65A156E95B4001E0AA3 /* PBXContainerItemProxy */;
|
||||
};
|
||||
3114A675156E9619001E0AA3 /* PBXTargetDependency */ = {
|
||||
|
|
@ -5460,7 +5460,7 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
3114A653156E9596001E0AA3 /* Build configuration list for PBXNativeTarget "fbmtest" */ = {
|
||||
3114A653156E9596001E0AA3 /* Build configuration list for PBXNativeTarget "landtest" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
3114A654156E9596001E0AA3 /* Debug */,
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ static Res MVTContingencySearch(Addr *baseReturn, Addr *limitReturn,
|
|||
static Bool MVTCheckFit(Addr base, Addr limit, Size min, Arena arena);
|
||||
static ABQ MVTABQ(MVT mvt);
|
||||
static Land MVTCBS(MVT mvt);
|
||||
static Freelist MVTFreelist(MVT mvt);
|
||||
static Land MVTFreelist(MVT mvt);
|
||||
|
||||
|
||||
/* Types */
|
||||
|
|
@ -174,9 +174,9 @@ static Land MVTCBS(MVT mvt)
|
|||
}
|
||||
|
||||
|
||||
static Freelist MVTFreelist(MVT mvt)
|
||||
static Land MVTFreelist(MVT mvt)
|
||||
{
|
||||
return &mvt->flStruct;
|
||||
return &mvt->flStruct.landStruct;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -280,7 +280,8 @@ static Res MVTInit(Pool pool, ArgList args)
|
|||
if (res != ResOK)
|
||||
goto failABQ;
|
||||
|
||||
res = FreelistInit(MVTFreelist(mvt), align);
|
||||
res = LandInit(MVTFreelist(mvt), FreelistLandClassGet(), arena, align, mvt,
|
||||
mps_args_none);
|
||||
if (res != ResOK)
|
||||
goto failFreelist;
|
||||
|
||||
|
|
@ -422,7 +423,7 @@ static void MVTFinish(Pool pool)
|
|||
}
|
||||
|
||||
/* Finish the Freelist, ABQ and CBS structures */
|
||||
FreelistFinish(MVTFreelist(mvt));
|
||||
LandFinish(MVTFreelist(mvt));
|
||||
ABQFinish(arena, MVTABQ(mvt));
|
||||
LandFinish(MVTCBS(mvt));
|
||||
}
|
||||
|
|
@ -810,14 +811,14 @@ static Res MVTInsert(MVT mvt, Addr base, Addr limit)
|
|||
|
||||
/* Attempt to flush the Freelist to the CBS to give maximum
|
||||
* opportunities for coalescence. */
|
||||
FreelistFlushToLand(MVTFreelist(mvt), MVTCBS(mvt));
|
||||
LandFlush(MVTCBS(mvt), MVTFreelist(mvt));
|
||||
|
||||
RangeInit(&range, base, limit);
|
||||
res = LandInsert(&newRange, MVTCBS(mvt), &range);
|
||||
if (ResIsAllocFailure(res)) {
|
||||
/* CBS ran out of memory for splay nodes: add range to emergency
|
||||
* free list instead. */
|
||||
res = FreelistInsert(&newRange, MVTFreelist(mvt), &range);
|
||||
res = LandInsert(&newRange, MVTFreelist(mvt), &range);
|
||||
}
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
|
@ -866,7 +867,7 @@ static Res MVTDelete(MVT mvt, Addr base, Addr limit)
|
|||
AVER(res == ResOK);
|
||||
} else if (res == ResFAIL) {
|
||||
/* Not found in the CBS: try the Freelist. */
|
||||
res = FreelistDelete(&rangeOld, MVTFreelist(mvt), &range);
|
||||
res = LandDelete(&rangeOld, MVTFreelist(mvt), &range);
|
||||
}
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
|
@ -1051,7 +1052,7 @@ static Res MVTDescribe(Pool pool, mps_lib_FILE *stream)
|
|||
res = ABQDescribe(MVTABQ(mvt), (ABQDescribeElement)RangeDescribe, stream);
|
||||
if(res != ResOK) return res;
|
||||
|
||||
res = FreelistDescribe(MVTFreelist(mvt), stream);
|
||||
res = LandDescribe(MVTFreelist(mvt), stream);
|
||||
if(res != ResOK) return res;
|
||||
|
||||
res = METER_WRITE(mvt->segAllocs, stream);
|
||||
|
|
@ -1272,13 +1273,16 @@ static Bool MVTReturnSegs(MVT mvt, Range range, Arena arena)
|
|||
}
|
||||
|
||||
|
||||
/* MVTRefillCallback -- called from CBSIterate or FreelistIterate at
|
||||
* the behest of MVTRefillABQIfEmpty
|
||||
*/
|
||||
static Bool MVTRefillCallback(MVT mvt, Range range)
|
||||
static Bool MVTRefillVisitor(Bool *deleteReturn, Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
AVERT(ABQ, MVTABQ(mvt));
|
||||
AVERT(Range, range);
|
||||
MVT mvt;
|
||||
|
||||
AVER(deleteReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
mvt = closureP;
|
||||
AVERT(MVT, mvt);
|
||||
UNUSED(closureS);
|
||||
|
||||
if (RangeSize(range) < mvt->reuseSize)
|
||||
return TRUE;
|
||||
|
|
@ -1287,29 +1291,6 @@ static Bool MVTRefillCallback(MVT mvt, Range range)
|
|||
return MVTReserve(mvt, range);
|
||||
}
|
||||
|
||||
static Bool MVTCBSRefillCallback(Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
MVT mvt;
|
||||
AVERT(Land, land);
|
||||
mvt = closureP;
|
||||
AVERT(MVT, mvt);
|
||||
UNUSED(closureS);
|
||||
return MVTRefillCallback(mvt, range);
|
||||
}
|
||||
|
||||
static Bool MVTFreelistRefillCallback(Bool *deleteReturn, Range range,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
MVT mvt;
|
||||
mvt = closureP;
|
||||
AVERT(MVT, mvt);
|
||||
UNUSED(closureS);
|
||||
AVER(deleteReturn != NULL);
|
||||
*deleteReturn = FALSE;
|
||||
return MVTRefillCallback(mvt, range);
|
||||
}
|
||||
|
||||
/* MVTRefillABQIfEmpty -- refill the ABQ from the CBS and the Freelist if
|
||||
* it is empty
|
||||
*/
|
||||
|
|
@ -1326,8 +1307,8 @@ static void MVTRefillABQIfEmpty(MVT mvt, Size size)
|
|||
if (mvt->abqOverflow && ABQIsEmpty(MVTABQ(mvt))) {
|
||||
mvt->abqOverflow = FALSE;
|
||||
METER_ACC(mvt->refills, size);
|
||||
LandIterate(MVTCBS(mvt), &MVTCBSRefillCallback, mvt, 0);
|
||||
FreelistIterate(MVTFreelist(mvt), &MVTFreelistRefillCallback, mvt, 0);
|
||||
LandIterate(MVTCBS(mvt), &MVTRefillVisitor, mvt, 0);
|
||||
LandIterate(MVTFreelist(mvt), &MVTRefillVisitor, mvt, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1348,19 +1329,26 @@ typedef struct MVTContigencyStruct
|
|||
} MVTContigencyStruct;
|
||||
|
||||
|
||||
/* MVTContingencyCallback -- called from CBSIterate or FreelistIterate
|
||||
* at the behest of MVTContingencySearch.
|
||||
/* MVTContingencyVisitor -- called from LandIterate at the behest of
|
||||
* MVTContingencySearch.
|
||||
*/
|
||||
static Bool MVTContingencyCallback(MVTContigency cl, Range range)
|
||||
|
||||
static Bool MVTContingencyVisitor(Bool *deleteReturn, Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
MVT mvt;
|
||||
Size size;
|
||||
Addr base, limit;
|
||||
MVTContigency cl;
|
||||
|
||||
AVER(cl != NULL);
|
||||
AVER(deleteReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
AVERT(Range, range);
|
||||
AVER(closureP != NULL);
|
||||
cl = closureP;
|
||||
mvt = cl->mvt;
|
||||
AVERT(MVT, mvt);
|
||||
AVERT(Range, range);
|
||||
UNUSED(closureS);
|
||||
|
||||
base = RangeBase(range);
|
||||
limit = RangeLimit(range);
|
||||
|
|
@ -1389,25 +1377,6 @@ static Bool MVTContingencyCallback(MVTContigency cl, Range range)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool MVTCBSContingencyCallback(Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
MVTContigency cl = closureP;
|
||||
AVERT(Land, land);
|
||||
UNUSED(closureS);
|
||||
return MVTContingencyCallback(cl, range);
|
||||
}
|
||||
|
||||
static Bool MVTFreelistContingencyCallback(Bool *deleteReturn, Range range,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
MVTContigency cl = closureP;
|
||||
UNUSED(closureS);
|
||||
AVER(deleteReturn != NULL);
|
||||
*deleteReturn = FALSE;
|
||||
return MVTContingencyCallback(cl, range);
|
||||
}
|
||||
|
||||
/* MVTContingencySearch -- search the CBS and the Freelist for a block
|
||||
* of size min */
|
||||
|
||||
|
|
@ -1423,11 +1392,10 @@ static Bool MVTContingencySearch(Addr *baseReturn, Addr *limitReturn,
|
|||
cls.steps = 0;
|
||||
cls.hardSteps = 0;
|
||||
|
||||
FreelistFlushToLand(MVTFreelist(mvt), MVTCBS(mvt));
|
||||
LandFlush(MVTCBS(mvt), MVTFreelist(mvt));
|
||||
|
||||
LandIterate(MVTCBS(mvt), MVTCBSContingencyCallback, (void *)&cls, 0);
|
||||
FreelistIterate(MVTFreelist(mvt), MVTFreelistContingencyCallback,
|
||||
(void *)&cls, 0);
|
||||
LandIterate(MVTCBS(mvt), MVTContingencyVisitor, (void *)&cls, 0);
|
||||
LandIterate(MVTFreelist(mvt), MVTContingencyVisitor, (void *)&cls, 0);
|
||||
if (!cls.found)
|
||||
return FALSE;
|
||||
|
||||
|
|
|
|||
|
|
@ -59,9 +59,7 @@ typedef struct MVFFStruct { /* MVFF pool outer structure */
|
|||
#define Pool2MVFF(pool) PARENT(MVFFStruct, poolStruct, pool)
|
||||
#define MVFF2Pool(mvff) (&((mvff)->poolStruct))
|
||||
#define CBSOfMVFF(mvff) (&((mvff)->cbsStruct.landStruct))
|
||||
#define MVFFOfCBS(cbs) PARENT(MVFFStruct, cbsStruct, cbs)
|
||||
#define FreelistOfMVFF(mvff) (&((mvff)->flStruct))
|
||||
#define MVFFOfFreelist(fl) PARENT(MVFFStruct, flStruct, fl)
|
||||
#define FreelistOfMVFF(mvff) (&((mvff)->flStruct.landStruct))
|
||||
|
||||
static Bool MVFFCheck(MVFF mvff);
|
||||
|
||||
|
|
@ -99,7 +97,7 @@ static Res MVFFAddToFreeList(Addr *baseIO, Addr *limitIO, MVFF mvff) {
|
|||
if (ResIsAllocFailure(res)) {
|
||||
/* CBS ran out of memory for splay nodes: add range to emergency
|
||||
* free list instead. */
|
||||
res = FreelistInsert(&newRange, FreelistOfMVFF(mvff), &range);
|
||||
res = LandInsert(&newRange, FreelistOfMVFF(mvff), &range);
|
||||
}
|
||||
|
||||
if (res == ResOK) {
|
||||
|
|
@ -178,7 +176,7 @@ static void MVFFFreeSegs(MVFF mvff, Addr base, Addr limit)
|
|||
}
|
||||
} else if (res == ResFAIL) {
|
||||
/* Not found in the CBS: must be found in the Freelist. */
|
||||
res = FreelistDelete(&oldRange, FreelistOfMVFF(mvff), &range);
|
||||
res = LandDelete(&oldRange, FreelistOfMVFF(mvff), &range);
|
||||
AVER(res == ResOK);
|
||||
mvff->free -= RangeSize(&range);
|
||||
}
|
||||
|
|
@ -297,7 +295,7 @@ static Bool MVFFFindFirstFree(Addr *baseReturn, Addr *limitReturn,
|
|||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, PoolAlignment(MVFF2Pool(mvff))));
|
||||
|
||||
FreelistFlushToLand(FreelistOfMVFF(mvff), CBSOfMVFF(mvff));
|
||||
LandFlush(CBSOfMVFF(mvff), FreelistOfMVFF(mvff));
|
||||
|
||||
findDelete = mvff->slotHigh ? FindDeleteHIGH : FindDeleteLOW;
|
||||
|
||||
|
|
@ -309,7 +307,7 @@ static Bool MVFFFindFirstFree(Addr *baseReturn, Addr *limitReturn,
|
|||
/* Failed to find a block in the CBS: try the emergency free list
|
||||
* as well. */
|
||||
foundBlock =
|
||||
(mvff->firstFit ? FreelistFindFirst : FreelistFindLast)
|
||||
(mvff->firstFit ? LandFindFirst : LandFindLast)
|
||||
(&range, &oldRange, FreelistOfMVFF(mvff), size, findDelete);
|
||||
}
|
||||
|
||||
|
|
@ -411,13 +409,12 @@ static Bool MVFFFindLargest(Range range, Range oldRange, MVFF mvff,
|
|||
AVER(size > 0);
|
||||
AVERT(FindDelete, findDelete);
|
||||
|
||||
FreelistFlushToLand(FreelistOfMVFF(mvff), CBSOfMVFF(mvff));
|
||||
LandFlush(CBSOfMVFF(mvff), FreelistOfMVFF(mvff));
|
||||
|
||||
if (LandFindLargest(range, oldRange, CBSOfMVFF(mvff), size, findDelete))
|
||||
return TRUE;
|
||||
|
||||
if (FreelistFindLargest(range, oldRange, FreelistOfMVFF(mvff),
|
||||
size, findDelete))
|
||||
if (LandFindLargest(range, oldRange, FreelistOfMVFF(mvff), size, findDelete))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
|
|
@ -598,16 +595,16 @@ static Res MVFFInit(Pool pool, ArgList args)
|
|||
mvff->total = 0;
|
||||
mvff->free = 0;
|
||||
|
||||
res = FreelistInit(FreelistOfMVFF(mvff), align);
|
||||
res = LandInit(FreelistOfMVFF(mvff), FreelistLandClassGet(), arena, align, mvff, mps_args_none);
|
||||
if (res != ResOK)
|
||||
goto failInit;
|
||||
goto failFreelistInit;
|
||||
|
||||
MPS_ARGS_BEGIN(liArgs) {
|
||||
MPS_ARGS_ADD(liArgs, CBSFastFind, TRUE);
|
||||
res = LandInit(CBSOfMVFF(mvff), CBSLandClassGet(), arena, align, mvff, liArgs);
|
||||
} MPS_ARGS_END(liArgs);
|
||||
if (res != ResOK)
|
||||
goto failInit;
|
||||
goto failCBSInit;
|
||||
|
||||
mvff->sig = MVFFSig;
|
||||
AVERT(MVFF, mvff);
|
||||
|
|
@ -615,7 +612,9 @@ static Res MVFFInit(Pool pool, ArgList args)
|
|||
slotHigh, arenaHigh, firstFit);
|
||||
return ResOK;
|
||||
|
||||
failInit:
|
||||
failCBSInit:
|
||||
LandFinish(FreelistOfMVFF(mvff));
|
||||
failFreelistInit:
|
||||
ControlFree(arena, p, sizeof(SegPrefStruct));
|
||||
return res;
|
||||
}
|
||||
|
|
@ -649,7 +648,7 @@ static void MVFFFinish(Pool pool)
|
|||
ControlFree(arena, mvff->segPref, sizeof(SegPrefStruct));
|
||||
|
||||
LandFinish(CBSOfMVFF(mvff));
|
||||
FreelistFinish(FreelistOfMVFF(mvff));
|
||||
LandFinish(FreelistOfMVFF(mvff));
|
||||
|
||||
mvff->sig = SigInvalid;
|
||||
}
|
||||
|
|
@ -697,7 +696,7 @@ static Res MVFFDescribe(Pool pool, mps_lib_FILE *stream)
|
|||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = FreelistDescribe(FreelistOfMVFF(mvff), stream);
|
||||
res = LandDescribe(FreelistOfMVFF(mvff), stream);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -804,8 +803,8 @@ static Bool MVFFCheck(MVFF mvff)
|
|||
CHECKL(mvff->total >= mvff->free);
|
||||
CHECKL(SizeIsAligned(mvff->free, PoolAlignment(MVFF2Pool(mvff))));
|
||||
CHECKL(SizeIsAligned(mvff->total, ArenaAlign(PoolArena(MVFF2Pool(mvff)))));
|
||||
CHECKD(Land, CBSOfMVFF(mvff));
|
||||
CHECKD(Freelist, FreelistOfMVFF(mvff));
|
||||
CHECKD(CBS, &mvff->cbsStruct);
|
||||
CHECKD(Freelist, &mvff->flStruct);
|
||||
CHECKL(BoolCheck(mvff->slotHigh));
|
||||
CHECKL(BoolCheck(mvff->firstFit));
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,10 @@ eager coalescence.
|
|||
|
||||
_`.readership`: This document is intended for any MM developer.
|
||||
|
||||
_`.source`: design.mps.poolmv2, design.mps.poolmvff.
|
||||
_`.source`: design.mps.poolmv2_, design.mps.poolmvff_.
|
||||
|
||||
.. _design.mps.poolmv2: poolmv2
|
||||
.. _design.mps.poolmvff: poolmvff
|
||||
|
||||
_`.overview`: The "coalescing block structure" is a set of addresses
|
||||
(or a subset of address space), with provision for efficient
|
||||
|
|
@ -33,7 +36,9 @@ Requirements
|
|||
------------
|
||||
|
||||
In addition to the generic land requirements (see
|
||||
design.mps.land.req), the CBS must satisfy:
|
||||
design.mps.land_), the CBS must satisfy:
|
||||
|
||||
.. _design.mps.land: land
|
||||
|
||||
_`.req.fast`: Common operations must have a low amortized cost.
|
||||
|
||||
|
|
@ -45,8 +50,9 @@ storage of any subset of address space.
|
|||
Interface
|
||||
---------
|
||||
|
||||
_`.land`: The interface to CBS is the generic functions for the *land*
|
||||
abstract data type. See `design.mps.land <land/>`_.
|
||||
_`.land`: CBS is an implementation of the *land* abstract data type,
|
||||
so the interface consists of the generic functions for lands. See
|
||||
design.mps.land_.
|
||||
|
||||
|
||||
External types
|
||||
|
|
@ -54,8 +60,9 @@ External types
|
|||
|
||||
``typedef struct CBSStruct *CBS``
|
||||
|
||||
_`.type.cbs`: A ``CBSStruct`` may be embedded in another structure, or
|
||||
you can create it using ``LandCreate()``.
|
||||
_`.type.cbs`: The type of coalescing block structures. A ``CBSStruct``
|
||||
may be embedded in another structure, or you can create it using
|
||||
``LandCreate()``.
|
||||
|
||||
|
||||
External functions
|
||||
|
|
@ -101,6 +108,25 @@ following optional keyword arguments:
|
|||
generic function.
|
||||
|
||||
|
||||
Limitations
|
||||
...........
|
||||
|
||||
_`.limit.find`: CBS does not support the ``LandFindFirst()``,
|
||||
``LandFindLast()``, and ``LandFindLargest()`` generic functions unless
|
||||
the ``CBSFastFind`` keyword argument was set to ``TRUE``.
|
||||
|
||||
_`.limit.zones`: CBS does not support the ``LandFindInZones()``
|
||||
generic function unless the ``CBSFastFind`` and ``CBSZoned`` keyword
|
||||
arguments were both set to ``TRUE``.
|
||||
|
||||
_`.limit.iterate`: CBS does not support visitors setting
|
||||
``deleteReturn`` to ``TRUE`` when iterating over ranges with
|
||||
``LandIterate()``.
|
||||
|
||||
_`.limit.flush`: CBS cannot be used as the source in a call to
|
||||
``LandFlush()``.
|
||||
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
|
|
@ -108,7 +134,6 @@ _`.impl`: This section is concerned with describing various aspects of
|
|||
the implementation. It does not form part of the interface definition.
|
||||
|
||||
|
||||
|
||||
Splay tree
|
||||
..........
|
||||
|
||||
|
|
@ -163,12 +188,12 @@ Testing
|
|||
|
||||
_`.test`: The following testing will be performed on this module:
|
||||
|
||||
_`.test.fbmtest`: A generic test for land implementations. See
|
||||
design.mps.land.fbmtest.
|
||||
_`.test.land`: A generic test for land implementations. See
|
||||
design.mps.land.test.
|
||||
|
||||
_`.test.pool`: Several pools (currently MVT_ and MVFF_) are implemented
|
||||
on top of a CBS. These pool are subject to testing in development, QA,
|
||||
and are/will be heavily exercised by customers.
|
||||
_`.test.pool`: The arena and two pools (MVT_ and MVFF_) are
|
||||
implemented on top of a CBS. These are subject to testing in
|
||||
development, QA, and are heavily exercised by customers.
|
||||
|
||||
.. _MVT: poolmvt
|
||||
.. _MVFF: poolmvff
|
||||
|
|
@ -177,9 +202,9 @@ and are/will be heavily exercised by customers.
|
|||
Notes for future development
|
||||
----------------------------
|
||||
|
||||
_`.future.not-splay`: The initial implementation of CBSs is based on
|
||||
splay trees. It could be revised to use any other data structure that
|
||||
meets the requirements (especially `.req.fast`_).
|
||||
_`.future.not-splay`: The implementation of CBSs is based on splay
|
||||
trees. It could be revised to use other data structures that meet the
|
||||
requirements (especially `.req.fast`_).
|
||||
|
||||
_`.future.hybrid`: It would be possible to attenuate the problem of
|
||||
`.risk.overhead`_ (below) by using a single word bit set to represent
|
||||
|
|
|
|||
|
|
@ -40,174 +40,53 @@ When memory becomes available again to allocate control structures,
|
|||
the free lists can be "flushed" back into the more efficient data
|
||||
structures.
|
||||
|
||||
_`.bg`: The free list allocator was formerly part of the Coalescing
|
||||
Block Structure module (see design.mps.cbs) but it was split into its
|
||||
own module because this makes it:
|
||||
|
||||
#. simpler (no need to interact with CBS) and thus more maintainable;
|
||||
#. possible to test directly (no need to create a CBS and then force
|
||||
its control pool to run out of memory); and
|
||||
#. usable as a fallback allocator in other pools (not just in pools
|
||||
that use CBS).
|
||||
|
||||
|
||||
Definitions
|
||||
-----------
|
||||
|
||||
_`.def.range`: A (contiguous) *range* of addresses is a semi-open
|
||||
interval on address space.
|
||||
|
||||
_`.def.isolated`: A contiguous range is *isolated* with respect to
|
||||
some property it has, if adjacent elements do not have that property.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
_`.req.set`: Must maintain a set of free address ranges.
|
||||
In addition to the generic land requirements (see design.mps.land_),
|
||||
free lists must satisfy:
|
||||
|
||||
_`.req.add`: Must be able to add free address ranges to the set.
|
||||
|
||||
_`.req.remove`: Must be able to remove address ranges from the set (in
|
||||
particular, when memory is allocated).
|
||||
|
||||
_`.req.iterate`: Must support the iteration of all isolated contiguous
|
||||
ranges.
|
||||
|
||||
_`.req.protocol`: Must detect protocol violations.
|
||||
|
||||
_`.req.align`: Must support an alignment (the alignment of all
|
||||
addresses specifying ranges) of down to ``sizeof(void *)`` without
|
||||
losing memory.
|
||||
.. _design.mps.land: land
|
||||
|
||||
_`.req.zero-overhead`: Must have zero space overhead for the storage
|
||||
of any set of free blocks, so that it can be used to manage memory
|
||||
when no memory can be allocated for control structures.
|
||||
|
||||
_`.req.source`: This set of requirements is derived from those of the
|
||||
CBS module (see design.mps.cbs.req), except that there is no
|
||||
equivalent of design.mps.cbs.req.fast, and design.mps.cbs.req.small
|
||||
has been replaced with `.req.zero-overhead`_.
|
||||
|
||||
|
||||
Interface
|
||||
---------
|
||||
|
||||
_`.land`: Free lists are an implementation of the *land* abstract data
|
||||
type, so the interface consists of the generic functions for lands.
|
||||
See design.mps.land_.
|
||||
|
||||
|
||||
Types
|
||||
.....
|
||||
|
||||
``typedef struct FreelistStruct *Freelist``
|
||||
|
||||
_`.type.freelist`: The type of free lists. The structure
|
||||
``FreelistStruct`` is declared in the header so that it can be inlined
|
||||
in other structures, but you should not depend on its details.
|
||||
|
||||
``typedef Bool (*FreelistIterateMethod)(Bool *deleteReturn, Freelist fl, Range range, void *closureP, Size closureS)``
|
||||
|
||||
_`.type.iterate.method`: A callback function that may be passed to
|
||||
``FreelistIterate()``. It is called for every isolated contiguous
|
||||
range in address order, and with the closure arguments that were
|
||||
originally passed to ``FreelistIterate()``. It must update
|
||||
``*deleteReturn`` to ``TRUE`` if the range must be deleted from the
|
||||
free lists, or ``FALSE`` if the range must be kept. The function must
|
||||
return ``TRUE`` if the iteration must continue, and ``FALSE`` if the
|
||||
iteration must stop (after possibly deleting the current range).
|
||||
_`.type.freelist`: The type of free lists. A ``FreelistStruct`` may be
|
||||
embedded in another structure, or you can create it using
|
||||
``LandCreate()``.
|
||||
|
||||
|
||||
Functions
|
||||
.........
|
||||
External functions
|
||||
..................
|
||||
|
||||
``Res FreelistInit(Freelist fl, Align alignment)``
|
||||
``LandClass FreelistLandClassGet(void)``
|
||||
|
||||
_`.function.init`: Initialize the ``Freelist`` structure pointed to by
|
||||
``fl``. The argument ``alignment`` is the alignment of address ranges
|
||||
to be maintained. An initialised free list contains no address ranges.
|
||||
_`.function.class`: The function ``FreelistLandClassGet()`` returns
|
||||
the free list class, a subclass of ``LandClass`` suitable for passing
|
||||
to ``LandCreate()`` or ``LandInit()``.
|
||||
|
||||
``void FreelistFinish(Freelist fl)``
|
||||
|
||||
_`.function.finish`: Finish the free list pointed to by ``fl``.
|
||||
|
||||
``Res FreelistInsert(Range rangeReturn, Freelist fl, Range range)``
|
||||
|
||||
_`.function.insert`: If any part of ``range`` is already in the free
|
||||
list ``fl``, then leave the free list unchanged and return
|
||||
``ResFAIL``. Otherwise, insert ``range`` into the free list ``fl``;
|
||||
update ``rangeReturn`` to describe the contiguous isolated range
|
||||
containing the inserted range (this may differ from ``range`` if there
|
||||
was coalescence on either side) and return ``ResOK``.
|
||||
|
||||
``Res FreelistDelete(Range rangeReturn, Freelist fl, Range range)``
|
||||
|
||||
_`.function.delete`: If any part of the range is not in the free list,
|
||||
then leave the free list unchanged and return ``ResFAIL``. Otherwise,
|
||||
remove ``range`` from the free list and update ``rangeReturn`` to
|
||||
describe the contiguous isolated range that formerly contained the
|
||||
deleted range (this may differ from ``range`` if there were fragments
|
||||
left on either side), and return ``ResOK``.
|
||||
|
||||
``void FreelistIterate(Freelist fl, FreelistIterateMethod iterate, void *closureP, Size closureS)``
|
||||
|
||||
_`.function.iterate`: Iterate all isolated contiguous ranges in the
|
||||
free list ``fl`` in address order, calling ``iterate`` for each one.
|
||||
See ``FreelistIterateMethod`` for details.
|
||||
|
||||
``Bool FreelistFindFirst(Range rangeReturn, Range oldRangeReturn, Freelist fl, Size size, FindDelete findDelete)``
|
||||
|
||||
_`.function.find.first`: Locate the first isolated contiguous range in
|
||||
address order, within the free list ``fl``, of at least ``size``
|
||||
bytes, update ``rangeReturn`` to that range, and return ``TRUE``. If
|
||||
there is no such continuous range, return ``FALSE``.
|
||||
|
||||
In addition, optionally delete the found range from the free list,
|
||||
depending on the ``findDelete`` argument. This saves a separate call
|
||||
to ``FreelistDelete()``, and uses the knowledge of exactly where we
|
||||
found the range. The value of ``findDelete`` must come from this
|
||||
enumeration::
|
||||
|
||||
enum {
|
||||
FindDeleteNONE, /* don't delete after finding */
|
||||
FindDeleteLOW, /* delete size bytes from low end of block */
|
||||
FindDeleteHIGH, /* delete size bytes from high end of block */
|
||||
FindDeleteENTIRE /* delete entire range */
|
||||
};
|
||||
|
||||
The original contiguous isolated range in which the range was found is
|
||||
returned via the ``oldRangeReturn`` argument. (If ``findDelete`` is
|
||||
``FindDeleteNONE`` or ``FindDeleteENTIRE``, then this will be
|
||||
identical to the range returned via the ``rangeReturn`` argument.)
|
||||
|
||||
``Bool FreelistFindLast(Range rangeReturn, Range oldRangeReturn, Freelist fl, Size size, FindDelete findDelete)``
|
||||
|
||||
_`.function.find.last`: Like ``FreelistFindFirst()``, except that it
|
||||
finds the last block in address order.
|
||||
|
||||
``Bool FreelistFindLargest(Range rangeReturn, Range oldRangeReturn, Freelist fl, Size, size, FindDelete findDelete)``
|
||||
|
||||
_`.function.find.largest`: Locate the largest block within the free
|
||||
list ``fl``, and if that block is at least as big as ``size``, return
|
||||
its range via the ``rangeReturn`` argument, and return ``TRUE``. If
|
||||
there are no blocks in the free list at least as large as ``size``,
|
||||
return ``FALSE``. Pass 0 for ``size`` if you want the largest block
|
||||
unconditionally.
|
||||
|
||||
Like ``FreelistFindFirst()``, optionally delete the range from the
|
||||
free list. (Always the whole range: specifying ``FindDeleteLOW`` or
|
||||
``FindDeleteHIGH`` has the same effect as ``FindDeleteENTIRE``).
|
||||
|
||||
``void FreelistFlushToCBS(Freelist fl, CBS cbs)``
|
||||
|
||||
Remove free address ranges from the free list ``fl`` and add them to
|
||||
the Coalescing Block Structure ``cbs``. Continue until a call to
|
||||
``CBSInsert()`` fails, or until the free list is empty, whichever
|
||||
happens first.
|
||||
|
||||
``Res FreelistDescribe(Freelist fl, mps_lib_FILE *stream)``
|
||||
|
||||
_`.function.describe`: Print a textual representation of the free
|
||||
list ``fl`` to the given stream, indicating the contiguous ranges in
|
||||
order. It is provided for debugging purposes only.
|
||||
Keyword arguments
|
||||
.................
|
||||
|
||||
When initializing a free list, ``LandCreate()`` and ``LandInit()``
|
||||
take no keyword arguments. Pass ``mps_args_none``.
|
||||
|
||||
|
||||
Implementation
|
||||
|
|
@ -246,6 +125,23 @@ do this, such as using another tag to indicate the last block in the
|
|||
list, but these would be more complicated.)
|
||||
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
_`.test`: The following testing will be performed on this module:
|
||||
|
||||
_`.test.land`: A generic test for land implementations. See
|
||||
design.mps.land.test.
|
||||
|
||||
_`.test.pool`: Two pools (MVT_ and MVFF_) use free lists as a fallback
|
||||
when low on memory. These are subject to testing in development, QA,
|
||||
and are heavily exercised by customers.
|
||||
|
||||
.. _MVT: poolmvt
|
||||
.. _MVFF: poolmvff
|
||||
|
||||
|
||||
|
||||
Opportunities for improvement
|
||||
-----------------------------
|
||||
|
||||
|
|
@ -255,8 +151,8 @@ exceed the recorded size of the list.
|
|||
|
||||
_`.improve.maxsize`: We could maintain the maximum size of any range
|
||||
on the list, and use that to make an early exit from
|
||||
``FreelistFindLargest()``. It's not clear that this would actually be
|
||||
an improvement.
|
||||
``LandFindLargest()``. It's not clear that this would actually be an
|
||||
improvement.
|
||||
|
||||
|
||||
|
||||
|
|
@ -265,6 +161,8 @@ Document History
|
|||
|
||||
- 2013-05-18 GDR_ Initial draft based on CBS "emergency block" design.
|
||||
|
||||
- 2014-04-01 GDR_ Moved generic material to design.mps.land_.
|
||||
|
||||
.. _GDR: http://www.ravenbrook.com/consultants/gdr/
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -77,12 +77,15 @@ Types
|
|||
|
||||
_`.type.land`: The type of a generic land instance.
|
||||
|
||||
``typedef Bool (*LandVisitor)(Land land, Range range, void *closureP, Size closureS);``
|
||||
``typedef Bool (*LandVisitor)(Bool *deleteReturn, Land land, Range range, void *closureP, Size closureS);``
|
||||
|
||||
_`.type.visitor`: Type ``LandVisitor`` is a callback function that
|
||||
may be passed to ``LandIterate()``. It is called for every isolated
|
||||
contiguous range in address order. The function must return a
|
||||
``Bool`` indicating whether to continue with the iteration.
|
||||
_`.type.visitor`: Type ``LandVisitor`` is a callback function that may
|
||||
be passed to ``LandIterate()``. It is called for every isolated
|
||||
contiguous range in address order. The function must return a ``Bool``
|
||||
indicating whether to continue with the iteration. It may additionally
|
||||
update ``*deleteReturn`` to ``TRUE`` if the range must be deleted from
|
||||
the land, or ``FALSE`` if the range must be kept. (The default is to
|
||||
keep the range, and not all land classes support deletion.)
|
||||
|
||||
|
||||
Generic functions
|
||||
|
|
@ -220,25 +223,28 @@ the ``oldRangeReturn`` argument.
|
|||
|
||||
``Res LandDescribe(Land land, mps_lib_FILE *stream)``
|
||||
|
||||
_`.function.describe`: ``LandDescribe()`` is a function that prints
|
||||
a textual representation of the land to the given stream, indicating
|
||||
the contiguous ranges in order, as well as the structure of the
|
||||
underlying splay tree implementation. It is provided for debugging
|
||||
purposes only.
|
||||
_`.function.describe`: ``LandDescribe()`` prints a textual
|
||||
representation of the land to the given stream, indicating the
|
||||
contiguous ranges in order, as well as the structure of the underlying
|
||||
splay tree implementation. It is provided for debugging purposes only.
|
||||
|
||||
``void LandFlush(Land dest, Land src)``
|
||||
|
||||
_`.function.flush`: Delete ranges of addresses from ``src`` and insert
|
||||
them into ``dest``, so long as ``LandInsert()`` remains successful.
|
||||
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
_`.test.fbmtest`: There is a stress test for implementations of this
|
||||
interface in impl.c.fbmtest. This allocates a large block of memory
|
||||
and then simulates the allocation and deallocation of ranges within
|
||||
this block using both a ``Land`` and a ``BT``. It makes both valid and
|
||||
invalid requests, and compares the ``Land`` response to the correct
|
||||
behaviour as determined by the ``BT``. It iterates the ranges in the
|
||||
``Land``, comparing them to the ``BT``. It invokes the
|
||||
``LandDescribe()`` generic function, but makes no automatic test of
|
||||
the resulting output.
|
||||
_`.test`: There is a stress test for implementations of this interface
|
||||
in impl.c.landtest. This allocates a large block of memory and then
|
||||
simulates the allocation and deallocation of ranges within this block
|
||||
using both a ``Land`` and a ``BT``. It makes both valid and invalid
|
||||
requests, and compares the ``Land`` response to the correct behaviour
|
||||
as determined by the ``BT``. It iterates the ranges in the ``Land``,
|
||||
comparing them to the ``BT``. It invokes the ``LandDescribe()``
|
||||
generic function, but makes no automatic test of the resulting output.
|
||||
|
||||
|
||||
Document History
|
||||
|
|
|
|||
|
|
@ -32,10 +32,10 @@ set ALL_TEST_CASES=^
|
|||
btcv.exe ^
|
||||
exposet0.exe ^
|
||||
expt825.exe ^
|
||||
fbmtest.exe ^
|
||||
finalcv.exe ^
|
||||
finaltest.exe ^
|
||||
fotest.exe ^
|
||||
landtest.exe ^
|
||||
locbwcss.exe ^
|
||||
lockcov.exe ^
|
||||
lockutw3.exe ^
|
||||
|
|
|
|||
|
|
@ -29,10 +29,10 @@ ALL_TEST_CASES="
|
|||
btcv
|
||||
exposet0
|
||||
expt825
|
||||
fbmtest
|
||||
finalcv
|
||||
finaltest
|
||||
fotest
|
||||
landtest
|
||||
locbwcss
|
||||
lockcov
|
||||
locusss
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue