mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-30 04:10:54 -08:00
First pass at implementation of lands (collections of address ranges). 100% boilerplate!
Copied from Perforce Change: 185131 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
f3c8926e04
commit
d2cbfda452
18 changed files with 800 additions and 316 deletions
135
mps/code/arena.c
135
mps/code/arena.c
|
|
@ -19,7 +19,7 @@ SRCID(arena, "$Id$");
|
|||
|
||||
#define ArenaControlPool(arena) MV2Pool(&(arena)->controlPoolStruct)
|
||||
#define ArenaCBSBlockPool(arena) (&(arena)->freeCBSBlockPoolStruct.poolStruct)
|
||||
#define ArenaFreeCBS(arena) (&(arena)->freeCBSStruct)
|
||||
#define ArenaFreeLand(arena) ((Land)&(arena)->freeLandStruct)
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
|
|
@ -153,9 +153,9 @@ Bool ArenaCheck(Arena arena)
|
|||
|
||||
CHECKL(LocusCheck(arena));
|
||||
|
||||
CHECKL(BoolCheck(arena->hasFreeCBS));
|
||||
if (arena->hasFreeCBS)
|
||||
CHECKL(CBSCheck(ArenaFreeCBS(arena)));
|
||||
CHECKL(BoolCheck(arena->hasFreeLand));
|
||||
if (arena->hasFreeLand)
|
||||
CHECKL(LandCheck(ArenaFreeLand(arena)));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -198,7 +198,7 @@ Res ArenaInit(Arena arena, ArenaClass class, Align alignment, ArgList args)
|
|||
arena->poolReady = FALSE; /* <design/arena/#pool.ready> */
|
||||
arena->lastTract = NULL;
|
||||
arena->lastTractBase = NULL;
|
||||
arena->hasFreeCBS = FALSE;
|
||||
arena->hasFreeLand = FALSE;
|
||||
arena->freeZones = ZoneSetUNIV;
|
||||
arena->zoned = zoned;
|
||||
|
||||
|
|
@ -214,11 +214,12 @@ Res ArenaInit(Arena arena, ArenaClass class, Align alignment, ArgList args)
|
|||
goto failGlobalsInit;
|
||||
|
||||
arena->sig = ArenaSig;
|
||||
AVERT(Arena, arena);
|
||||
|
||||
/* Initialise a pool to hold the arena's CBS blocks. This pool can't be
|
||||
allowed to extend itself using ArenaAlloc because it is used during
|
||||
ArenaAlloc, so MFSExtendSelf is set to FALSE. Failures to extend are
|
||||
handled where the CBS is used. */
|
||||
handled where the Land is used. */
|
||||
|
||||
MPS_ARGS_BEGIN(piArgs) {
|
||||
MPS_ARGS_ADD(piArgs, MPS_KEY_MFS_UNIT_SIZE, sizeof(CBSBlockStruct));
|
||||
|
|
@ -231,18 +232,19 @@ Res ArenaInit(Arena arena, ArenaClass class, Align alignment, ArgList args)
|
|||
if (res != ResOK)
|
||||
goto failMFSInit;
|
||||
|
||||
/* Initialise the freeCBS. */
|
||||
MPS_ARGS_BEGIN(cbsiArgs) {
|
||||
MPS_ARGS_ADD(cbsiArgs, CBSBlockPool, ArenaCBSBlockPool(arena));
|
||||
MPS_ARGS_DONE(cbsiArgs);
|
||||
res = CBSInit(ArenaFreeCBS(arena), arena, arena, alignment,
|
||||
/* fastFind */ TRUE, arena->zoned, cbsiArgs);
|
||||
} MPS_ARGS_END(cbsiArgs);
|
||||
/* Initialise the freeLand. */
|
||||
MPS_ARGS_BEGIN(landiArgs) {
|
||||
MPS_ARGS_ADD(landiArgs, CBSBlockPool, ArenaCBSBlockPool(arena));
|
||||
MPS_ARGS_ADD(landiArgs, CBSFastFind, TRUE);
|
||||
MPS_ARGS_ADD(landiArgs, CBSZoned, arena->zoned);
|
||||
MPS_ARGS_DONE(landiArgs);
|
||||
res = LandInit(ArenaFreeLand(arena), CBSLandClassGet(), arena, alignment, arena, landiArgs);
|
||||
} MPS_ARGS_END(landiArgs);
|
||||
AVER(res == ResOK); /* no allocation, no failure expected */
|
||||
if (res != ResOK)
|
||||
goto failCBSInit;
|
||||
/* Note that although freeCBS is initialised, it doesn't have any memory
|
||||
for its blocks, so hasFreeCBS remains FALSE until later. */
|
||||
goto failLandInit;
|
||||
/* Note that although freeLand is initialised, it doesn't have any memory
|
||||
for its blocks, so hasFreeLand remains FALSE until later. */
|
||||
|
||||
/* initialize the reservoir, <design/reservoir/> */
|
||||
res = ReservoirInit(&arena->reservoirStruct, arena);
|
||||
|
|
@ -253,8 +255,8 @@ Res ArenaInit(Arena arena, ArenaClass class, Align alignment, ArgList args)
|
|||
return ResOK;
|
||||
|
||||
failReservoirInit:
|
||||
CBSFinish(ArenaFreeCBS(arena));
|
||||
failCBSInit:
|
||||
LandFinish(ArenaFreeLand(arena));
|
||||
failLandInit:
|
||||
PoolFinish(ArenaCBSBlockPool(arena));
|
||||
failMFSInit:
|
||||
GlobalsFinish(ArenaGlobals(arena));
|
||||
|
|
@ -304,15 +306,15 @@ Res ArenaCreate(Arena *arenaReturn, ArenaClass class, ArgList args)
|
|||
goto failStripeSize;
|
||||
}
|
||||
|
||||
/* With the primary chunk initialised we can add page memory to the freeCBS
|
||||
/* With the primary chunk initialised we can add page memory to the freeLand
|
||||
that describes the free address space in the primary chunk. */
|
||||
arena->hasFreeCBS = TRUE;
|
||||
res = ArenaFreeCBSInsert(arena,
|
||||
arena->hasFreeLand = TRUE;
|
||||
res = ArenaFreeLandInsert(arena,
|
||||
PageIndexBase(arena->primary,
|
||||
arena->primary->allocBase),
|
||||
arena->primary->limit);
|
||||
if (res != ResOK)
|
||||
goto failPrimaryCBS;
|
||||
goto failPrimaryLand;
|
||||
|
||||
res = ControlInit(arena);
|
||||
if (res != ResOK)
|
||||
|
|
@ -329,7 +331,7 @@ Res ArenaCreate(Arena *arenaReturn, ArenaClass class, ArgList args)
|
|||
failGlobalsCompleteCreate:
|
||||
ControlFinish(arena);
|
||||
failControlInit:
|
||||
failPrimaryCBS:
|
||||
failPrimaryLand:
|
||||
failStripeSize:
|
||||
(*class->finish)(arena);
|
||||
failInit:
|
||||
|
|
@ -378,11 +380,11 @@ void ArenaDestroy(Arena arena)
|
|||
arena->poolReady = FALSE;
|
||||
ControlFinish(arena);
|
||||
|
||||
/* We must tear down the freeCBS before the chunks, because pages
|
||||
/* We must tear down the freeLand before the chunks, because pages
|
||||
containing CBS blocks might be allocated in those chunks. */
|
||||
AVER(arena->hasFreeCBS);
|
||||
arena->hasFreeCBS = FALSE;
|
||||
CBSFinish(ArenaFreeCBS(arena));
|
||||
AVER(arena->hasFreeLand);
|
||||
arena->hasFreeLand = FALSE;
|
||||
LandFinish(ArenaFreeLand(arena));
|
||||
|
||||
/* The CBS block pool can't free its own memory via ArenaFree because
|
||||
that would use the ZonedCBS. */
|
||||
|
|
@ -601,9 +603,10 @@ Res ControlDescribe(Arena arena, mps_lib_FILE *stream)
|
|||
|
||||
/* arenaAllocPage -- allocate one page from the arena
|
||||
*
|
||||
* This is a primitive allocator used to allocate pages for the arena CBS.
|
||||
* It is called rarely and can use a simple search. It may not use the
|
||||
* CBS or any pool, because it is used as part of the bootstrap.
|
||||
* This is a primitive allocator used to allocate pages for the arena
|
||||
* Land. It is called rarely and can use a simple search. It may not
|
||||
* use the Land or any pool, because it is used as part of the
|
||||
* bootstrap.
|
||||
*/
|
||||
|
||||
static Res arenaAllocPageInChunk(Addr *baseReturn, Chunk chunk, Pool pool)
|
||||
|
|
@ -685,7 +688,7 @@ static Res arenaExtendCBSBlockPool(Range pageRangeReturn, Arena arena)
|
|||
return ResOK;
|
||||
}
|
||||
|
||||
/* arenaExcludePage -- exclude CBS block pool's page from CBSs
|
||||
/* arenaExcludePage -- exclude CBS block pool's page from Land
|
||||
*
|
||||
* Exclude the page we specially allocated for the CBS block pool
|
||||
* so that it doesn't get reallocated.
|
||||
|
|
@ -696,20 +699,20 @@ static void arenaExcludePage(Arena arena, Range pageRange)
|
|||
RangeStruct oldRange;
|
||||
Res res;
|
||||
|
||||
res = CBSDelete(&oldRange, ArenaFreeCBS(arena), pageRange);
|
||||
AVER(res == ResOK); /* we just gave memory to the CBSs */
|
||||
res = LandDelete(&oldRange, ArenaFreeLand(arena), pageRange);
|
||||
AVER(res == ResOK); /* we just gave memory to the Land */
|
||||
}
|
||||
|
||||
|
||||
/* arenaCBSInsert -- add a block to an arena CBS, extending pool if necessary
|
||||
/* arenaLandInsert -- add a block to an arena Land, extending pool if necessary
|
||||
*
|
||||
* The arena's CBSs can't get memory in the usual way because they are used
|
||||
* The arena's Land can't get memory in the usual way because they are used
|
||||
* in the basic allocator, so we allocate pages specially.
|
||||
*
|
||||
* Only fails if it can't get a page for the block pool.
|
||||
*/
|
||||
|
||||
static Res arenaCBSInsert(Range rangeReturn, Arena arena, Range range)
|
||||
static Res arenaLandInsert(Range rangeReturn, Arena arena, Range range)
|
||||
{
|
||||
Res res;
|
||||
|
||||
|
|
@ -717,17 +720,17 @@ static Res arenaCBSInsert(Range rangeReturn, Arena arena, Range range)
|
|||
AVERT(Arena, arena);
|
||||
AVERT(Range, range);
|
||||
|
||||
res = CBSInsert(rangeReturn, ArenaFreeCBS(arena), range);
|
||||
res = LandInsert(rangeReturn, ArenaFreeLand(arena), range);
|
||||
|
||||
if (res == ResLIMIT) { /* freeCBS MFS pool ran out of blocks */
|
||||
if (res == ResLIMIT) { /* freeLand MFS pool ran out of blocks */
|
||||
RangeStruct pageRange;
|
||||
res = arenaExtendCBSBlockPool(&pageRange, arena);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
/* .insert.exclude: Must insert before exclude so that we can
|
||||
bootstrap when the zoned CBS is empty. */
|
||||
res = CBSInsert(rangeReturn, ArenaFreeCBS(arena), range);
|
||||
AVER(res == ResOK); /* we just gave memory to the CBSs */
|
||||
res = LandInsert(rangeReturn, ArenaFreeLand(arena), range);
|
||||
AVER(res == ResOK); /* we just gave memory to the Land */
|
||||
arenaExcludePage(arena, &pageRange);
|
||||
}
|
||||
|
||||
|
|
@ -735,16 +738,16 @@ static Res arenaCBSInsert(Range rangeReturn, Arena arena, Range range)
|
|||
}
|
||||
|
||||
|
||||
/* ArenaFreeCBSInsert -- add a block to arena CBS, maybe stealing memory
|
||||
/* ArenaFreeLandInsert -- add a block to arena Land, maybe stealing memory
|
||||
*
|
||||
* See arenaCBSInsert. This function may only be applied to mapped pages
|
||||
* and may steal them to store CBS nodes if it's unable to allocate
|
||||
* See arenaLandInsert. This function may only be applied to mapped pages
|
||||
* and may steal them to store Land nodes if it's unable to allocate
|
||||
* space for CBS nodes.
|
||||
*
|
||||
* IMPORTANT: May update rangeIO.
|
||||
*/
|
||||
|
||||
static void arenaCBSInsertSteal(Range rangeReturn, Arena arena, Range rangeIO)
|
||||
static void arenaLandInsertSteal(Range rangeReturn, Arena arena, Range rangeIO)
|
||||
{
|
||||
Res res;
|
||||
|
||||
|
|
@ -752,7 +755,7 @@ static void arenaCBSInsertSteal(Range rangeReturn, Arena arena, Range rangeIO)
|
|||
AVERT(Arena, arena);
|
||||
AVERT(Range, rangeIO);
|
||||
|
||||
res = arenaCBSInsert(rangeReturn, arena, rangeIO);
|
||||
res = arenaLandInsert(rangeReturn, arena, rangeIO);
|
||||
|
||||
if (res != ResOK) {
|
||||
Addr pageBase;
|
||||
|
|
@ -773,22 +776,22 @@ static void arenaCBSInsertSteal(Range rangeReturn, Arena arena, Range rangeIO)
|
|||
MFSExtend(ArenaCBSBlockPool(arena), pageBase, ArenaAlign(arena));
|
||||
|
||||
/* Try again. */
|
||||
res = CBSInsert(rangeReturn, ArenaFreeCBS(arena), rangeIO);
|
||||
AVER(res == ResOK); /* we just gave memory to the CBS */
|
||||
res = LandInsert(rangeReturn, ArenaFreeLand(arena), rangeIO);
|
||||
AVER(res == ResOK); /* we just gave memory to the Land */
|
||||
}
|
||||
|
||||
AVER(res == ResOK); /* not expecting other kinds of error from the CBS */
|
||||
AVER(res == ResOK); /* not expecting other kinds of error from the Land */
|
||||
}
|
||||
|
||||
|
||||
/* ArenaFreeCBSInsert -- add block to free CBS, extending pool if necessary
|
||||
/* ArenaFreeLandInsert -- add block to free Land, extending pool if necessary
|
||||
*
|
||||
* The inserted block of address space may not abut any existing block.
|
||||
* This restriction ensures that we don't coalesce chunks and allocate
|
||||
* object across the boundary, preventing chunk deletion.
|
||||
*/
|
||||
|
||||
Res ArenaFreeCBSInsert(Arena arena, Addr base, Addr limit)
|
||||
Res ArenaFreeLandInsert(Arena arena, Addr base, Addr limit)
|
||||
{
|
||||
RangeStruct range, oldRange;
|
||||
Res res;
|
||||
|
|
@ -796,7 +799,7 @@ Res ArenaFreeCBSInsert(Arena arena, Addr base, Addr limit)
|
|||
AVERT(Arena, arena);
|
||||
|
||||
RangeInit(&range, base, limit);
|
||||
res = arenaCBSInsert(&oldRange, arena, &range);
|
||||
res = arenaLandInsert(&oldRange, arena, &range);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -809,7 +812,7 @@ Res ArenaFreeCBSInsert(Arena arena, Addr base, Addr limit)
|
|||
}
|
||||
|
||||
|
||||
/* ArenaFreeCBSDelete -- remove a block from free CBS, extending pool if necessary
|
||||
/* ArenaFreeLandDelete -- remove a block from free Land, extending pool if necessary
|
||||
*
|
||||
* This is called from ChunkFinish in order to remove address space from
|
||||
* the arena.
|
||||
|
|
@ -820,13 +823,13 @@ Res ArenaFreeCBSInsert(Arena arena, Addr base, Addr limit)
|
|||
* so we can't test that path.
|
||||
*/
|
||||
|
||||
void ArenaFreeCBSDelete(Arena arena, Addr base, Addr limit)
|
||||
void ArenaFreeLandDelete(Arena arena, Addr base, Addr limit)
|
||||
{
|
||||
RangeStruct range, oldRange;
|
||||
Res res;
|
||||
|
||||
RangeInit(&range, base, limit);
|
||||
res = CBSDelete(&oldRange, ArenaFreeCBS(arena), &range);
|
||||
res = LandDelete(&oldRange, ArenaFreeLand(arena), &range);
|
||||
|
||||
/* Shouldn't be any other kind of failure because we were only deleting
|
||||
a non-coalesced block. See .chunk.no-coalesce and
|
||||
|
|
@ -835,7 +838,7 @@ void ArenaFreeCBSDelete(Arena arena, Addr base, Addr limit)
|
|||
}
|
||||
|
||||
|
||||
static Res arenaAllocFromCBS(Tract *tractReturn, ZoneSet zones, Bool high,
|
||||
static Res arenaAllocFromLand(Tract *tractReturn, ZoneSet zones, Bool high,
|
||||
Size size, Pool pool)
|
||||
{
|
||||
Arena arena;
|
||||
|
|
@ -858,7 +861,7 @@ static Res arenaAllocFromCBS(Tract *tractReturn, ZoneSet zones, Bool high,
|
|||
|
||||
/* Step 1. Find a range of address space. */
|
||||
|
||||
res = CBSFindInZones(&range, &oldRange, ArenaFreeCBS(arena),
|
||||
res = LandFindInZones(&range, &oldRange, ArenaFreeLand(arena),
|
||||
size, zones, high);
|
||||
|
||||
if (res == ResLIMIT) { /* found block, but couldn't store info */
|
||||
|
|
@ -867,7 +870,7 @@ static Res arenaAllocFromCBS(Tract *tractReturn, ZoneSet zones, Bool high,
|
|||
if (res != ResOK) /* disastrously short on memory */
|
||||
return res;
|
||||
arenaExcludePage(arena, &pageRange);
|
||||
res = CBSFindInZones(&range, &oldRange, ArenaFreeCBS(arena),
|
||||
res = LandFindInZones(&range, &oldRange, ArenaFreeLand(arena),
|
||||
size, zones, high);
|
||||
AVER(res != ResLIMIT);
|
||||
}
|
||||
|
|
@ -901,7 +904,7 @@ static Res arenaAllocFromCBS(Tract *tractReturn, ZoneSet zones, Bool high,
|
|||
|
||||
failMark:
|
||||
{
|
||||
Res insertRes = arenaCBSInsert(&oldRange, arena, &range);
|
||||
Res insertRes = arenaLandInsert(&oldRange, arena, &range);
|
||||
AVER(insertRes == ResOK); /* We only just deleted it. */
|
||||
/* If the insert does fail, we lose some address space permanently. */
|
||||
}
|
||||
|
|
@ -942,10 +945,10 @@ static Res arenaAllocPolicy(Tract *tractReturn, Arena arena, SegPref pref,
|
|||
}
|
||||
}
|
||||
|
||||
/* Plan A: allocate from the free CBS in the requested zones */
|
||||
/* Plan A: allocate from the free Land in the requested zones */
|
||||
zones = ZoneSetDiff(pref->zones, pref->avoid);
|
||||
if (zones != ZoneSetEMPTY) {
|
||||
res = arenaAllocFromCBS(&tract, zones, pref->high, size, pool);
|
||||
res = arenaAllocFromLand(&tract, zones, pref->high, size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
}
|
||||
|
|
@ -957,7 +960,7 @@ static Res arenaAllocPolicy(Tract *tractReturn, Arena arena, SegPref pref,
|
|||
See also job003384. */
|
||||
moreZones = ZoneSetUnion(pref->zones, ZoneSetDiff(arena->freeZones, pref->avoid));
|
||||
if (moreZones != zones) {
|
||||
res = arenaAllocFromCBS(&tract, moreZones, pref->high, size, pool);
|
||||
res = arenaAllocFromLand(&tract, moreZones, pref->high, size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
}
|
||||
|
|
@ -968,13 +971,13 @@ static Res arenaAllocPolicy(Tract *tractReturn, Arena arena, SegPref pref,
|
|||
if (res != ResOK)
|
||||
return res;
|
||||
if (zones != ZoneSetEMPTY) {
|
||||
res = arenaAllocFromCBS(&tract, zones, pref->high, size, pool);
|
||||
res = arenaAllocFromLand(&tract, zones, pref->high, size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
}
|
||||
if (moreZones != zones) {
|
||||
zones = ZoneSetUnion(zones, ZoneSetDiff(arena->freeZones, pref->avoid));
|
||||
res = arenaAllocFromCBS(&tract, moreZones, pref->high, size, pool);
|
||||
res = arenaAllocFromLand(&tract, moreZones, pref->high, size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
}
|
||||
|
|
@ -986,7 +989,7 @@ static Res arenaAllocPolicy(Tract *tractReturn, Arena arena, SegPref pref,
|
|||
/* TODO: log an event for this */
|
||||
evenMoreZones = ZoneSetDiff(ZoneSetUNIV, pref->avoid);
|
||||
if (evenMoreZones != moreZones) {
|
||||
res = arenaAllocFromCBS(&tract, evenMoreZones, pref->high, size, pool);
|
||||
res = arenaAllocFromLand(&tract, evenMoreZones, pref->high, size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
}
|
||||
|
|
@ -995,7 +998,7 @@ static Res arenaAllocPolicy(Tract *tractReturn, Arena arena, SegPref pref,
|
|||
common ambiguous bit patterns pin them down, causing the zone check
|
||||
to give even more false positives permanently, and possibly retaining
|
||||
garbage indefinitely. */
|
||||
res = arenaAllocFromCBS(&tract, ZoneSetUNIV, pref->high, size, pool);
|
||||
res = arenaAllocFromLand(&tract, ZoneSetUNIV, pref->high, size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
|
||||
|
|
@ -1113,7 +1116,7 @@ void ArenaFree(Addr base, Size size, Pool pool)
|
|||
|
||||
RangeInit(&range, base, limit);
|
||||
|
||||
arenaCBSInsertSteal(&oldRange, arena, &range); /* may update range */
|
||||
arenaLandInsertSteal(&oldRange, arena, &range); /* may update range */
|
||||
|
||||
(*arena->class->free)(RangeBase(&range), RangeSize(&range), pool);
|
||||
|
||||
|
|
|
|||
329
mps/code/cbs.c
329
mps/code/cbs.c
|
|
@ -26,6 +26,7 @@ SRCID(cbs, "$Id$");
|
|||
#define CBSBlockSize(block) AddrOffset((block)->base, (block)->limit)
|
||||
|
||||
|
||||
#define cbsOfLand(land) ((CBS)(land))
|
||||
#define cbsSplay(cbs) (&((cbs)->splayTreeStruct))
|
||||
#define cbsOfSplay(_splay) PARENT(CBSStruct, splayTreeStruct, _splay)
|
||||
#define cbsBlockTree(block) (&((block)->treeStruct))
|
||||
|
|
@ -65,16 +66,14 @@ Bool CBSCheck(CBS cbs)
|
|||
{
|
||||
/* See .enter-leave.simple. */
|
||||
CHECKS(CBS, cbs);
|
||||
CHECKL(cbs != NULL);
|
||||
CHECKL(LandCheck(&cbs->landStruct));
|
||||
CHECKD(SplayTree, cbsSplay(cbs));
|
||||
/* nothing to check about treeSize */
|
||||
CHECKD(Pool, cbs->blockPool);
|
||||
CHECKU(Arena, cbs->arena);
|
||||
CHECKL(BoolCheck(cbs->fastFind));
|
||||
CHECKL(BoolCheck(cbs->inCBS));
|
||||
CHECKL(BoolCheck(cbs->ownPool));
|
||||
CHECKL(BoolCheck(cbs->zoned));
|
||||
/* No MeterCheck */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -212,7 +211,7 @@ static void cbsUpdateZonedNode(SplayTree splay, Tree tree)
|
|||
cbsUpdateNode(splay, tree);
|
||||
|
||||
block = cbsBlockOfTree(tree);
|
||||
arena = cbsOfSplay(splay)->arena;
|
||||
arena = cbsOfSplay(splay)->landStruct.arena;
|
||||
zones = ZoneSetOfRange(arena, CBSBlockBase(block), CBSBlockLimit(block));
|
||||
|
||||
if (TreeHasLeft(tree))
|
||||
|
|
@ -225,29 +224,34 @@ static void cbsUpdateZonedNode(SplayTree splay, Tree tree)
|
|||
}
|
||||
|
||||
|
||||
/* CBSInit -- Initialise a CBS structure
|
||||
/* cbsInit -- Initialise a CBS structure
|
||||
*
|
||||
* See <design/cbs/#function.cbs.init>.
|
||||
*/
|
||||
|
||||
ARG_DEFINE_KEY(cbs_extend_by, Size);
|
||||
ARG_DEFINE_KEY(cbs_block_pool, Pool);
|
||||
ARG_DEFINE_KEY(cbs_fast_find, Bool);
|
||||
ARG_DEFINE_KEY(cbs_zoned, Bool);
|
||||
|
||||
Res CBSInit(CBS cbs, Arena arena, void *owner, Align alignment,
|
||||
Bool fastFind, Bool zoned, ArgList args)
|
||||
static Res cbsInit(Land land, ArgList args)
|
||||
{
|
||||
CBS cbs;
|
||||
LandClass super;
|
||||
Size extendBy = CBS_EXTEND_BY_DEFAULT;
|
||||
Bool extendSelf = TRUE;
|
||||
Bool fastFind = FALSE;
|
||||
Bool zoned = FALSE;
|
||||
ArgStruct arg;
|
||||
Res res;
|
||||
Pool blockPool = NULL;
|
||||
SplayUpdateNodeMethod update;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
AVER(cbs != NULL);
|
||||
AVER(AlignCheck(alignment));
|
||||
AVER(BoolCheck(fastFind));
|
||||
AVER(BoolCheck(zoned));
|
||||
AVERT(Land, land);
|
||||
super = LAND_SUPERCLASS(CBSLandClass);
|
||||
res = (*super->init)(land, args);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
if (ArgPick(&arg, args, CBSBlockPool))
|
||||
blockPool = arg.val.pool;
|
||||
|
|
@ -255,6 +259,10 @@ Res CBSInit(CBS cbs, Arena arena, void *owner, Align alignment,
|
|||
extendBy = arg.val.size;
|
||||
if (ArgPick(&arg, args, MFSExtendSelf))
|
||||
extendSelf = arg.val.b;
|
||||
if (ArgPick(&arg, args, CBSFastFind))
|
||||
fastFind = arg.val.b;
|
||||
if (ArgPick(&arg, args, CBSZoned))
|
||||
zoned = arg.val.b;
|
||||
|
||||
update = SplayTrivUpdate;
|
||||
if (fastFind)
|
||||
|
|
@ -264,6 +272,7 @@ Res CBSInit(CBS cbs, Arena arena, void *owner, Align alignment,
|
|||
update = cbsUpdateZonedNode;
|
||||
}
|
||||
|
||||
cbs = cbsOfLand(land);
|
||||
SplayTreeInit(cbsSplay(cbs), cbsCompare, cbsKey, update);
|
||||
|
||||
if (blockPool != NULL) {
|
||||
|
|
@ -274,7 +283,7 @@ Res CBSInit(CBS cbs, Arena arena, void *owner, Align alignment,
|
|||
MPS_ARGS_ADD(pcArgs, MPS_KEY_MFS_UNIT_SIZE, sizeof(CBSBlockStruct));
|
||||
MPS_ARGS_ADD(pcArgs, MPS_KEY_EXTEND_BY, extendBy);
|
||||
MPS_ARGS_ADD(pcArgs, MFSExtendSelf, extendSelf);
|
||||
res = PoolCreate(&cbs->blockPool, arena, PoolClassMFS(), pcArgs);
|
||||
res = PoolCreate(&cbs->blockPool, LandArena(land), PoolClassMFS(), pcArgs);
|
||||
} MPS_ARGS_END(pcArgs);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
|
@ -282,10 +291,8 @@ Res CBSInit(CBS cbs, Arena arena, void *owner, Align alignment,
|
|||
}
|
||||
cbs->treeSize = 0;
|
||||
|
||||
cbs->arena = arena;
|
||||
cbs->fastFind = fastFind;
|
||||
cbs->zoned = zoned;
|
||||
cbs->alignment = alignment;
|
||||
cbs->inCBS = TRUE;
|
||||
|
||||
METER_INIT(cbs->treeSearch, "size of tree", (void *)cbs);
|
||||
|
|
@ -293,7 +300,6 @@ Res CBSInit(CBS cbs, Arena arena, void *owner, Align alignment,
|
|||
cbs->sig = CBSSig;
|
||||
|
||||
AVERT(CBS, cbs);
|
||||
EVENT2(CBSInit, cbs, owner);
|
||||
cbsLeave(cbs);
|
||||
return ResOK;
|
||||
}
|
||||
|
|
@ -304,8 +310,12 @@ Res CBSInit(CBS cbs, Arena arena, void *owner, Align alignment,
|
|||
* See <design/cbs/#function.cbs.finish>.
|
||||
*/
|
||||
|
||||
void CBSFinish(CBS cbs)
|
||||
static void cbsFinish(Land land)
|
||||
{
|
||||
CBS cbs;
|
||||
|
||||
AVERT(Land, land);
|
||||
cbs = cbsOfLand(land);
|
||||
AVERT(CBS, cbs);
|
||||
cbsEnter(cbs);
|
||||
|
||||
|
|
@ -427,8 +437,9 @@ static void cbsBlockInsert(CBS cbs, CBSBlock block)
|
|||
|
||||
/* cbsInsertIntoTree -- Insert a range into the tree */
|
||||
|
||||
static Res cbsInsertIntoTree(Range rangeReturn, CBS cbs, Range range)
|
||||
static Res cbsInsertIntoTree(Range rangeReturn, Land land, Range range)
|
||||
{
|
||||
CBS cbs;
|
||||
Bool b;
|
||||
Res res;
|
||||
Addr base, limit, newBase, newLimit;
|
||||
|
|
@ -438,10 +449,11 @@ static Res cbsInsertIntoTree(Range rangeReturn, CBS cbs, Range range)
|
|||
Size oldSize;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVERT(CBS, cbs);
|
||||
AVERT(Land, land);
|
||||
AVERT(Range, range);
|
||||
AVER(RangeIsAligned(range, cbs->alignment));
|
||||
AVER(RangeIsAligned(range, LandAlignment(land)));
|
||||
|
||||
cbs = cbsOfLand(land);
|
||||
base = RangeBase(range);
|
||||
limit = RangeLimit(range);
|
||||
|
||||
|
|
@ -522,7 +534,7 @@ fail:
|
|||
}
|
||||
|
||||
|
||||
/* CBSInsert -- Insert a range into the CBS
|
||||
/* cbsInsert -- Insert a range into the CBS
|
||||
*
|
||||
* See <design/cbs/#functions.cbs.insert>.
|
||||
*
|
||||
|
|
@ -530,18 +542,21 @@ fail:
|
|||
* abut an existing range.
|
||||
*/
|
||||
|
||||
Res CBSInsert(Range rangeReturn, CBS cbs, Range 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, cbs->alignment));
|
||||
AVER(RangeIsAligned(range, LandAlignment(land)));
|
||||
|
||||
res = cbsInsertIntoTree(rangeReturn, cbs, range);
|
||||
res = cbsInsertIntoTree(rangeReturn, land, range);
|
||||
|
||||
cbsLeave(cbs);
|
||||
return res;
|
||||
|
|
@ -550,18 +565,20 @@ Res CBSInsert(Range rangeReturn, CBS cbs, Range range)
|
|||
|
||||
/* cbsDeleteFromTree -- delete blocks from the tree */
|
||||
|
||||
static Res cbsDeleteFromTree(Range rangeReturn, CBS cbs, Range range)
|
||||
static Res cbsDeleteFromTree(Range rangeReturn, Land land, Range range)
|
||||
{
|
||||
CBS cbs;
|
||||
Res res;
|
||||
CBSBlock cbsBlock;
|
||||
Tree tree;
|
||||
Addr base, limit, oldBase, oldLimit;
|
||||
Size oldSize;
|
||||
|
||||
AVERT(Land, land);
|
||||
cbs = cbsOfLand(land);
|
||||
AVER(rangeReturn != NULL);
|
||||
AVERT(CBS, cbs);
|
||||
AVERT(Range, range);
|
||||
AVER(RangeIsAligned(range, cbs->alignment));
|
||||
AVER(RangeIsAligned(range, LandAlignment(land)));
|
||||
|
||||
base = RangeBase(range);
|
||||
limit = RangeLimit(range);
|
||||
|
|
@ -626,7 +643,7 @@ failSplayTreeSearch:
|
|||
}
|
||||
|
||||
|
||||
/* CBSDelete -- Remove a range from a CBS
|
||||
/* cbsDelete -- Remove a range from a CBS
|
||||
*
|
||||
* See <design/cbs/#function.cbs.delete>.
|
||||
*
|
||||
|
|
@ -634,18 +651,21 @@ failSplayTreeSearch:
|
|||
* an existing range.
|
||||
*/
|
||||
|
||||
Res CBSDelete(Range rangeReturn, CBS cbs, Range range)
|
||||
static Res cbsDelete(Range rangeReturn, Land land, Range range)
|
||||
{
|
||||
Res res;
|
||||
CBS cbs;
|
||||
Res res;
|
||||
|
||||
AVERT(Land, land);
|
||||
cbs = cbsOfLand(land);
|
||||
AVERT(CBS, cbs);
|
||||
cbsEnter(cbs);
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVERT(Range, range);
|
||||
AVER(RangeIsAligned(range, cbs->alignment));
|
||||
AVER(RangeIsAligned(range, LandAlignment(land)));
|
||||
|
||||
res = cbsDeleteFromTree(rangeReturn, cbs, range);
|
||||
res = cbsDeleteFromTree(rangeReturn, land, range);
|
||||
|
||||
cbsLeave(cbs);
|
||||
return res;
|
||||
|
|
@ -683,7 +703,7 @@ static Res cbsSplayNodeDescribe(Tree tree, mps_lib_FILE *stream)
|
|||
}
|
||||
|
||||
|
||||
/* CBSIterate -- iterate over all blocks in CBS
|
||||
/* cbsIterate -- iterate over all blocks in CBS
|
||||
*
|
||||
* Applies a visitor to all isolated contiguous ranges in a CBS.
|
||||
* It receives a pointer, ``Size`` closure pair to pass on to the
|
||||
|
|
@ -699,8 +719,8 @@ static Res cbsSplayNodeDescribe(Tree tree, mps_lib_FILE *stream)
|
|||
*/
|
||||
|
||||
typedef struct CBSIterateClosure {
|
||||
CBS cbs;
|
||||
CBSVisitor iterate;
|
||||
Land land;
|
||||
LandVisitor iterate;
|
||||
void *closureP;
|
||||
Size closureS;
|
||||
} CBSIterateClosure;
|
||||
|
|
@ -710,24 +730,28 @@ static Bool cbsIterateVisit(Tree tree, void *closureP, Size closureS)
|
|||
CBSIterateClosure *closure = closureP;
|
||||
RangeStruct range;
|
||||
CBSBlock cbsBlock;
|
||||
CBS cbs = closure->cbs;
|
||||
Land land = closure->land;
|
||||
CBS cbs = cbsOfLand(land);
|
||||
|
||||
UNUSED(closureS);
|
||||
|
||||
cbsBlock = cbsBlockOfTree(tree);
|
||||
RangeInit(&range, CBSBlockBase(cbsBlock), CBSBlockLimit(cbsBlock));
|
||||
if (!closure->iterate(cbs, &range, closure->closureP, closure->closureS))
|
||||
if (!closure->iterate(land, &range, closure->closureP, closure->closureS))
|
||||
return FALSE;
|
||||
METER_ACC(cbs->treeSearch, cbs->treeSize);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CBSIterate(CBS cbs, CBSVisitor visitor,
|
||||
void *closureP, Size closureS)
|
||||
static void cbsIterate(Land land, LandVisitor visitor,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
CBS cbs;
|
||||
SplayTree splay;
|
||||
CBSIterateClosure closure;
|
||||
|
||||
AVERT(Land, land);
|
||||
cbs = cbsOfLand(land);
|
||||
AVERT(CBS, cbs);
|
||||
cbsEnter(cbs);
|
||||
AVER(FUNCHECK(visitor));
|
||||
|
|
@ -737,7 +761,7 @@ void CBSIterate(CBS cbs, CBSVisitor visitor,
|
|||
/* searches and meter it. */
|
||||
METER_ACC(cbs->treeSearch, cbs->treeSize);
|
||||
|
||||
closure.cbs = cbs;
|
||||
closure.land = land;
|
||||
closure.iterate = visitor;
|
||||
closure.closureP = closureP;
|
||||
closure.closureS = closureS;
|
||||
|
|
@ -766,7 +790,7 @@ Bool FindDeleteCheck(FindDelete findDelete)
|
|||
/* cbsFindDeleteRange -- delete appropriate range of block found */
|
||||
|
||||
static void cbsFindDeleteRange(Range rangeReturn, Range oldRangeReturn,
|
||||
CBS cbs, Range range, Size size,
|
||||
Land land, Range range, Size size,
|
||||
FindDelete findDelete)
|
||||
{
|
||||
Bool callDelete = TRUE;
|
||||
|
|
@ -774,11 +798,11 @@ static void cbsFindDeleteRange(Range rangeReturn, Range oldRangeReturn,
|
|||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(CBS, cbs);
|
||||
AVERT(Land, land);
|
||||
AVERT(Range, range);
|
||||
AVER(RangeIsAligned(range, cbs->alignment));
|
||||
AVER(RangeIsAligned(range, LandAlignment(land)));
|
||||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, cbs->alignment));
|
||||
AVER(SizeIsAligned(size, LandAlignment(land)));
|
||||
AVER(RangeSize(range) >= size);
|
||||
AVERT(FindDelete, findDelete);
|
||||
|
||||
|
|
@ -812,7 +836,7 @@ static void cbsFindDeleteRange(Range rangeReturn, Range oldRangeReturn,
|
|||
|
||||
if (callDelete) {
|
||||
Res res;
|
||||
res = cbsDeleteFromTree(oldRangeReturn, cbs, rangeReturn);
|
||||
res = cbsDeleteFromTree(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
|
||||
|
|
@ -824,19 +848,22 @@ static void cbsFindDeleteRange(Range rangeReturn, Range oldRangeReturn,
|
|||
|
||||
/* CBSFindFirst -- find the first block of at least the given size */
|
||||
|
||||
Bool CBSFindFirst(Range rangeReturn, Range oldRangeReturn,
|
||||
CBS cbs, Size size, FindDelete findDelete)
|
||||
static Bool cbsFindFirst(Range rangeReturn, Range oldRangeReturn,
|
||||
Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
CBS cbs;
|
||||
Bool found;
|
||||
Tree tree;
|
||||
|
||||
AVERT(Land, land);
|
||||
cbs = cbsOfLand(land);
|
||||
AVERT(CBS, cbs);
|
||||
cbsEnter(cbs);
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, cbs->alignment));
|
||||
AVER(SizeIsAligned(size, LandAlignment(land)));
|
||||
AVER(cbs->fastFind);
|
||||
AVERT(FindDelete, findDelete);
|
||||
|
||||
|
|
@ -850,7 +877,7 @@ Bool CBSFindFirst(Range rangeReturn, Range oldRangeReturn,
|
|||
AVER(CBSBlockSize(block) >= size);
|
||||
RangeInit(&range, CBSBlockBase(block), CBSBlockLimit(block));
|
||||
AVER(RangeSize(&range) >= size);
|
||||
cbsFindDeleteRange(rangeReturn, oldRangeReturn, cbs, &range,
|
||||
cbsFindDeleteRange(rangeReturn, oldRangeReturn, land, &range,
|
||||
size, findDelete);
|
||||
}
|
||||
|
||||
|
|
@ -858,8 +885,10 @@ Bool CBSFindFirst(Range rangeReturn, Range oldRangeReturn,
|
|||
return found;
|
||||
}
|
||||
|
||||
/* CBSFindFirstInZones -- find the first block of at least the given size
|
||||
that lies entirely within a zone set */
|
||||
/* cbsFindInZones -- find a block of at least the given size that lies
|
||||
* entirely within a zone set. (The first such block, if high is
|
||||
* FALSE, or the last, if high is TRUE.)
|
||||
*/
|
||||
|
||||
typedef struct cbsTestNodeInZonesClosureStruct {
|
||||
Size size;
|
||||
|
|
@ -902,90 +931,25 @@ static Bool cbsTestTreeInZones(SplayTree splay, Tree tree,
|
|||
ZoneSetInter(block->zones, closure->zoneSet) != ZoneSetEMPTY;
|
||||
}
|
||||
|
||||
Res CBSFindInZones(Range rangeReturn, Range oldRangeReturn,
|
||||
CBS cbs, Size size,
|
||||
ZoneSet zoneSet, Bool high)
|
||||
{
|
||||
Tree tree;
|
||||
cbsTestNodeInZonesClosureStruct closure;
|
||||
Res res;
|
||||
CBSFindMethod cbsFind;
|
||||
SplayFindMethod splayFind;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(CBS, cbs);
|
||||
/* AVER(ZoneSetCheck(zoneSet)); */
|
||||
AVER(BoolCheck(high));
|
||||
|
||||
cbsFind = high ? CBSFindLast : CBSFindFirst;
|
||||
splayFind = high ? SplayFindLast : SplayFindFirst;
|
||||
|
||||
if (zoneSet == ZoneSetEMPTY)
|
||||
return ResFAIL;
|
||||
if (zoneSet == ZoneSetUNIV) {
|
||||
FindDelete fd = high ? FindDeleteHIGH : FindDeleteLOW;
|
||||
if (cbsFind(rangeReturn, oldRangeReturn, cbs, size, fd))
|
||||
return ResOK;
|
||||
else
|
||||
return ResFAIL;
|
||||
}
|
||||
if (ZoneSetIsSingle(zoneSet) && size > ArenaStripeSize(cbs->arena))
|
||||
return ResFAIL;
|
||||
|
||||
/* 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 = cbs->arena;
|
||||
closure.zoneSet = zoneSet;
|
||||
closure.size = size;
|
||||
closure.high = high;
|
||||
if (splayFind(&tree, cbsSplay(cbs),
|
||||
cbsTestNodeInZones,
|
||||
cbsTestTreeInZones,
|
||||
&closure, sizeof(closure))) {
|
||||
CBSBlock block = cbsBlockOfTree(tree);
|
||||
RangeStruct rangeStruct, oldRangeStruct;
|
||||
|
||||
AVER(CBSBlockBase(block) <= closure.base);
|
||||
AVER(AddrOffset(closure.base, closure.limit) >= size);
|
||||
AVER(ZoneSetSub(ZoneSetOfRange(cbs->arena, closure.base, closure.limit), zoneSet));
|
||||
AVER(closure.limit <= CBSBlockLimit(block));
|
||||
|
||||
if (!high)
|
||||
RangeInit(&rangeStruct, closure.base, AddrAdd(closure.base, size));
|
||||
else
|
||||
RangeInit(&rangeStruct, AddrSub(closure.limit, size), closure.limit);
|
||||
res = cbsDeleteFromTree(&oldRangeStruct, cbs, &rangeStruct);
|
||||
if (res == ResOK) { /* enough memory to split block */
|
||||
RangeCopy(rangeReturn, &rangeStruct);
|
||||
RangeCopy(oldRangeReturn, &oldRangeStruct);
|
||||
}
|
||||
} else
|
||||
res = ResFAIL;
|
||||
|
||||
cbsLeave(cbs);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* CBSFindLast -- find the last block of at least the given size */
|
||||
|
||||
Bool CBSFindLast(Range rangeReturn, Range oldRangeReturn,
|
||||
CBS cbs, Size size, FindDelete findDelete)
|
||||
|
||||
/* cbsFindLast -- find the last block of at least the given size */
|
||||
|
||||
static Bool cbsFindLast(Range rangeReturn, Range oldRangeReturn,
|
||||
Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
CBS cbs;
|
||||
Bool found;
|
||||
Tree tree;
|
||||
|
||||
AVERT(Land, land);
|
||||
cbs = cbsOfLand(land);
|
||||
AVERT(CBS, cbs);
|
||||
cbsEnter(cbs);
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, cbs->alignment));
|
||||
AVER(SizeIsAligned(size, LandAlignment(land)));
|
||||
AVER(cbs->fastFind);
|
||||
AVERT(FindDelete, findDelete);
|
||||
|
||||
|
|
@ -999,7 +963,7 @@ Bool CBSFindLast(Range rangeReturn, Range oldRangeReturn,
|
|||
AVER(CBSBlockSize(block) >= size);
|
||||
RangeInit(&range, CBSBlockBase(block), CBSBlockLimit(block));
|
||||
AVER(RangeSize(&range) >= size);
|
||||
cbsFindDeleteRange(rangeReturn, oldRangeReturn, cbs, &range,
|
||||
cbsFindDeleteRange(rangeReturn, oldRangeReturn, land, &range,
|
||||
size, findDelete);
|
||||
}
|
||||
|
||||
|
|
@ -1008,13 +972,16 @@ Bool CBSFindLast(Range rangeReturn, Range oldRangeReturn,
|
|||
}
|
||||
|
||||
|
||||
/* CBSFindLargest -- find the largest block in the CBS */
|
||||
/* cbsFindLargest -- find the largest block in the CBS */
|
||||
|
||||
Bool CBSFindLargest(Range rangeReturn, Range oldRangeReturn,
|
||||
CBS cbs, Size size, FindDelete findDelete)
|
||||
static Bool cbsFindLargest(Range rangeReturn, Range oldRangeReturn,
|
||||
Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
CBS cbs;
|
||||
Bool found = FALSE;
|
||||
|
||||
AVERT(Land, land);
|
||||
cbs = cbsOfLand(land);
|
||||
AVERT(CBS, cbs);
|
||||
cbsEnter(cbs);
|
||||
|
||||
|
|
@ -1039,7 +1006,7 @@ Bool CBSFindLargest(Range rangeReturn, Range oldRangeReturn,
|
|||
AVER(CBSBlockSize(block) >= maxSize);
|
||||
RangeInit(&range, CBSBlockBase(block), CBSBlockLimit(block));
|
||||
AVER(RangeSize(&range) >= maxSize);
|
||||
cbsFindDeleteRange(rangeReturn, oldRangeReturn, cbs, &range,
|
||||
cbsFindDeleteRange(rangeReturn, oldRangeReturn, land, &range,
|
||||
maxSize, findDelete);
|
||||
}
|
||||
}
|
||||
|
|
@ -1049,15 +1016,91 @@ Bool CBSFindLargest(Range rangeReturn, Range oldRangeReturn,
|
|||
}
|
||||
|
||||
|
||||
/* CBSDescribe -- describe a CBS
|
||||
static Res cbsFindInZones(Range rangeReturn, Range oldRangeReturn,
|
||||
Land land, Size size,
|
||||
ZoneSet zoneSet, Bool high)
|
||||
{
|
||||
CBS cbs;
|
||||
Tree tree;
|
||||
cbsTestNodeInZonesClosureStruct closure;
|
||||
Res res;
|
||||
LandFindMethod landFind;
|
||||
SplayFindMethod splayFind;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
cbs = cbsOfLand(land);
|
||||
AVERT(CBS, cbs);
|
||||
/* AVER(ZoneSetCheck(zoneSet)); */
|
||||
AVER(BoolCheck(high));
|
||||
|
||||
landFind = high ? cbsFindLast : cbsFindFirst;
|
||||
splayFind = high ? SplayFindLast : SplayFindFirst;
|
||||
|
||||
if (zoneSet == ZoneSetEMPTY)
|
||||
return ResFAIL;
|
||||
if (zoneSet == ZoneSetUNIV) {
|
||||
FindDelete fd = high ? FindDeleteHIGH : FindDeleteLOW;
|
||||
if ((*landFind)(rangeReturn, oldRangeReturn, land, size, fd))
|
||||
return ResOK;
|
||||
else
|
||||
return ResFAIL;
|
||||
}
|
||||
if (ZoneSetIsSingle(zoneSet) && size > ArenaStripeSize(LandArena(land)))
|
||||
return ResFAIL;
|
||||
|
||||
/* 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;
|
||||
closure.high = high;
|
||||
if (splayFind(&tree, cbsSplay(cbs),
|
||||
cbsTestNodeInZones,
|
||||
cbsTestTreeInZones,
|
||||
&closure, sizeof(closure))) {
|
||||
CBSBlock block = cbsBlockOfTree(tree);
|
||||
RangeStruct rangeStruct, oldRangeStruct;
|
||||
|
||||
AVER(CBSBlockBase(block) <= closure.base);
|
||||
AVER(AddrOffset(closure.base, closure.limit) >= size);
|
||||
AVER(ZoneSetSub(ZoneSetOfRange(LandArena(land), closure.base, closure.limit), zoneSet));
|
||||
AVER(closure.limit <= CBSBlockLimit(block));
|
||||
|
||||
if (!high)
|
||||
RangeInit(&rangeStruct, closure.base, AddrAdd(closure.base, size));
|
||||
else
|
||||
RangeInit(&rangeStruct, AddrSub(closure.limit, size), closure.limit);
|
||||
res = cbsDeleteFromTree(&oldRangeStruct, land, &rangeStruct);
|
||||
if (res == ResOK) { /* enough memory to split block */
|
||||
RangeCopy(rangeReturn, &rangeStruct);
|
||||
RangeCopy(oldRangeReturn, &oldRangeStruct);
|
||||
}
|
||||
} else
|
||||
res = ResFAIL;
|
||||
|
||||
cbsLeave(cbs);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* cbsDescribe -- describe a CBS
|
||||
*
|
||||
* See <design/cbs/#function.cbs.describe>.
|
||||
*/
|
||||
|
||||
Res CBSDescribe(CBS cbs, mps_lib_FILE *stream)
|
||||
static Res cbsDescribe(Land land, mps_lib_FILE *stream)
|
||||
{
|
||||
CBS cbs;
|
||||
Res res;
|
||||
|
||||
if (!TESTT(Land, land))
|
||||
return ResFAIL;
|
||||
cbs = cbsOfLand(land);
|
||||
if (!TESTT(CBS, cbs))
|
||||
return ResFAIL;
|
||||
if (stream == NULL)
|
||||
|
|
@ -1065,7 +1108,6 @@ Res CBSDescribe(CBS cbs, mps_lib_FILE *stream)
|
|||
|
||||
res = WriteF(stream,
|
||||
"CBS $P {\n", (WriteFP)cbs,
|
||||
" alignment: $U\n", (WriteFU)cbs->alignment,
|
||||
" blockPool: $P\n", (WriteFP)cbsBlockPool(cbs),
|
||||
" fastFind: $U\n", (WriteFU)cbs->fastFind,
|
||||
" inCBS: $U\n", (WriteFU)cbs->inCBS,
|
||||
|
|
@ -1084,6 +1126,27 @@ Res CBSDescribe(CBS cbs, mps_lib_FILE *stream)
|
|||
}
|
||||
|
||||
|
||||
typedef LandClassStruct CBSLandClassStruct;
|
||||
|
||||
DEFINE_CLASS(CBSLandClass, class)
|
||||
{
|
||||
INHERIT_CLASS(class, LandClass);
|
||||
class->name = "CBS";
|
||||
class->size = sizeof(CBSStruct);
|
||||
class->init = cbsInit;
|
||||
class->finish = cbsFinish;
|
||||
class->insert = cbsInsert;
|
||||
class->delete = cbsDelete;
|
||||
class->iterate = cbsIterate;
|
||||
class->findFirst = cbsFindFirst;
|
||||
class->findLast = cbsFindLast;
|
||||
class->findLargest = cbsFindLargest;
|
||||
class->findInZones = cbsFindInZones;
|
||||
class->describe = cbsDescribe;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
#include "range.h"
|
||||
#include "splay.h"
|
||||
|
||||
|
||||
/* TODO: There ought to be different levels of CBS block with inheritance
|
||||
so that CBSs without fastFind don't allocate the maxSize and zones fields,
|
||||
and CBSs without zoned don't allocate the zones field. */
|
||||
|
|
@ -29,40 +28,21 @@ typedef struct CBSBlockStruct {
|
|||
ZoneSet zones; /* union zone set of all ranges in sub-tree */
|
||||
} CBSBlockStruct;
|
||||
|
||||
|
||||
typedef struct CBSStruct *CBS;
|
||||
typedef Bool (*CBSVisitor)(CBS cbs, Range range,
|
||||
void *closureP, Size closureS);
|
||||
|
||||
extern Bool CBSCheck(CBS cbs);
|
||||
|
||||
extern CBSLandClass CBSLandClassGet(void);
|
||||
|
||||
extern const struct mps_key_s _mps_key_cbs_block_pool;
|
||||
#define CBSBlockPool (&_mps_key_cbs_block_pool)
|
||||
#define CBSBlockPool_FIELD pool
|
||||
extern const struct mps_key_s _mps_key_cbs_fast_find;
|
||||
#define CBSFastFind (&_mps_key_cbs_fast_find)
|
||||
#define CBSFastFind_FIELD b
|
||||
extern const struct mps_key_s _mps_key_cbs_zoned;
|
||||
#define CBSZoned (&_mps_key_cbs_zoned)
|
||||
#define CBSZoned_FIELD b
|
||||
|
||||
/* TODO: Passing booleans to affect behaviour is ugly and error-prone. */
|
||||
extern Res CBSInit(CBS cbs, Arena arena, void *owner, Align alignment,
|
||||
Bool fastFind, Bool zoned, ArgList args);
|
||||
extern void CBSFinish(CBS cbs);
|
||||
|
||||
extern Res CBSInsert(Range rangeReturn, CBS cbs, Range range);
|
||||
extern Res CBSDelete(Range rangeReturn, CBS cbs, Range range);
|
||||
extern void CBSIterate(CBS cbs, CBSVisitor visitor,
|
||||
void *closureP, Size closureS);
|
||||
|
||||
extern Res CBSDescribe(CBS cbs, mps_lib_FILE *stream);
|
||||
|
||||
typedef Bool (*CBSFindMethod)(Range rangeReturn, Range oldRangeReturn,
|
||||
CBS cbs, Size size, FindDelete findDelete);
|
||||
extern Bool CBSFindFirst(Range rangeReturn, Range oldRangeReturn,
|
||||
CBS cbs, Size size, FindDelete findDelete);
|
||||
extern Bool CBSFindLast(Range rangeReturn, Range oldRangeReturn,
|
||||
CBS cbs, Size size, FindDelete findDelete);
|
||||
extern Bool CBSFindLargest(Range rangeReturn, Range oldRangeReturn,
|
||||
CBS cbs, Size size, FindDelete findDelete);
|
||||
|
||||
extern Res CBSFindInZones(Range rangeReturn, Range oldRangeReturn,
|
||||
CBS cbs, Size size, ZoneSet zoneSet, Bool high);
|
||||
|
||||
#endif /* cbs_h */
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@
|
|||
EVENT(X, PoolFinish , 0x0016, TRUE, Pool) \
|
||||
EVENT(X, PoolAlloc , 0x0017, TRUE, Object) \
|
||||
EVENT(X, PoolFree , 0x0018, TRUE, Object) \
|
||||
EVENT(X, CBSInit , 0x0019, TRUE, Pool) \
|
||||
EVENT(X, LandInit , 0x0019, TRUE, Pool) \
|
||||
EVENT(X, Intern , 0x001a, TRUE, User) \
|
||||
EVENT(X, Label , 0x001b, TRUE, User) \
|
||||
EVENT(X, TraceStart , 0x001c, TRUE, Trace) \
|
||||
|
|
@ -311,8 +311,8 @@
|
|||
PARAM(X, 1, A, old) \
|
||||
PARAM(X, 2, W, size)
|
||||
|
||||
#define EVENT_CBSInit_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, P, cbs) \
|
||||
#define EVENT_LandInit_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, P, land) \
|
||||
PARAM(X, 1, P, owner)
|
||||
|
||||
#define EVENT_Intern_PARAMS(PARAM, X) \
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ typedef struct FBMStateStruct {
|
|||
BT allocTable;
|
||||
Addr block;
|
||||
union {
|
||||
CBS cbs;
|
||||
Land land;
|
||||
Freelist fl;
|
||||
} the;
|
||||
} FBMStateStruct, *FBMState;
|
||||
|
|
@ -83,7 +83,7 @@ static Index (indexOfAddr)(FBMState state, Addr a)
|
|||
static void describe(FBMState state) {
|
||||
switch (state->type) {
|
||||
case FBMTypeCBS:
|
||||
die(CBSDescribe(state->the.cbs, mps_lib_get_stdout()), "CBSDescribe");
|
||||
die(LandDescribe(state->the.land, mps_lib_get_stdout()), "LandDescribe");
|
||||
break;
|
||||
case FBMTypeFreelist:
|
||||
die(FreelistDescribe(state->the.fl, mps_lib_get_stdout()), "FreelistDescribe");
|
||||
|
|
@ -125,10 +125,10 @@ static Bool checkCallback(Range range, void *closureP, Size closureS)
|
|||
}
|
||||
|
||||
|
||||
static Bool checkCBSCallback(CBS cbs, Range range,
|
||||
static Bool checkCBSCallback(Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
UNUSED(cbs);
|
||||
UNUSED(land);
|
||||
return checkCallback(range, closureP, closureS);
|
||||
}
|
||||
|
||||
|
|
@ -151,7 +151,7 @@ static void check(FBMState state)
|
|||
|
||||
switch (state->type) {
|
||||
case FBMTypeCBS:
|
||||
CBSIterate(state->the.cbs, checkCBSCallback, (void *)&closure, 0);
|
||||
LandIterate(state->the.land, checkCBSCallback, (void *)&closure, 0);
|
||||
break;
|
||||
case FBMTypeFreelist:
|
||||
FreelistIterate(state->the.fl, checkFLCallback, (void *)&closure, 0);
|
||||
|
|
@ -305,7 +305,7 @@ static void allocate(FBMState state, Addr base, Addr limit)
|
|||
RangeInit(&range, base, limit);
|
||||
switch (state->type) {
|
||||
case FBMTypeCBS:
|
||||
res = CBSDelete(&oldRange, state->the.cbs, &range);
|
||||
res = LandDelete(&oldRange, state->the.land, &range);
|
||||
break;
|
||||
case FBMTypeFreelist:
|
||||
res = FreelistDelete(&oldRange, state->the.fl, &range);
|
||||
|
|
@ -381,7 +381,7 @@ static void deallocate(FBMState state, Addr base, Addr limit)
|
|||
RangeInit(&range, base, limit);
|
||||
switch (state->type) {
|
||||
case FBMTypeCBS:
|
||||
res = CBSInsert(&freeRange, state->the.cbs, &range);
|
||||
res = LandInsert(&freeRange, state->the.land, &range);
|
||||
break;
|
||||
case FBMTypeFreelist:
|
||||
res = FreelistInsert(&freeRange, state->the.fl, &range);
|
||||
|
|
@ -459,8 +459,8 @@ static void find(FBMState state, Size size, Bool high, FindDelete findDelete)
|
|||
|
||||
switch (state->type) {
|
||||
case FBMTypeCBS:
|
||||
found = (high ? CBSFindLast : CBSFindFirst)
|
||||
(&foundRange, &oldRange, state->the.cbs, size * state->align, findDelete);
|
||||
found = (high ? LandFindLast : LandFindFirst)
|
||||
(&foundRange, &oldRange, state->the.land, size * state->align, findDelete);
|
||||
break;
|
||||
case FBMTypeFreelist:
|
||||
found = (high ? FreelistFindLast : FreelistFindFirst)
|
||||
|
|
@ -558,6 +558,7 @@ extern int main(int argc, char *argv[])
|
|||
BT allocTable;
|
||||
FreelistStruct flStruct;
|
||||
CBSStruct cbsStruct;
|
||||
Land land = (Land)&cbsStruct;
|
||||
Align align;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
|
@ -585,16 +586,18 @@ extern int main(int argc, char *argv[])
|
|||
(char *)dummyBlock + ArraySize);
|
||||
}
|
||||
|
||||
die((mps_res_t)CBSInit(&cbsStruct, arena, arena, align,
|
||||
/* fastFind */ TRUE, /* zoned */ FALSE, mps_args_none),
|
||||
"failed to initialise CBS");
|
||||
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.cbs = &cbsStruct;
|
||||
state.the.land = land;
|
||||
test(&state, nCBSOperations);
|
||||
CBSFinish(&cbsStruct);
|
||||
LandFinish(land);
|
||||
|
||||
die((mps_res_t)FreelistInit(&flStruct, align),
|
||||
"failed to initialise Freelist");
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@
|
|||
|
||||
/* Accessors for the CBS used to implement a pool. */
|
||||
|
||||
extern CBS _mps_mvff_cbs(mps_pool_t);
|
||||
extern CBS _mps_mvt_cbs(mps_pool_t);
|
||||
extern Land _mps_mvff_cbs(mps_pool_t);
|
||||
extern Land _mps_mvt_cbs(mps_pool_t);
|
||||
|
||||
|
||||
/* "OOM" pool class -- dummy alloc/free pool class whose alloc()
|
||||
|
|
@ -180,7 +180,7 @@ int main(int argc, char *argv[])
|
|||
die(mps_pool_create_k(&pool, arena, mps_class_mvff(), args), "create MVFF");
|
||||
} MPS_ARGS_END(args);
|
||||
{
|
||||
CBS cbs = _mps_mvff_cbs(pool);
|
||||
CBS cbs = (CBS)_mps_mvff_cbs(pool);
|
||||
die(stress(randomSizeAligned, alignment, pool, cbs), "stress MVFF");
|
||||
}
|
||||
mps_pool_destroy(pool);
|
||||
|
|
@ -199,7 +199,7 @@ int main(int argc, char *argv[])
|
|||
die(mps_pool_create_k(&pool, arena, mps_class_mvt(), args), "create MVFF");
|
||||
} MPS_ARGS_END(args);
|
||||
{
|
||||
CBS cbs = _mps_mvt_cbs(pool);
|
||||
CBS cbs = (CBS)_mps_mvt_cbs(pool);
|
||||
die(stress(randomSizeAligned, alignment, pool, cbs), "stress MVT");
|
||||
}
|
||||
mps_pool_destroy(pool);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
* .sources: <design/freelist/>.
|
||||
*/
|
||||
|
||||
#include "cbs.h"
|
||||
#include "freelist.h"
|
||||
#include "mpm.h"
|
||||
|
||||
|
|
@ -589,22 +588,22 @@ Res FreelistDescribe(Freelist fl, mps_lib_FILE *stream)
|
|||
|
||||
|
||||
/* freelistFlushIterateMethod -- Iterate method for
|
||||
* FreelistFlushToCBS. Attempst to insert the range into the CBS.
|
||||
* FreelistFlushToLand. Attempst to insert the range into the Land.
|
||||
*/
|
||||
static Bool freelistFlushIterateMethod(Bool *deleteReturn, Range range,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
Res res;
|
||||
RangeStruct newRange;
|
||||
CBS cbs;
|
||||
Land land;
|
||||
|
||||
AVER(deleteReturn != NULL);
|
||||
AVERT(Range, range);
|
||||
AVER(closureP != NULL);
|
||||
UNUSED(closureS);
|
||||
|
||||
cbs = closureP;
|
||||
res = CBSInsert(&newRange, cbs, range);
|
||||
land = closureP;
|
||||
res = LandInsert(&newRange, land, range);
|
||||
if (res == ResOK) {
|
||||
*deleteReturn = TRUE;
|
||||
return TRUE;
|
||||
|
|
@ -615,12 +614,12 @@ static Bool freelistFlushIterateMethod(Bool *deleteReturn, Range range,
|
|||
}
|
||||
|
||||
|
||||
void FreelistFlushToCBS(Freelist fl, CBS cbs)
|
||||
void FreelistFlushToLand(Freelist fl, Land land)
|
||||
{
|
||||
AVERT(Freelist, fl);
|
||||
AVERT(CBS, cbs);
|
||||
AVERT(Land, land);
|
||||
|
||||
FreelistIterate(fl, freelistFlushIterateMethod, cbs, 0);
|
||||
FreelistIterate(fl, freelistFlushIterateMethod, land, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#ifndef freelist_h
|
||||
#define freelist_h
|
||||
|
||||
#include "cbs.h"
|
||||
#include "mpmtypes.h"
|
||||
#include "range.h"
|
||||
|
||||
|
|
@ -46,7 +45,7 @@ extern Bool FreelistFindLast(Range rangeReturn, Range oldRangeReturn,
|
|||
extern Bool FreelistFindLargest(Range rangeReturn, Range oldRangeReturn,
|
||||
Freelist fl, Size size, FindDelete findDelete);
|
||||
|
||||
extern void FreelistFlushToCBS(Freelist fl, CBS cbs);
|
||||
extern void FreelistFlushToLand(Freelist fl, Land land);
|
||||
|
||||
#endif /* freelist.h */
|
||||
|
||||
|
|
|
|||
348
mps/code/land.c
Normal file
348
mps/code/land.c
Normal file
|
|
@ -0,0 +1,348 @@
|
|||
/* land.c: LAND (COLLECTION OF ADDRESS RANGES) IMPLEMENTATION
|
||||
*
|
||||
* $Id: //info.ravenbrook.com/project/mps/branch/2014-03-30/land/code/land.c#1 $
|
||||
* Copyright (c) 2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .design: <design/land/>
|
||||
*/
|
||||
|
||||
#include "mpm.h"
|
||||
|
||||
SRCID(land, "$Id$");
|
||||
|
||||
|
||||
Bool LandCheck(Land land)
|
||||
{
|
||||
CHECKS(Land, land);
|
||||
CHECKU(Arena, land->arena);
|
||||
CHECKL(AlignCheck(land->alignment));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Res LandInit(Land land, LandClass class, Arena arena, Align alignment, void *owner, ArgList args)
|
||||
{
|
||||
Res res;
|
||||
|
||||
AVER(land != NULL);
|
||||
AVERT(LandClass, class);
|
||||
AVER(AlignCheck(alignment));
|
||||
|
||||
land->alignment = alignment;
|
||||
land->arena = arena;
|
||||
land->class = class;
|
||||
land->sig = LandSig;
|
||||
|
||||
AVERT(Land, land);
|
||||
|
||||
res = (*class->init)(land, args);
|
||||
if (res != ResOK)
|
||||
goto failInit;
|
||||
|
||||
EVENT2(LandInit, land, owner);
|
||||
return ResOK;
|
||||
|
||||
failInit:
|
||||
land->sig = SigInvalid;
|
||||
return res;
|
||||
}
|
||||
|
||||
Res LandCreate(Land *landReturn, Arena arena, LandClass class, Align alignment, void *owner, ArgList args)
|
||||
{
|
||||
Res res;
|
||||
Land land;
|
||||
void *p;
|
||||
|
||||
AVER(landReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVERT(LandClass, class);
|
||||
|
||||
res = ControlAlloc(&p, arena, class->size,
|
||||
/* withReservoirPermit */ FALSE);
|
||||
if (res != ResOK)
|
||||
goto failAlloc;
|
||||
land = p;
|
||||
|
||||
res = LandInit(land, class, arena, alignment, owner, args);
|
||||
if (res != ResOK)
|
||||
goto failInit;
|
||||
|
||||
*landReturn = land;
|
||||
return ResOK;
|
||||
|
||||
failInit:
|
||||
ControlFree(arena, land, class->size);
|
||||
failAlloc:
|
||||
return res;
|
||||
}
|
||||
|
||||
void LandDestroy(Land land)
|
||||
{
|
||||
Arena arena;
|
||||
LandClass class;
|
||||
|
||||
AVERT(Land, land);
|
||||
arena = land->arena;
|
||||
class = land->class;
|
||||
AVERT(LandClass, class);
|
||||
LandFinish(land);
|
||||
ControlFree(arena, land, class->size);
|
||||
}
|
||||
|
||||
void LandFinish(Land land)
|
||||
{
|
||||
AVERT(Land, land);
|
||||
(*land->class->finish)(land);
|
||||
}
|
||||
|
||||
Res LandInsert(Range rangeReturn, Land land, Range range)
|
||||
{
|
||||
AVER(rangeReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
AVERT(Range, range);
|
||||
AVER(RangeIsAligned(range, land->alignment));
|
||||
|
||||
return (*land->class->insert)(rangeReturn, land, range);
|
||||
}
|
||||
|
||||
Res LandDelete(Range rangeReturn, Land land, Range range)
|
||||
{
|
||||
AVER(rangeReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
AVERT(Range, range);
|
||||
AVER(RangeIsAligned(range, land->alignment));
|
||||
|
||||
return (*land->class->delete)(rangeReturn, land, range);
|
||||
}
|
||||
|
||||
void LandIterate(Land land, LandVisitor visitor, void *closureP, Size closureS)
|
||||
{
|
||||
AVERT(Land, land);
|
||||
AVER(FUNCHECK(visitor));
|
||||
|
||||
(*land->class->iterate)(land, visitor, closureP, closureS);
|
||||
}
|
||||
|
||||
Bool LandFindFirst(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
AVER(SizeIsAligned(size, land->alignment));
|
||||
AVER(FindDeleteCheck(findDelete));
|
||||
|
||||
return (*land->class->findFirst)(rangeReturn, oldRangeReturn, land, size,
|
||||
findDelete);
|
||||
}
|
||||
|
||||
Bool LandFindLast(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
AVER(SizeIsAligned(size, land->alignment));
|
||||
AVER(FindDeleteCheck(findDelete));
|
||||
|
||||
return (*land->class->findLast)(rangeReturn, oldRangeReturn, land, size,
|
||||
findDelete);
|
||||
}
|
||||
|
||||
Bool LandFindLargest(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
AVER(SizeIsAligned(size, land->alignment));
|
||||
AVER(FindDeleteCheck(findDelete));
|
||||
|
||||
return (*land->class->findLargest)(rangeReturn, oldRangeReturn, land, size,
|
||||
findDelete);
|
||||
}
|
||||
|
||||
Res LandFindInZones(Range rangeReturn, Range oldRangeReturn, Land land, Size size, ZoneSet zoneSet, Bool high)
|
||||
{
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
AVER(SizeIsAligned(size, land->alignment));
|
||||
/* AVER(ZoneSetCheck(zoneSet)); */
|
||||
AVER(BoolCheck(high));
|
||||
|
||||
return (*land->class->findInZones)(rangeReturn, oldRangeReturn, land, size,
|
||||
zoneSet, high);
|
||||
}
|
||||
|
||||
Res LandDescribe(Land land, mps_lib_FILE *stream)
|
||||
{
|
||||
Res res;
|
||||
|
||||
if (!TESTT(Land, land)) return ResFAIL;
|
||||
if (stream == NULL) return ResFAIL;
|
||||
|
||||
res = WriteF(stream,
|
||||
"Land $P {\n", (WriteFP)land,
|
||||
" class $P", (WriteFP)land->class,
|
||||
" (\"$S\")\n", land->class->name,
|
||||
" arena $P\n", (WriteFP)land->arena,
|
||||
" align $U\n", (WriteFU)land->alignment,
|
||||
NULL);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = (*land->class->describe)(land, stream);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = WriteF(stream, "} Land $P\n", (WriteFP)land, NULL);
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
Bool LandClassCheck(LandClass class)
|
||||
{
|
||||
CHECKL(ProtocolClassCheck(&class->protocol));
|
||||
CHECKL(class->name != NULL); /* Should be <=6 char C identifier */
|
||||
CHECKL(class->size >= sizeof(LandStruct));
|
||||
CHECKL(FUNCHECK(class->init));
|
||||
CHECKL(FUNCHECK(class->finish));
|
||||
CHECKL(FUNCHECK(class->insert));
|
||||
CHECKL(FUNCHECK(class->delete));
|
||||
CHECKL(FUNCHECK(class->findFirst));
|
||||
CHECKL(FUNCHECK(class->findLast));
|
||||
CHECKL(FUNCHECK(class->findLargest));
|
||||
CHECKL(FUNCHECK(class->findInZones));
|
||||
CHECKL(FUNCHECK(class->describe));
|
||||
CHECKS(LandClass, class);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static Res landTrivInit(Land land, ArgList args)
|
||||
{
|
||||
AVERT(Land, land);
|
||||
AVER(ArgListCheck(args));
|
||||
UNUSED(args);
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
static void landTrivFinish(Land land)
|
||||
{
|
||||
AVERT(Land, land);
|
||||
NOOP;
|
||||
}
|
||||
|
||||
static Res landNoInsert(Range rangeReturn, Land land, Range range)
|
||||
{
|
||||
AVER(rangeReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
AVERT(Range, range);
|
||||
return ResUNIMPL;
|
||||
}
|
||||
|
||||
static Res landNoDelete(Range rangeReturn, Land land, Range range)
|
||||
{
|
||||
AVER(rangeReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
AVERT(Range, range);
|
||||
return ResUNIMPL;
|
||||
}
|
||||
|
||||
static void landNoIterate(Land land, LandVisitor visitor, void *closureP, Size closureS)
|
||||
{
|
||||
AVERT(Land, land);
|
||||
AVER(visitor != NULL);
|
||||
UNUSED(closureP);
|
||||
UNUSED(closureS);
|
||||
NOOP;
|
||||
}
|
||||
|
||||
static Bool landNoFind(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
UNUSED(size);
|
||||
AVER(FindDeleteCheck(findDelete));
|
||||
return ResUNIMPL;
|
||||
}
|
||||
|
||||
static Res landNoFindInZones(Range rangeReturn, Range oldRangeReturn, Land land, Size size, ZoneSet zoneSet, Bool high)
|
||||
{
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
UNUSED(size);
|
||||
UNUSED(zoneSet);
|
||||
AVER(BoolCheck(high));
|
||||
return ResUNIMPL;
|
||||
}
|
||||
|
||||
static Res landTrivDescribe(Land land, mps_lib_FILE *stream)
|
||||
{
|
||||
if (!TESTT(Land, land))
|
||||
return ResFAIL;
|
||||
if (stream == NULL)
|
||||
return ResFAIL;
|
||||
/* dispatching function does it all */
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
DEFINE_CLASS(LandClass, class)
|
||||
{
|
||||
INHERIT_CLASS(&class->protocol, ProtocolClass);
|
||||
class->name = "LAND";
|
||||
class->size = sizeof(LandStruct);
|
||||
class->init = landTrivInit;
|
||||
class->finish = landTrivFinish;
|
||||
class->insert = landNoInsert;
|
||||
class->delete = landNoDelete;
|
||||
class->iterate = landNoIterate;
|
||||
class->findFirst = landNoFind;
|
||||
class->findLast = landNoFind;
|
||||
class->findLargest = landNoFind;
|
||||
class->findInZones = landNoFindInZones;
|
||||
class->describe = landTrivDescribe;
|
||||
class->sig = LandClassSig;
|
||||
AVERT(LandClass, class);
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Redistributions in any form must be accompanied by information on how
|
||||
* to obtain complete source code for this software and any accompanying
|
||||
* software that uses this software. The source code must either be
|
||||
* included in the distribution or be available for no more than the cost
|
||||
* of distribution plus a nominal fee, and must be freely redistributable
|
||||
* under reasonable conditions. For an executable file, complete source
|
||||
* code means the source code for all modules it contains. It does not
|
||||
* include source code for modules or files that typically accompany the
|
||||
* major components of the operating system on which the executable file
|
||||
* runs.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
|
@ -480,6 +480,7 @@ void LocusInit(Arena arena)
|
|||
gen->proflow = 0.0;
|
||||
RingInit(&gen->locusRing);
|
||||
gen->sig = GenDescSig;
|
||||
AVERT(GenDesc, gen);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -490,8 +490,8 @@ extern void ArenaFinish(Arena arena);
|
|||
extern Res ArenaDescribe(Arena arena, mps_lib_FILE *stream);
|
||||
extern Res ArenaDescribeTracts(Arena arena, mps_lib_FILE *stream);
|
||||
extern Bool ArenaAccess(Addr addr, AccessSet mode, MutatorFaultContext context);
|
||||
extern Res ArenaFreeCBSInsert(Arena arena, Addr base, Addr limit);
|
||||
extern void ArenaFreeCBSDelete(Arena arena, Addr base, Addr limit);
|
||||
extern Res ArenaFreeLandInsert(Arena arena, Addr base, Addr limit);
|
||||
extern void ArenaFreeLandDelete(Arena arena, Addr base, Addr limit);
|
||||
|
||||
|
||||
extern Bool GlobalsCheck(Globals arena);
|
||||
|
|
@ -992,6 +992,30 @@ extern Size VMReserved(VM vm);
|
|||
extern Size VMMapped(VM vm);
|
||||
|
||||
|
||||
/* Land Interface -- see <design/land/> */
|
||||
|
||||
extern Bool LandCheck(Land land);
|
||||
#define LandArena(land) ((land)->arena)
|
||||
#define LandAlignment(land) ((land)->alignment)
|
||||
|
||||
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);
|
||||
extern void LandFinish(Land land);
|
||||
extern Res LandInsert(Range rangeReturn, Land land, Range range);
|
||||
extern Res LandDelete(Range rangeReturn, Land land, Range range);
|
||||
extern void LandIterate(Land land, LandVisitor visitor, void *closureP, Size closureS);
|
||||
extern Bool LandFindFirst(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete);
|
||||
extern Bool LandFindLast(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete);
|
||||
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 Bool LandClassCheck(LandClass class);
|
||||
extern LandClass LandClassGet(void);
|
||||
#define LAND_SUPERCLASS(className) ((LandClass)SUPERCLASS(className))
|
||||
|
||||
|
||||
/* Stack Probe */
|
||||
|
||||
extern void StackProbe(Size depth);
|
||||
|
|
|
|||
|
|
@ -604,7 +604,50 @@ typedef struct GlobalsStruct {
|
|||
} GlobalsStruct;
|
||||
|
||||
|
||||
/* LandClassStruct -- land class structure
|
||||
*
|
||||
* See <design/land/>.
|
||||
*/
|
||||
|
||||
#define LandClassSig ((Sig)0x5197A4DC) /* SIGnature LAND Class */
|
||||
|
||||
typedef struct LandClassStruct {
|
||||
ProtocolClassStruct protocol;
|
||||
const char *name; /* class name string */
|
||||
size_t size; /* size of outer structure */
|
||||
LandInitMethod init; /* initialize the land */
|
||||
LandFinishMethod finish; /* finish the land */
|
||||
LandInsertMethod insert; /* insert a range into the land */
|
||||
LandDeleteMethod delete; /* delete a range from the land */
|
||||
LandIterateMethod iterate; /* iterate over ranges in the land */
|
||||
LandFindMethod findFirst; /* find first range of given size */
|
||||
LandFindMethod findLast; /* find last range of given size */
|
||||
LandFindMethod findLargest; /* find largest range */
|
||||
LandFindInZonesMethod findInZones; /* find first range of given size in zone set */
|
||||
LandDescribeMethod describe; /* describe the land */
|
||||
Sig sig; /* .class.end-sig */
|
||||
} LandClassStruct;
|
||||
|
||||
|
||||
/* LandStruct -- generic land structure
|
||||
*
|
||||
* See <design/land/>, <code/land.c>
|
||||
*/
|
||||
|
||||
#define LandSig ((Sig)0x5197A4D9) /* SIGnature LAND */
|
||||
|
||||
typedef struct LandStruct {
|
||||
Sig sig; /* <design/sig/> */
|
||||
LandClass class; /* land class structure */
|
||||
Arena arena; /* owning arena */
|
||||
Align alignment; /* alignment of addresses */
|
||||
} LandStruct;
|
||||
|
||||
|
||||
/* CBSStruct -- coalescing block structure
|
||||
*
|
||||
* CBS is a subclass of Land that maintains a collection of disjoint
|
||||
* ranges in a splay tree.
|
||||
*
|
||||
* See <code/cbs.c>.
|
||||
*/
|
||||
|
|
@ -612,18 +655,17 @@ typedef struct GlobalsStruct {
|
|||
#define CBSSig ((Sig)0x519CB599) /* SIGnature CBS */
|
||||
|
||||
typedef struct CBSStruct {
|
||||
LandStruct landStruct; /* superclass fields come first */
|
||||
SplayTreeStruct splayTreeStruct;
|
||||
STATISTIC_DECL(Count treeSize);
|
||||
Arena arena;
|
||||
Pool blockPool;
|
||||
Align alignment;
|
||||
Pool blockPool; /* pool that manages blocks */
|
||||
Bool fastFind; /* maintain and use size property? */
|
||||
Bool zoned; /* maintain and use zone property? */
|
||||
Bool inCBS; /* prevent reentrance */
|
||||
Bool ownPool; /* did we create blockPool? */
|
||||
/* meters for sizes of search structures at each op */
|
||||
METER_DECL(treeSearch);
|
||||
Sig sig; /* sig at end because embeded */
|
||||
Sig sig; /* sig at end because embedded */
|
||||
} CBSStruct;
|
||||
|
||||
|
||||
|
|
@ -661,9 +703,9 @@ typedef struct mps_arena_s {
|
|||
Serial chunkSerial; /* next chunk number */
|
||||
ChunkCacheEntryStruct chunkCache; /* just one entry */
|
||||
|
||||
Bool hasFreeCBS; /* Is freeCBS available? */
|
||||
Bool hasFreeLand; /* Is freeLand available? */
|
||||
MFSStruct freeCBSBlockPoolStruct;
|
||||
CBSStruct freeCBSStruct;
|
||||
CBSStruct freeLandStruct;
|
||||
ZoneSet freeZones; /* zones not yet allocated */
|
||||
Bool zoned; /* use zoned allocation? */
|
||||
|
||||
|
|
|
|||
|
|
@ -109,7 +109,13 @@ typedef struct AllocPatternStruct *AllocPattern;
|
|||
typedef struct AllocFrameStruct *AllocFrame; /* <design/alloc-frame/> */
|
||||
typedef struct ReservoirStruct *Reservoir; /* <design/reservoir/> */
|
||||
typedef struct StackContextStruct *StackContext;
|
||||
typedef unsigned FindDelete; /* <design/cbs/> */
|
||||
typedef struct RangeStruct *Range; /* <design/range/> */
|
||||
typedef struct LandStruct *Land; /* <design/land/> */
|
||||
typedef struct LandClassStruct *LandClass; /* <design/land/> */
|
||||
typedef LandClass CBSLandClass; /* <design/cbs/> */
|
||||
typedef struct CBSStruct *CBS; /* <design/cbs/> */
|
||||
typedef LandClass FreelistClass; /* <design/freelist/> */
|
||||
typedef unsigned FindDelete; /* <design/land/> */
|
||||
|
||||
|
||||
/* Arena*Method -- see <code/mpmst.h#ArenaClassStruct> */
|
||||
|
|
@ -262,6 +268,19 @@ typedef struct TraceStartMessageStruct *TraceStartMessage;
|
|||
typedef struct TraceMessageStruct *TraceMessage; /* trace end */
|
||||
|
||||
|
||||
/* Land*Method -- see <design/land/> */
|
||||
|
||||
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 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);
|
||||
typedef Res (*LandDescribeMethod)(Land land, mps_lib_FILE *stream);
|
||||
|
||||
|
||||
/* CONSTANTS */
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@
|
|||
#include "range.c"
|
||||
#include "freelist.c"
|
||||
#include "sa.c"
|
||||
#include "land.c"
|
||||
|
||||
/* Additional pool classes */
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ static Res MVTContingencySearch(Addr *baseReturn, Addr *limitReturn,
|
|||
MVT mvt, Size min);
|
||||
static Bool MVTCheckFit(Addr base, Addr limit, Size min, Arena arena);
|
||||
static ABQ MVTABQ(MVT mvt);
|
||||
static CBS MVTCBS(MVT mvt);
|
||||
static Land MVTCBS(MVT mvt);
|
||||
static Freelist MVTFreelist(MVT mvt);
|
||||
|
||||
|
||||
|
|
@ -168,9 +168,9 @@ static ABQ MVTABQ(MVT mvt)
|
|||
}
|
||||
|
||||
|
||||
static CBS MVTCBS(MVT mvt)
|
||||
static Land MVTCBS(MVT mvt)
|
||||
{
|
||||
return &mvt->cbsStruct;
|
||||
return (Land)(&mvt->cbsStruct);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -269,8 +269,10 @@ static Res MVTInit(Pool pool, ArgList args)
|
|||
if (abqDepth < 3)
|
||||
abqDepth = 3;
|
||||
|
||||
res = CBSInit(MVTCBS(mvt), arena, (void *)mvt, align,
|
||||
/* fastFind */ FALSE, /* zoned */ FALSE, args);
|
||||
MPS_ARGS_BEGIN(landiArgs) {
|
||||
MPS_ARGS_ADD(landiArgs, CBSFastFind, TRUE);
|
||||
res = LandInit(MVTCBS(mvt), CBSLandClassGet(), arena, align, mvt, landiArgs);
|
||||
} MPS_ARGS_END(landiArgs);
|
||||
if (res != ResOK)
|
||||
goto failCBS;
|
||||
|
||||
|
|
@ -348,7 +350,7 @@ static Res MVTInit(Pool pool, ArgList args)
|
|||
failFreelist:
|
||||
ABQFinish(arena, MVTABQ(mvt));
|
||||
failABQ:
|
||||
CBSFinish(MVTCBS(mvt));
|
||||
LandFinish(MVTCBS(mvt));
|
||||
failCBS:
|
||||
AVER(res != ResOK);
|
||||
return res;
|
||||
|
|
@ -422,7 +424,7 @@ static void MVTFinish(Pool pool)
|
|||
/* Finish the Freelist, ABQ and CBS structures */
|
||||
FreelistFinish(MVTFreelist(mvt));
|
||||
ABQFinish(arena, MVTABQ(mvt));
|
||||
CBSFinish(MVTCBS(mvt));
|
||||
LandFinish(MVTCBS(mvt));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -808,10 +810,10 @@ static Res MVTInsert(MVT mvt, Addr base, Addr limit)
|
|||
|
||||
/* Attempt to flush the Freelist to the CBS to give maximum
|
||||
* opportunities for coalescence. */
|
||||
FreelistFlushToCBS(MVTFreelist(mvt), MVTCBS(mvt));
|
||||
FreelistFlushToLand(MVTFreelist(mvt), MVTCBS(mvt));
|
||||
|
||||
RangeInit(&range, base, limit);
|
||||
res = CBSInsert(&newRange, MVTCBS(mvt), &range);
|
||||
res = LandInsert(&newRange, MVTCBS(mvt), &range);
|
||||
if (ResIsAllocFailure(res)) {
|
||||
/* CBS ran out of memory for splay nodes: add range to emergency
|
||||
* free list instead. */
|
||||
|
|
@ -845,7 +847,7 @@ static Res MVTDelete(MVT mvt, Addr base, Addr limit)
|
|||
AVER(base < limit);
|
||||
|
||||
RangeInit(&range, base, limit);
|
||||
res = CBSDelete(&rangeOld, MVTCBS(mvt), &range);
|
||||
res = LandDelete(&rangeOld, MVTCBS(mvt), &range);
|
||||
if (ResIsAllocFailure(res)) {
|
||||
/* CBS ran out of memory for splay nodes, which must mean that
|
||||
* there were fragments on both sides: see
|
||||
|
|
@ -853,7 +855,7 @@ static Res MVTDelete(MVT mvt, Addr base, Addr limit)
|
|||
* deleting the whole of rangeOld (which requires no
|
||||
* allocation) and re-inserting the fragments. */
|
||||
RangeStruct rangeOld2;
|
||||
res = CBSDelete(&rangeOld2, MVTCBS(mvt), &rangeOld);
|
||||
res = LandDelete(&rangeOld2, MVTCBS(mvt), &rangeOld);
|
||||
AVER(res == ResOK);
|
||||
AVER(RangesEqual(&rangeOld2, &rangeOld));
|
||||
AVER(RangeBase(&rangeOld) != base);
|
||||
|
|
@ -1043,7 +1045,7 @@ static Res MVTDescribe(Pool pool, mps_lib_FILE *stream)
|
|||
NULL);
|
||||
if(res != ResOK) return res;
|
||||
|
||||
res = CBSDescribe(MVTCBS(mvt), stream);
|
||||
res = LandDescribe(MVTCBS(mvt), stream);
|
||||
if(res != ResOK) return res;
|
||||
|
||||
res = ABQDescribe(MVTABQ(mvt), (ABQDescribeElement)RangeDescribe, stream);
|
||||
|
|
@ -1285,11 +1287,11 @@ static Bool MVTRefillCallback(MVT mvt, Range range)
|
|||
return MVTReserve(mvt, range);
|
||||
}
|
||||
|
||||
static Bool MVTCBSRefillCallback(CBS cbs, Range range,
|
||||
static Bool MVTCBSRefillCallback(Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
MVT mvt;
|
||||
AVERT(CBS, cbs);
|
||||
AVERT(Land, land);
|
||||
mvt = closureP;
|
||||
AVERT(MVT, mvt);
|
||||
UNUSED(closureS);
|
||||
|
|
@ -1324,7 +1326,7 @@ static void MVTRefillABQIfEmpty(MVT mvt, Size size)
|
|||
if (mvt->abqOverflow && ABQIsEmpty(MVTABQ(mvt))) {
|
||||
mvt->abqOverflow = FALSE;
|
||||
METER_ACC(mvt->refills, size);
|
||||
CBSIterate(MVTCBS(mvt), &MVTCBSRefillCallback, mvt, 0);
|
||||
LandIterate(MVTCBS(mvt), &MVTCBSRefillCallback, mvt, 0);
|
||||
FreelistIterate(MVTFreelist(mvt), &MVTFreelistRefillCallback, mvt, 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -1387,11 +1389,11 @@ static Bool MVTContingencyCallback(MVTContigency cl, Range range)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool MVTCBSContingencyCallback(CBS cbs, Range range,
|
||||
static Bool MVTCBSContingencyCallback(Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
{
|
||||
MVTContigency cl = closureP;
|
||||
UNUSED(cbs);
|
||||
AVERT(Land, land);
|
||||
UNUSED(closureS);
|
||||
return MVTContingencyCallback(cl, range);
|
||||
}
|
||||
|
|
@ -1421,9 +1423,9 @@ static Bool MVTContingencySearch(Addr *baseReturn, Addr *limitReturn,
|
|||
cls.steps = 0;
|
||||
cls.hardSteps = 0;
|
||||
|
||||
FreelistFlushToCBS(MVTFreelist(mvt), MVTCBS(mvt));
|
||||
FreelistFlushToLand(MVTFreelist(mvt), MVTCBS(mvt));
|
||||
|
||||
CBSIterate(MVTCBS(mvt), MVTCBSContingencyCallback, (void *)&cls, 0);
|
||||
LandIterate(MVTCBS(mvt), MVTCBSContingencyCallback, (void *)&cls, 0);
|
||||
FreelistIterate(MVTFreelist(mvt), MVTFreelistContingencyCallback,
|
||||
(void *)&cls, 0);
|
||||
if (!cls.found)
|
||||
|
|
@ -1472,8 +1474,8 @@ static Bool MVTCheckFit(Addr base, Addr limit, Size min, Arena arena)
|
|||
|
||||
/* Return the CBS of an MVT pool for the benefit of fotest.c. */
|
||||
|
||||
extern CBS _mps_mvt_cbs(mps_pool_t);
|
||||
CBS _mps_mvt_cbs(mps_pool_t mps_pool) {
|
||||
extern Land _mps_mvt_cbs(mps_pool_t);
|
||||
Land _mps_mvt_cbs(mps_pool_t mps_pool) {
|
||||
Pool pool;
|
||||
MVT mvt;
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,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))
|
||||
#define CBSOfMVFF(mvff) ((Land)&((mvff)->cbsStruct))
|
||||
#define MVFFOfCBS(cbs) PARENT(MVFFStruct, cbsStruct, cbs)
|
||||
#define FreelistOfMVFF(mvff) (&((mvff)->flStruct))
|
||||
#define MVFFOfFreelist(fl) PARENT(MVFFStruct, flStruct, fl)
|
||||
|
|
@ -95,7 +95,7 @@ static Res MVFFAddToFreeList(Addr *baseIO, Addr *limitIO, MVFF mvff) {
|
|||
AVERT(MVFF, mvff);
|
||||
RangeInit(&range, *baseIO, *limitIO);
|
||||
|
||||
res = CBSInsert(&newRange, CBSOfMVFF(mvff), &range);
|
||||
res = LandInsert(&newRange, CBSOfMVFF(mvff), &range);
|
||||
if (ResIsAllocFailure(res)) {
|
||||
/* CBS ran out of memory for splay nodes: add range to emergency
|
||||
* free list instead. */
|
||||
|
|
@ -150,7 +150,7 @@ static void MVFFFreeSegs(MVFF mvff, Addr base, Addr limit)
|
|||
RangeStruct range, oldRange;
|
||||
RangeInit(&range, segBase, segLimit);
|
||||
|
||||
res = CBSDelete(&oldRange, CBSOfMVFF(mvff), &range);
|
||||
res = LandDelete(&oldRange, CBSOfMVFF(mvff), &range);
|
||||
if (res == ResOK) {
|
||||
mvff->free -= RangeSize(&range);
|
||||
} else if (ResIsAllocFailure(res)) {
|
||||
|
|
@ -160,7 +160,7 @@ static void MVFFFreeSegs(MVFF mvff, Addr base, Addr limit)
|
|||
* deleting the whole of oldRange (which requires no
|
||||
* allocation) and re-inserting the fragments. */
|
||||
RangeStruct oldRange2;
|
||||
res = CBSDelete(&oldRange2, CBSOfMVFF(mvff), &oldRange);
|
||||
res = LandDelete(&oldRange2, CBSOfMVFF(mvff), &oldRange);
|
||||
AVER(res == ResOK);
|
||||
AVER(RangesEqual(&oldRange2, &oldRange));
|
||||
mvff->free -= RangeSize(&oldRange);
|
||||
|
|
@ -297,12 +297,12 @@ static Bool MVFFFindFirstFree(Addr *baseReturn, Addr *limitReturn,
|
|||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, PoolAlignment(MVFF2Pool(mvff))));
|
||||
|
||||
FreelistFlushToCBS(FreelistOfMVFF(mvff), CBSOfMVFF(mvff));
|
||||
FreelistFlushToLand(FreelistOfMVFF(mvff), CBSOfMVFF(mvff));
|
||||
|
||||
findDelete = mvff->slotHigh ? FindDeleteHIGH : FindDeleteLOW;
|
||||
|
||||
foundBlock =
|
||||
(mvff->firstFit ? CBSFindFirst : CBSFindLast)
|
||||
(mvff->firstFit ? LandFindFirst : LandFindLast)
|
||||
(&range, &oldRange, CBSOfMVFF(mvff), size, findDelete);
|
||||
|
||||
if (!foundBlock) {
|
||||
|
|
@ -411,9 +411,9 @@ static Bool MVFFFindLargest(Range range, Range oldRange, MVFF mvff,
|
|||
AVER(size > 0);
|
||||
AVERT(FindDelete, findDelete);
|
||||
|
||||
FreelistFlushToCBS(FreelistOfMVFF(mvff), CBSOfMVFF(mvff));
|
||||
FreelistFlushToLand(FreelistOfMVFF(mvff), CBSOfMVFF(mvff));
|
||||
|
||||
if (CBSFindLargest(range, oldRange, CBSOfMVFF(mvff), size, findDelete))
|
||||
if (LandFindLargest(range, oldRange, CBSOfMVFF(mvff), size, findDelete))
|
||||
return TRUE;
|
||||
|
||||
if (FreelistFindLargest(range, oldRange, FreelistOfMVFF(mvff),
|
||||
|
|
@ -602,8 +602,10 @@ static Res MVFFInit(Pool pool, ArgList args)
|
|||
if (res != ResOK)
|
||||
goto failInit;
|
||||
|
||||
res = CBSInit(CBSOfMVFF(mvff), arena, (void *)mvff, align,
|
||||
/* fastFind */ TRUE, /* zoned */ FALSE, args);
|
||||
MPS_ARGS_BEGIN(landiArgs) {
|
||||
MPS_ARGS_ADD(landiArgs, CBSFastFind, TRUE);
|
||||
res = LandInit(CBSOfMVFF(mvff), CBSLandClassGet(), arena, align, mvff, landiArgs);
|
||||
} MPS_ARGS_END(landiArgs);
|
||||
if (res != ResOK)
|
||||
goto failInit;
|
||||
|
||||
|
|
@ -646,7 +648,7 @@ static void MVFFFinish(Pool pool)
|
|||
arena = PoolArena(pool);
|
||||
ControlFree(arena, mvff->segPref, sizeof(SegPrefStruct));
|
||||
|
||||
CBSFinish(CBSOfMVFF(mvff));
|
||||
LandFinish(CBSOfMVFF(mvff));
|
||||
FreelistFinish(FreelistOfMVFF(mvff));
|
||||
|
||||
mvff->sig = SigInvalid;
|
||||
|
|
@ -691,7 +693,7 @@ static Res MVFFDescribe(Pool pool, mps_lib_FILE *stream)
|
|||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
res = CBSDescribe(CBSOfMVFF(mvff), stream);
|
||||
res = LandDescribe(CBSOfMVFF(mvff), stream);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -802,7 +804,7 @@ 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(CBS, CBSOfMVFF(mvff));
|
||||
CHECKD(Land, CBSOfMVFF(mvff));
|
||||
CHECKD(Freelist, FreelistOfMVFF(mvff));
|
||||
CHECKL(BoolCheck(mvff->slotHigh));
|
||||
CHECKL(BoolCheck(mvff->firstFit));
|
||||
|
|
@ -812,8 +814,8 @@ static Bool MVFFCheck(MVFF mvff)
|
|||
|
||||
/* Return the CBS of an MVFF pool for the benefit of fotest.c. */
|
||||
|
||||
extern CBS _mps_mvff_cbs(mps_pool_t);
|
||||
CBS _mps_mvff_cbs(mps_pool_t mps_pool) {
|
||||
extern Land _mps_mvff_cbs(mps_pool_t);
|
||||
Land _mps_mvff_cbs(mps_pool_t mps_pool) {
|
||||
Pool pool;
|
||||
MVFF mvff;
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@
|
|||
|
||||
/* Prototypes */
|
||||
|
||||
typedef struct RangeStruct *Range;
|
||||
|
||||
#define RangeBase(range) ((range)->base)
|
||||
#define RangeLimit(range) ((range)->limit)
|
||||
#define RangeSize(range) (AddrOffset(RangeBase(range), RangeLimit(range)))
|
||||
|
|
|
|||
|
|
@ -210,25 +210,25 @@ Res ChunkInit(Chunk chunk, Arena arena,
|
|||
|
||||
/* Add the chunk's free address space to the arena's freeCBS, so that
|
||||
we can allocate from it. */
|
||||
if (arena->hasFreeCBS) {
|
||||
res = ArenaFreeCBSInsert(arena,
|
||||
PageIndexBase(chunk, chunk->allocBase),
|
||||
chunk->limit);
|
||||
if (arena->hasFreeLand) {
|
||||
res = ArenaFreeLandInsert(arena,
|
||||
PageIndexBase(chunk, chunk->allocBase),
|
||||
chunk->limit);
|
||||
if (res != ResOK)
|
||||
goto failCBSInsert;
|
||||
goto failLandInsert;
|
||||
}
|
||||
|
||||
chunk->sig = ChunkSig;
|
||||
AVERT(Chunk, chunk);
|
||||
|
||||
/* As part of the bootstrap, the first created chunk becomes the primary
|
||||
chunk. This step allows AreaFreeCBSInsert to allocate pages. */
|
||||
chunk. This step allows AreaFreeLandInsert to allocate pages. */
|
||||
if (arena->primary == NULL)
|
||||
arena->primary = chunk;
|
||||
|
||||
return ResOK;
|
||||
|
||||
failCBSInsert:
|
||||
failLandInsert:
|
||||
(arena->class->chunkFinish)(chunk);
|
||||
/* .no-clean: No clean-ups needed past this point for boot, as we will
|
||||
discard the chunk. */
|
||||
|
|
@ -248,10 +248,10 @@ void ChunkFinish(Chunk chunk)
|
|||
chunk->sig = SigInvalid;
|
||||
RingRemove(&chunk->chunkRing);
|
||||
|
||||
if (ChunkArena(chunk)->hasFreeCBS)
|
||||
ArenaFreeCBSDelete(ChunkArena(chunk),
|
||||
PageIndexBase(chunk, chunk->allocBase),
|
||||
chunk->limit);
|
||||
if (ChunkArena(chunk)->hasFreeLand)
|
||||
ArenaFreeLandDelete(ChunkArena(chunk),
|
||||
PageIndexBase(chunk, chunk->allocBase),
|
||||
chunk->limit);
|
||||
|
||||
if (chunk->arena->primary == chunk)
|
||||
chunk->arena->primary = NULL;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue