diff --git a/mps/code/arena.c b/mps/code/arena.c index 1d1647552f2..bb2a060b27c 100644 --- a/mps/code/arena.c +++ b/mps/code/arena.c @@ -9,7 +9,6 @@ #include "poolmv.h" #include "mpm.h" #include "cbs.h" -#include "zonedcbs.h" #include "bt.h" #include "poolmfs.h" #include "mpscmfs.h" @@ -155,7 +154,7 @@ Bool ArenaCheck(Arena arena) CHECKL(BoolCheck(arena->hasFreeCBS)); if (arena->hasFreeCBS) - ZonedCBSCheck(ArenaZonedCBS(arena)); + CBSCheck(ArenaZonedCBS(arena)); return TRUE; } @@ -221,11 +220,18 @@ Res ArenaInit(Arena arena, ArenaClass class, Align alignment) if (res != ResOK) goto failMFSInit; - res = ZonedCBSInit(ArenaZonedCBS(arena), arena, ArenaCBSBlockPool(arena), - ArenaAlign(arena)); + /* Initialise the freeCBS. */ + MPS_ARGS_BEGIN(cbsiArgs) { + MPS_ARGS_ADD(cbsiArgs, CBSBlockPool, ArenaCBSBlockPool(arena)); + MPS_ARGS_DONE(cbsiArgs); + res = CBSInit(arena, ArenaZonedCBS(arena), arena, alignment, TRUE, TRUE, cbsiArgs); + } MPS_ARGS_END(cbsiArgs); + 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. */ + /* initialize the reservoir, */ res = ReservoirInit(&arena->reservoirStruct, arena); if (res != ResOK) @@ -235,7 +241,7 @@ Res ArenaInit(Arena arena, ArenaClass class, Align alignment) return ResOK; failReservoirInit: - ZonedCBSFinish(ArenaZonedCBS(arena)); + CBSFinish(ArenaZonedCBS(arena)); failCBSInit: PoolFinish(ArenaCBSBlockPool(arena)); failMFSInit: @@ -364,7 +370,7 @@ void ArenaDestroy(Arena arena) containing CBS blocks might be allocated in those chunks. */ AVER(arena->hasFreeCBS); arena->hasFreeCBS = FALSE; - ZonedCBSFinish(ArenaZonedCBS(arena)); + CBSFinish(ArenaZonedCBS(arena)); /* The CBS block pool can't free its own memory via ArenaFree because that would use the ZonedCBS. */ @@ -675,7 +681,7 @@ static void arenaExcludePage(Arena arena, Range pageRange) RangeStruct oldRange; Res res; - res = ZonedCBSDelete(&oldRange, ArenaZonedCBS(arena), pageRange); + res = CBSDelete(&oldRange, ArenaZonedCBS(arena), pageRange); AVER(res == ResOK); /* we just gave memory to the CBSs */ } @@ -696,7 +702,7 @@ static Res arenaCBSInsert(Range rangeReturn, Arena arena, Range range) AVERT(Arena, arena); AVERT(Range, range); - res = ZonedCBSInsert(rangeReturn, ArenaZonedCBS(arena), range); + res = CBSInsert(rangeReturn, ArenaZonedCBS(arena), range); if (res == ResLIMIT) { /* freeCBS MFS pool ran out of blocks */ RangeStruct pageRange; @@ -704,8 +710,8 @@ static Res arenaCBSInsert(Range rangeReturn, Arena arena, Range range) if (res != ResOK) return res; /* Must insert before exclude so that we can bootstrap when the - ZonedCBS is empty. */ - res = ZonedCBSInsert(rangeReturn, ArenaZonedCBS(arena), range); + zoned CBS is empty. */ + res = CBSInsert(rangeReturn, ArenaZonedCBS(arena), range); AVER(res == ResOK); /* we just gave memory to the CBSs */ arenaExcludePage(arena, &pageRange); } @@ -752,7 +758,7 @@ static void arenaCBSInsertSteal(Range rangeReturn, Arena arena, Range rangeIO) MFSExtend(ArenaCBSBlockPool(arena), pageBase, ArenaAlign(arena)); /* Try again. */ - res = ZonedCBSInsert(rangeReturn, ArenaZonedCBS(arena), rangeIO); + res = CBSInsert(rangeReturn, ArenaZonedCBS(arena), rangeIO); AVER(res == ResOK); /* we just gave memory to the CBS */ } @@ -803,7 +809,7 @@ void ArenaFreeCBSDelete(Arena arena, Addr base, Addr limit) Res res; RangeInit(&range, base, limit); - res = ZonedCBSDelete(&oldRange, ArenaZonedCBS(arena), &range); + res = CBSDelete(&oldRange, ArenaZonedCBS(arena), &range); /* Shouldn't be any other kind of failure because we were only deleting a non-coalesced block. See .chunk.no-coalesce. */ @@ -823,6 +829,7 @@ static Res arenaAllocFromCBS(Tract *tractReturn, ZoneSet zones, Bool high, Count pages; Res res; FindDelete fd; + CBSFindInZonesMethod find; AVER(tractReturn != NULL); /* ZoneSet is arbitrary */ @@ -834,8 +841,8 @@ static Res arenaAllocFromCBS(Tract *tractReturn, ZoneSet zones, Bool high, /* Step 1. Find a range of address space. */ fd = high ? FindDeleteHIGH : FindDeleteLOW; - res = ZonedCBSFind(&range, &oldRange, ArenaZonedCBS(arena), - zones, size, fd, high); + find = high ? CBSFindLastInZones : CBSFindFirstInZones; + res = find(&range, &oldRange, ArenaZonedCBS(arena), size, arena, zones); if (res == ResLIMIT) { /* found block, but couldn't store info */ RangeStruct pageRange; @@ -843,8 +850,7 @@ static Res arenaAllocFromCBS(Tract *tractReturn, ZoneSet zones, Bool high, if (res != ResOK) /* disasterously short on memory */ return res; arenaExcludePage(arena, &pageRange); - res = ZonedCBSFind(&range, &oldRange, ArenaZonedCBS(arena), - zones, size, fd, high); + res = find(&range, &oldRange, ArenaZonedCBS(arena), size, arena, zones); AVER(res != ResLIMIT); } @@ -876,7 +882,7 @@ static Res arenaAllocFromCBS(Tract *tractReturn, ZoneSet zones, Bool high, failMark: NOTREACHED; /* FIXME */ { - Res insertRes = ZonedCBSInsert(&oldRange, ArenaZonedCBS(arena), &range); + Res insertRes = CBSInsert(&oldRange, ArenaZonedCBS(arena), &range); AVER(insertRes == ResOK); /* We only just deleted it. */ /* If the insert does fail, we lose some address space permanently. */ } diff --git a/mps/code/cbs.c b/mps/code/cbs.c index dc6fcfc75eb..fe07f6aff27 100644 --- a/mps/code/cbs.c +++ b/mps/code/cbs.c @@ -70,6 +70,7 @@ Bool CBSCheck(CBS cbs) CHECKL(SplayTreeCheck(splayTreeOfCBS(cbs))); /* nothing to check about splayTreeSize */ CHECKD(Pool, cbs->blockPool); + CHECKU(Arena, cbs->arena); CHECKL(BoolCheck(cbs->fastFind)); CHECKL(BoolCheck(cbs->inCBS)); CHECKL(BoolCheck(cbs->ownPool)); @@ -198,6 +199,48 @@ static void cbsUpdateNode(SplayTree tree, SplayNode node, } +/* cbsUpdateZonedNode -- update size and zone info after restructuring */ + +static void cbsUpdateZonedNode(SplayTree tree, SplayNode node, + SplayNode leftChild, SplayNode rightChild) +{ + Size maxSize; + ZoneSet zones; + CBSBlock block; + Arena arena; + + AVERT(SplayTree, tree); + AVERT(SplayNode, node); + if (leftChild != NULL) + AVERT(SplayNode, leftChild); + if (rightChild != NULL) + AVERT(SplayNode, rightChild); + AVER(cbsOfSplayTree(tree)->fastFind); + + block = cbsBlockOfSplayNode(node); + maxSize = CBSBlockSize(block); + arena = cbsOfSplayTree(tree)->arena; + zones = ZoneSetOfRange(arena, CBSBlockBase(block), CBSBlockLimit(block)); + + if (leftChild != NULL) { + Size size = cbsBlockOfSplayNode(leftChild)->maxSize; + if (size > maxSize) + maxSize = size; + zones = ZoneSetUnion(zones, cbsBlockOfSplayNode(leftChild)->zones); + } + + if (rightChild != NULL) { + Size size = cbsBlockOfSplayNode(rightChild)->maxSize; + if (size > maxSize) + maxSize = size; + zones = ZoneSetUnion(zones, cbsBlockOfSplayNode(rightChild)->zones); + } + + block->maxSize = maxSize; + block->zones = zones; +} + + /* CBSInit -- Initialise a CBS structure * * See . @@ -207,15 +250,21 @@ ARG_DEFINE_KEY(cbs_extend_by, Size); ARG_DEFINE_KEY(cbs_block_pool, Pool); Res CBSInit(Arena arena, CBS cbs, void *owner, Align alignment, - Bool fastFind, ArgList args) + Bool fastFind, Bool zoned, ArgList args) { Size extendBy = CBS_EXTEND_BY_DEFAULT; Bool extendSelf = TRUE; ArgStruct arg; Res res; Pool blockPool = NULL; + SplayUpdateNodeMethod update; AVERT(Arena, arena); + AVER(cbs != NULL); + AVER(AlignCheck(alignment)); + AVER(BoolCheck(fastFind)); + AVER(BoolCheck(zoned)); + if (ArgPick(&arg, args, CBSBlockPool)) blockPool = arg.val.pool; @@ -224,8 +273,15 @@ Res CBSInit(Arena arena, CBS cbs, void *owner, Align alignment, if (ArgPick(&arg, args, MFSExtendSelf)) extendSelf = arg.val.b; - SplayTreeInit(splayTreeOfCBS(cbs), &cbsSplayCompare, - fastFind ? &cbsUpdateNode : NULL); + update = NULL; + if (fastFind) + update = cbsUpdateNode; + if (zoned) { + AVER(fastFind); + update = cbsUpdateZonedNode; + } + + SplayTreeInit(splayTreeOfCBS(cbs), cbsSplayCompare, update); if (blockPool != NULL) { cbs->blockPool = blockPool; @@ -245,7 +301,9 @@ Res CBSInit(Arena arena, CBS cbs, void *owner, Align alignment, cbs->splayTreeSize = 0; + cbs->arena = arena; cbs->fastFind = fastFind; + cbs->zoned = zoned; cbs->alignment = alignment; cbs->inCBS = TRUE; @@ -812,6 +870,20 @@ static Bool cbsTestNodeInZones(SplayTree tree, SplayNode node, closure->arena, closure->zoneSet, closure->size); } +static Bool cbsTestTreeInZones(SplayTree tree, SplayNode node, + void *closureP, Size closureSize) +{ + CBSBlock block = cbsBlockOfSplayNode(node); + cbsTestNodeInZonesClosure closure = closureP; + + UNUSED(tree); + AVER(closureSize == sizeof(cbsTestNodeInZonesClosureStruct)); + UNUSED(closureSize); + + return block->maxSize >= closure->size && + ZoneSetInter(block->zones, closure->zoneSet) != ZoneSetEMPTY; +} + static Res CBSFindInZones(Range rangeReturn, Range oldRangeReturn, CBS cbs, Size size, Arena arena, ZoneSet zoneSet, @@ -855,7 +927,7 @@ static Res CBSFindInZones(Range rangeReturn, Range oldRangeReturn, closure.size = size; if (splayFind(&node, splayTreeOfCBS(cbs), &cbsTestNodeInZones, - &cbsTestTree, + &cbsTestTreeInZones, &closure, sizeof(closure))) { CBSBlock block = cbsBlockOfSplayNode(node); RangeStruct rangeStruct, oldRangeStruct; diff --git a/mps/code/cbs.h b/mps/code/cbs.h index 4ee9ebb3657..e2141a30351 100644 --- a/mps/code/cbs.h +++ b/mps/code/cbs.h @@ -16,6 +16,10 @@ #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. */ + typedef struct CBSBlockStruct *CBSBlock; typedef struct CBSBlockStruct { SplayNodeStruct splayNode; @@ -36,8 +40,8 @@ extern const struct mps_key_s _mps_key_cbs_block_pool; #define CBSBlockPool (&_mps_key_cbs_block_pool) #define CBSBlockPool_FIELD pool -extern Res CBSInit(Arena arena, CBS cbs, void *owner, - Align alignment, Bool fastFind, ArgList args); +extern Res CBSInit(Arena arena, CBS cbs, void *owner, Align alignment, + Bool fastFind, Bool zoned, ArgList args); extern void CBSFinish(CBS cbs); extern Res CBSInsert(Range rangeReturn, CBS cbs, Range range); diff --git a/mps/code/config.h b/mps/code/config.h index 8e3004a81b1..348585ba321 100644 --- a/mps/code/config.h +++ b/mps/code/config.h @@ -307,12 +307,9 @@ /* @@@@ knows the implementation of ZoneSets */ /* FIXME: There's no particular reason to think this will avoid GC segments. */ -/* .segpref.default: For EPcore, non-DL segments should be placed high */ -/* to reduce fragmentation of DL pools (see request.epcore.170193_). */ -/* .. _request.epcore.170193: https://info.ravenbrook.com/project/mps/import/2001-11-05/mmprevol/request/epcore/170193 */ #define SegPrefDEFAULT { \ SegPrefSig, /* sig */ \ - TRUE, /* high */ \ + FALSE, /* high */ \ ArenaDefaultZONESET, /* zoneSet */ \ ZoneSetEMPTY, /* avoid */ \ } diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index 4c0747e3b9c..0b02fbbb10d 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -614,9 +614,11 @@ typedef struct GlobalsStruct { typedef struct CBSStruct { SplayTreeStruct splayTree; STATISTIC_DECL(Count splayTreeSize); + Arena arena; Pool blockPool; Align alignment; - Bool fastFind; + 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 */ @@ -677,7 +679,7 @@ typedef struct mps_arena_s { Bool hasFreeCBS; /* Is freeCBS available? */ MFSStruct zonedCBSBlockPoolStruct; - ZonedCBSStruct zonedCBSStruct; + CBSStruct zonedCBSStruct; ZoneSet freeZones; /* zones not yet allocated */ /* locus fields () */ diff --git a/mps/code/mps.c b/mps/code/mps.c index 85c34f81359..329c67de9a4 100644 --- a/mps/code/mps.c +++ b/mps/code/mps.c @@ -74,7 +74,6 @@ #include "range.c" #include "freelist.c" #include "sa.c" -#include "zonedcbs.c" /* Additional pool classes */ diff --git a/mps/code/mps.xcodeproj/project.pbxproj b/mps/code/mps.xcodeproj/project.pbxproj index 69b47b767dc..9524465561a 100644 --- a/mps/code/mps.xcodeproj/project.pbxproj +++ b/mps/code/mps.xcodeproj/project.pbxproj @@ -1250,8 +1250,6 @@ 3114A6BA156E9768001E0AA3 /* walkt0.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = walkt0.c; sourceTree = ""; }; 3114A6C6156E9815001E0AA3 /* mpseventcnv */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mpseventcnv; sourceTree = BUILT_PRODUCTS_DIR; }; 3114A6D0156E9829001E0AA3 /* eventcnv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eventcnv.c; sourceTree = ""; }; - 3115E70118BED7E000385449 /* zonedcbs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = zonedcbs.h; sourceTree = ""; }; - 3115E70218BEDA1100385449 /* zonedcbs.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = zonedcbs.c; sourceTree = ""; }; 31160D921899540D0071EB17 /* abq.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = abq.txt; path = ../design/abq.txt; sourceTree = ""; }; 31160D931899540D0071EB17 /* alloc-frame.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "alloc-frame.txt"; path = "../design/alloc-frame.txt"; sourceTree = ""; }; 31160D941899540D0071EB17 /* arena.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = arena.txt; path = ../design/arena.txt; sourceTree = ""; }; @@ -2137,8 +2135,6 @@ 31EEAC0E156AB27B00714D05 /* walk.c */, 3112ED3A18ABC57F00CC531A /* sa.h */, 3112ED3B18ABC75200CC531A /* sa.c */, - 3115E70118BED7E000385449 /* zonedcbs.h */, - 3115E70218BEDA1100385449 /* zonedcbs.c */, ); name = "MPM Core"; sourceTree = ""; diff --git a/mps/code/poolmv2.c b/mps/code/poolmv2.c index 16f11060e05..7c616bcfcfa 100644 --- a/mps/code/poolmv2.c +++ b/mps/code/poolmv2.c @@ -269,7 +269,7 @@ static Res MVTInit(Pool pool, ArgList args) if (abqDepth < 3) abqDepth = 3; - res = CBSInit(arena, MVTCBS(mvt), (void *)mvt, align, FALSE, args); + res = CBSInit(arena, MVTCBS(mvt), (void *)mvt, align, FALSE, FALSE, args); if (res != ResOK) goto failCBS; diff --git a/mps/code/poolmvff.c b/mps/code/poolmvff.c index 8ed836ea247..79666896b1a 100644 --- a/mps/code/poolmvff.c +++ b/mps/code/poolmvff.c @@ -602,7 +602,7 @@ static Res MVFFInit(Pool pool, ArgList args) if (res != ResOK) goto failInit; - res = CBSInit(arena, CBSOfMVFF(mvff), (void *)mvff, align, TRUE, args); + res = CBSInit(arena, CBSOfMVFF(mvff), (void *)mvff, align, TRUE, FALSE, args); if (res != ResOK) goto failInit; diff --git a/mps/code/zonedcbs.c b/mps/code/zonedcbs.c deleted file mode 100644 index 1a668642484..00000000000 --- a/mps/code/zonedcbs.c +++ /dev/null @@ -1,433 +0,0 @@ -/* zonedcbs.c: ZONED COALESCING BLOCK STRUCTURE IMPLEMENTATION - * - * $Id$ - * Copyright (c) 2014 Ravenbrook Limited. See end of file for license. - * - * A Zone CBS is like a CBS but allows for efficient allocation in zones. - * Allocation in zones gives control over some parts of an object's address, - * so that we can later apply fast filters on the critical path. - * The Zone CBS is mainly used by the arena to allocate blocks to pools. - * - * Can be stressed by setting a small arena size. - * - * This code is essentially an optimisation of CBSFindFirstInZones, but - * doesn't have quite the same effect. FIXME: Be clearer. - */ - -#include "zonedcbs.h" -#include "mpm.h" -#include "cbs.h" - - -#define ZonedCBSBlockPool(zcbs) RVALUE((zcbs)->blockPool) -#define ZonedCBSFreeCBS(zcbs) (&(zcbs)->freeStruct) -#define ZonedCBSZoneCBS(zcbs, z) (&(zcbs)->zoneStruct[z]) -#define ZonedCBSNZones(zcbs) NELEMS((zcbs)->zoneStruct) - - -/* ZonedCBSCheck -- check consistency of zoned CBS structure */ - -Bool ZonedCBSCheck(ZonedCBS zcbs) -{ - Index i; - - CHECKS(ZonedCBS, zcbs); - CHECKU(Arena, zcbs->arena); - CHECKD(Pool, ZonedCBSBlockPool(zcbs)); - CHECKD(CBS, ZonedCBSFreeCBS(zcbs)); - CHECKL(ZonedCBSNZones(zcbs) == sizeof(ZoneSet) * CHAR_BIT); - CHECKL(ZonedCBSNZones(zcbs) == NELEMS(zcbs->zoneStruct)); - for (i = 0; i < ZonedCBSNZones(zcbs); ++i) - CHECKD(CBS, ZonedCBSZoneCBS(zcbs, i)); - - /* TODO: Thorough check summing CBSs against totals. The sum of the - sizes of the contents of the zone CBSs and the freeCBS should equal - the total allocatable free space in the chunks. The CBS ADT - probably ought to maintain totals like this too. */ - - return TRUE; -} - - -/* ZonedCBSInit -- initialise a Zoned CBS */ - -Res ZonedCBSInit(ZonedCBS zcbs, Arena arena, Pool blockPool, Align alignment) -{ - Index i; - Res res; - - AVER(zcbs != NULL); - AVERT(Pool, blockPool); - - zcbs->arena = arena; - zcbs->blockPool = blockPool; - - /* Initialise the freeCBS. */ - MPS_ARGS_BEGIN(cbsiArgs) { - MPS_ARGS_ADD(cbsiArgs, CBSBlockPool, blockPool); - MPS_ARGS_DONE(cbsiArgs); - res = CBSInit(arena, ZonedCBSFreeCBS(zcbs), zcbs, alignment, TRUE, cbsiArgs); - } MPS_ARGS_END(cbsiArgs); - 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. */ - - /* Initialise the zoneCBSs. */ - for (i = 0; i < NELEMS(zcbs->zoneStruct); ++i) { - MPS_ARGS_BEGIN(cbsiArgs) { - MPS_ARGS_ADD(cbsiArgs, CBSBlockPool, blockPool); - MPS_ARGS_DONE(cbsiArgs); - res = CBSInit(arena, ZonedCBSZoneCBS(zcbs, i), arena, alignment, TRUE, cbsiArgs); - } MPS_ARGS_END(cbsiArgs); - AVER(res == ResOK); /* no allocation, no failure expected */ - if (res != ResOK) - goto failZoneCBSInit; - } - - zcbs->sig = ZonedCBSSig; - AVERT(ZonedCBS, zcbs); - - return ResOK; - -failZoneCBSInit: - while (i > 0) { - --i; - CBSFinish(ZonedCBSZoneCBS(zcbs, i)); - } - CBSFinish(ZonedCBSFreeCBS(zcbs)); -failCBSInit: - return res; -} - - -/* ZonedCBSFinish -- finish the zoned CBS */ - -void ZonedCBSFinish(ZonedCBS zcbs) -{ - Index i; - - AVERT(ZonedCBS, zcbs); - - zcbs->sig = SigInvalid; - - /* FIXME: Should be asserting that CBSs are empty? Could iterate over - chunks and remove their ranges to make sure things are consistent. */ - - for (i = 0; i < ZonedCBSNZones(zcbs); ++i) - CBSFinish(ZonedCBSZoneCBS(zcbs, i)); - CBSFinish(ZonedCBSFreeCBS(zcbs)); -} - - -/* ZonedCBSInsert -- insert a range into the zoned CBS - * - * We just insert it into the free CBS. It will get split up and cached - * in the zoned CBSs by ZonedCBSFindFirst and ZonedCBSFindLast. - */ - -Res ZonedCBSInsert(Range rangeReturn, ZonedCBS zcbs, Range range) -{ - ZoneSet zs; - - AVERT(ZonedCBS, zcbs); - - /* TODO: Consider moving empty zone stripes back to freeCBS. At the - moment we do not do this, partly for simplicity, and partly to - keep large objects apart from smaller ones, at the possible cost - of address space fragmentation. We probably do not want to do it - eagerly in any case, but lazily if we're unable to find address - space, even though that reduces first-fit. */ - - zs = ZoneSetOfRange(zcbs->arena, RangeBase(range), RangeLimit(range)); - if (ZoneSetIsSingle(zs)) { - Index zone = AddrZone(zcbs->arena, RangeBase(range)); - CBS zoneCBS = ZonedCBSZoneCBS(zcbs, zone); - return CBSInsert(rangeReturn, zoneCBS, range); - } - - return CBSInsert(rangeReturn, ZonedCBSFreeCBS(zcbs), range); -} - - -/* ZonedCBSDelete -- delete a range from the zoned CBS - * - * The range may be split between the zone CBSs and the free CBS on zone - * stripe boundaries, in which case we have to iterate. - * - * .delete.exists: The range must exist in the zoned CBS. To make the - * zoned CBS more general we'd need to unwind the error case where we - * found a hole, putting the range we'd already found back. This isn't - * required by the arena. - * - * FIXME: Document guarantees about res. - */ - -Res ZonedCBSDelete(Range oldRange, ZonedCBS zcbs, Range range) -{ - Res res; - ZoneSet zs; - Addr base, limit; - - AVER(oldRange != NULL); - AVERT(ZonedCBS, zcbs); - AVERT(Range, range); - - zs = ZoneSetOfRange(zcbs->arena, RangeBase(range), RangeLimit(range)); - if (ZoneSetIsSingle(zs)) { - Index zone = AddrZone(zcbs->arena, RangeBase(range)); - CBS zoneCBS = ZonedCBSZoneCBS(zcbs, zone); - res = CBSDelete(oldRange, zoneCBS, range); - if (res != ResFAIL) /* block was in zone CBS */ - return res; - } - - res = CBSDelete(oldRange, ZonedCBSFreeCBS(zcbs), range); - if (res != ResFAIL) /* block was in free CBS */ - return res; - - /* The range may be divided between the free CBS and zone CBSs. */ - base = RangeBase(range); - limit = RangeLimit(range); - while (base < limit) { - Addr stripeLimit; - CBS zoneCBS; - RangeStruct stripe, oldStripe; - Index zone; - - stripeLimit = AddrAlignUp(AddrAdd(base, 1), ArenaStripeSize(zcbs->arena)); - if (stripeLimit > limit) - stripeLimit = limit; - - zone = AddrZone(zcbs->arena, base); - AVER(AddrZone(zcbs->arena, AddrSub(stripeLimit, 1)) == zone); - zoneCBS = ZonedCBSZoneCBS(zcbs, zone); - - RangeInit(&stripe, base, stripeLimit); - res = CBSDelete(&oldStripe, ZonedCBSFreeCBS(zcbs), &stripe); - - /* Optimisation: delete and skip over the rest of the block we - found in the free CBS, up to the next block that's in a zone CBS - (or the end). */ - if (res == ResOK && !RangesEqual(&oldStripe, &stripe)) { - Addr skipLimit = RangeLimit(&oldStripe); - if (skipLimit > limit) - skipLimit = limit; - if (stripeLimit < skipLimit) { - RangeStruct restOfBlock; - RangeInit(&restOfBlock, stripeLimit, skipLimit); - res = CBSDelete(&oldStripe, ZonedCBSFreeCBS(zcbs), &restOfBlock); - AVER(res == ResOK); /* FIXME: is this right? */ - AVER(RangesEqual(&oldStripe, &restOfBlock)); - base = skipLimit; - continue; - } - } - - if (res == ResFAIL) { - res = CBSDelete(&oldStripe, zoneCBS, &stripe); - AVER(res != ResFAIL); /* .delete.exists */ - AVER(RangesEqual(&oldStripe, &stripe)); - } - - AVER(res == ResOK); /* FIXME: end of range, shouldn't fail? */ - - base = stripeLimit; - } - - /* Shouldn't be any other kind of failure. */ - AVER(res == ResOK); - return ResOK; -} - - -/* ZonedCBSFindFirst, ZonedCBSFindLast -- find a range in the zoned CBS */ - - -static Res ZonedCBSFindInZones(Range rangeReturn, - Range oldRangeReturn, - ZonedCBS zcbs, - ZoneSet zones, - Size size, - FindDelete findDelete, - Bool high) -{ - Index i; - CBSFindMethod find = high ? CBSFindLast : CBSFindFirst; - - /* We could check zoneCBS if size > stripeSize to avoid looking in the - zoneCBSs, but this probably isn't a win for arena allocation. */ - - /* TODO: Does "high" really make sense for zone stripes? */ - /* TODO: How do we disable zones anyway? Just make zoneShift = WORD_WIDTH? - DL points out that if we had two zones, they'd both be blacklisted. */ - - /* Even though we have no guarantee that zone zero is at the bottom end - of anything, it makes sense to reverse the search when "high" is set, - because the point of it (presumably) is to separate memory usage into - two sets (high and low) that avoid interference. */ - - /* TODO: Consider masking zones against a ZoneSet of non-empty zone CBSs */ - - /* TODO: ZONESET_FOR using __builtin_ffsl or similar. */ - - for (i = 0; i < ZonedCBSNZones(zcbs); ++i) { - Index zone = high ? ZonedCBSNZones(zcbs) - i - 1 : i; - if (ZoneSetIsMember(zones, zone) && - find(rangeReturn, oldRangeReturn, ZonedCBSZoneCBS(zcbs, zone), - size, findDelete)) - return ResOK; - } - - return ResRESOURCE; -} - -static Res ZonedCBSFindInFree(Range rangeReturn, - Range oldRangeReturn, - ZonedCBS zcbs, - ZoneSet zones, - Size size, - FindDelete findDelete, - Bool high) -{ - CBSFindInZonesMethod find = high ? CBSFindLastInZones : CBSFindFirstInZones; - - UNUSED(findDelete); /* FIXME: why is this so? */ - - return find(rangeReturn, oldRangeReturn, ZonedCBSFreeCBS(zcbs), size, - zcbs->arena, zones); -} - -Res ZonedCBSFind(Range rangeReturn, - Range oldRangeReturn, - ZonedCBS zcbs, - ZoneSet zones, - Size size, - FindDelete findDelete, - Bool high) -{ - RangeStruct restRange; - Addr allocLimit, stripeLimit, oldLimit, limit; - Res res; - - AVER(rangeReturn != NULL); - AVER(oldRangeReturn != NULL); - AVERT(ZonedCBS, zcbs); - AVER(size > 0); - /* ZoneSet arbitrary. TODO: Make a ZoneSetCheck anyway. */ - AVER(BoolCheck(high)); - - /* TODO: Consider the other FindDelete cases. */ - AVER(findDelete == FindDeleteLOW || findDelete == FindDeleteHIGH); - AVER((findDelete == FindDeleteHIGH) == high); - - res = ZonedCBSFindInZones(rangeReturn, oldRangeReturn, - zcbs, zones, size, - findDelete, high); - if (res != ResRESOURCE) - return res; - - res = ZonedCBSFindInFree(rangeReturn, oldRangeReturn, - zcbs, zones, size, - findDelete, high); - if (res != ResOK) - return res; - - /* TODO: We may have failed to find because the address space is - fragmented between the zone CBSs and the free CBS. This isn't - a very important case for the arena, but it does make the Zone CBS - technically incorrect as a representation of a set of ranges. - Flush the zone CBSs back to the free CBS? */ - - /* Add the rest of the zone stripe to the zoneCBS so that subsequent - allocations in the zone are fast. This is what the ZonedCBS is - all about! */ - - allocLimit = RangeLimit(rangeReturn); - stripeLimit = AddrAlignUp(allocLimit, ArenaStripeSize(zcbs->arena)); - oldLimit = RangeLimit(oldRangeReturn); - limit = oldLimit < stripeLimit ? oldLimit : stripeLimit; - RangeInit(&restRange, allocLimit, limit); - AVER(RangesNest(oldRangeReturn, &restRange)); - - if (allocLimit < limit) { - Index zone; - CBS zoneCBS; - RangeStruct oldRange; - - res = CBSDelete(&oldRange, ZonedCBSFreeCBS(zcbs), &restRange); - AVER(res == ResOK); /* we should just be bumping up a base */ - zone = AddrZone(zcbs->arena, RangeBase(&restRange)); - zoneCBS = ZonedCBSZoneCBS(zcbs, zone); - - res = CBSInsert(&oldRange, zoneCBS, &restRange); - AVER(res != ResOK || RangesEqual(&oldRange, &restRange)); /* shouldn't coalesce */ - if (res != ResOK) { /* disasterously short on memory, so put it back */ - res = CBSInsert(&oldRange, ZonedCBSFreeCBS(zcbs), &restRange); - AVER(res == ResOK); /* should just be lowering a base */ - } - } - - return ResOK; -} - -/* -Res ZonedCBSFindFirst(Range rangeReturn, Range oldRangeReturn, - ZonedCBS zcbs, ZoneSet zones, - Size size, FindDelete findDelete) -{ - return ZonedCBSFind(rangeReturn, oldRangeReturn, zcbs, zones, size, - findDelete, FALSE); -} - -Bool ZonedCBSFindLast(Range rangeReturn, Range oldRangeReturn, - ZonedCBS zcbs, ZoneSet zones, - Size size, FindDelete findDelete) -{ - return ZonedCBSFind(rangeReturn, oldRangeReturn, zcbs, zones, size, - findDelete, TRUE); -} -*/ - - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2014 Ravenbrook Limited . - * 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. - */ diff --git a/mps/code/zonedcbs.h b/mps/code/zonedcbs.h deleted file mode 100644 index bc7e3dc39af..00000000000 --- a/mps/code/zonedcbs.h +++ /dev/null @@ -1,93 +0,0 @@ -/* zonedcbs.h: ZONE COALESCING BLOCK STRUCTURE INTERFACE - * - * $Id$ - * Copyright (c) 2014 Ravenbrook Limited. See end of file for license. - * - * A Zone CBS is like a CBS but allows for efficient allocation in zones. - * Allocation in zones gives control over some parts of an object's address, - * so that we can later apply fast filters on the critical path. - * The Zone CBS is mainly used by the arena to allocate blocks to pools. - */ - -#ifndef zonedcbs_h -#define zonedcbs_h - -#include "mpm.h" -#include "range.h" - - -typedef struct ZonedCBSStruct *ZonedCBS; - -/* ZoneCBSStruct is in mpmst.h because it is inlined in the ArenaStruct. */ - - -/* Basically the same interface as for CBS. See . */ - -extern Res ZonedCBSInit(ZonedCBS zcbs, Arena arena, Pool blockPool, - Align alignment); -extern void ZonedCBSFinish(ZonedCBS zcbs); -extern Bool ZonedCBSCheck(ZonedCBS zcbs); - -extern Res ZonedCBSInsert(Range rangeReturn, ZonedCBS zcbs, Range range); -extern Res ZonedCBSDelete(Range oldRange, ZonedCBS zcbs, Range range); - -extern Res ZonedCBSFind(Range rangeReturn, - Range oldRangeReturn, - ZonedCBS zcbs, - ZoneSet zones, - Size size, - FindDelete findDelete, - Bool high); - -/* -extern Bool ZonedCBSFindFirst(Range rangeReturn, Range oldRangeReturn, - ZonedCBS zcbs, ZoneSet zones, - Size size, FindDelete findDelete); -extern Bool ZonedCBSFindLast(Range rangeReturn, Range oldRangeReturn, - ZonedCBS zcbs, ZoneSet zones, - Size size, FindDelete findDelete); - */ - - -#endif /* zonedcbs_h */ - -/* C. COPYRIGHT AND LICENSE - * - * Copyright (C) 2014 Ravenbrook Limited . - * 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. - */