mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-04-27 16:51:06 -07:00
Simplifying interface to high and low allocation in the zoned cbs.
Copied from Perforce Change: 184576 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
9223d3de81
commit
322b4ba6dd
4 changed files with 114 additions and 54 deletions
|
|
@ -681,6 +681,8 @@ static void arenaExcludePage(Arena arena, Range pageRange)
|
|||
*
|
||||
* The arena's CBSs 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)
|
||||
|
|
@ -698,6 +700,8 @@ static Res arenaCBSInsert(Range rangeReturn, Arena arena, Range range)
|
|||
res = arenaExtendCBSBlockPool(&pageRange, arena);
|
||||
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);
|
||||
AVER(res == ResOK); /* we just gave memory to the CBSs */
|
||||
arenaExcludePage(arena, &pageRange);
|
||||
|
|
@ -783,6 +787,11 @@ Res ArenaFreeCBSInsert(Arena arena, Addr base, Addr limit)
|
|||
*
|
||||
* This is called from ChunkFinish in order to remove address space from
|
||||
* the arena.
|
||||
*
|
||||
* IMPORTANT: May only be called on whole chunk ranges, because we don't
|
||||
* deal with the case where the range is coalesced. This restriction would
|
||||
* be easy to lift by extending the block pool on error, but doesn't happen,
|
||||
* so we can't test that path.
|
||||
*/
|
||||
|
||||
void ArenaFreeCBSDelete(Arena arena, Addr base, Addr limit)
|
||||
|
|
@ -820,27 +829,19 @@ static Res arenaAllocFromCBS(Tract *tractReturn, ZoneSet zones, Bool high,
|
|||
AVER(SizeIsAligned(size, arena->alignment));
|
||||
|
||||
/* Step 1. Find a range of address space. */
|
||||
|
||||
fd = high ? FindDeleteHIGH : FindDeleteLOW;
|
||||
res = ZonedCBSFind(&range, &oldRange, ArenaZonedCBS(arena),
|
||||
zones, size, fd, high);
|
||||
|
||||
if (high)
|
||||
res = ZonedCBSFindLast(&range, &oldRange, ArenaZonedCBS(arena),
|
||||
zones, size, fd);
|
||||
else
|
||||
res = ZonedCBSFindFirst(&range, &oldRange, ArenaZonedCBS(arena),
|
||||
zones, size, fd);
|
||||
|
||||
if (res == ResLIMIT) {
|
||||
if (res == ResLIMIT) { /* found block, but couldn't store info */
|
||||
RangeStruct pageRange;
|
||||
res = arenaExtendCBSBlockPool(&pageRange, arena);
|
||||
if (res != ResOK) /* disasterously short on memory */
|
||||
return res;
|
||||
arenaExcludePage(arena, &pageRange);
|
||||
if (high)
|
||||
res = ZonedCBSFindLast(&range, &oldRange, ArenaZonedCBS(arena),
|
||||
zones, size, fd);
|
||||
else
|
||||
res = ZonedCBSFindFirst(&range, &oldRange, ArenaZonedCBS(arena),
|
||||
zones, size, fd);
|
||||
res = ZonedCBSFind(&range, &oldRange, ArenaZonedCBS(arena),
|
||||
zones, size, fd, high);
|
||||
AVER(res != ResLIMIT);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ extern Bool CBSFindLast(Range rangeReturn, Range oldRangeReturn,
|
|||
extern Bool CBSFindLargest(Range rangeReturn, Range oldRangeReturn,
|
||||
CBS cbs, Size size, FindDelete findDelete);
|
||||
|
||||
typedef Res (*CBSFindInZonesMethod)(Range rangeReturn, Range oldRangeReturn,
|
||||
CBS cbs, Size size,
|
||||
Arena arena, ZoneSet zoneSet);
|
||||
extern Res CBSFindFirstInZones(Range rangeReturn, Range oldRangeReturn,
|
||||
CBS cbs, Size size,
|
||||
Arena arena, ZoneSet zoneSet);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,11 @@
|
|||
* 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"
|
||||
|
|
@ -105,7 +110,8 @@ void ZonedCBSFinish(ZonedCBS zcbs)
|
|||
|
||||
zcbs->sig = SigInvalid;
|
||||
|
||||
/* FIXME: Should be asserting that CBSs are empty? */
|
||||
/* 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));
|
||||
|
|
@ -139,6 +145,11 @@ Res ZonedCBSInsert(Range rangeReturn, ZonedCBS zcbs, Range range)
|
|||
* 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.
|
||||
*/
|
||||
|
||||
|
|
@ -162,7 +173,6 @@ Res ZonedCBSDelete(Range oldRange, ZonedCBS zcbs, Range range)
|
|||
}
|
||||
|
||||
res = CBSDelete(oldRange, ZonedCBSFreeCBS(zcbs), range);
|
||||
|
||||
if (res != ResFAIL) /* block was in free CBS */
|
||||
return res;
|
||||
|
||||
|
|
@ -206,7 +216,7 @@ Res ZonedCBSDelete(Range oldRange, ZonedCBS zcbs, Range range)
|
|||
|
||||
if (res == ResFAIL) {
|
||||
res = CBSDelete(&oldStripe, zoneCBS, &stripe);
|
||||
AVER(res != ResFAIL); /* FIXME: not in any of the CBSs, return res */
|
||||
AVER(res != ResFAIL); /* .delete.exists */
|
||||
AVER(RangesEqual(&oldStripe, &stripe));
|
||||
}
|
||||
|
||||
|
|
@ -223,31 +233,17 @@ Res ZonedCBSDelete(Range oldRange, ZonedCBS zcbs, Range range)
|
|||
|
||||
/* ZonedCBSFindFirst, ZonedCBSFindLast -- find a range in the zoned CBS */
|
||||
|
||||
static Res ZonedCBSFind(Range rangeReturn,
|
||||
Range oldRangeReturn,
|
||||
ZonedCBS zcbs,
|
||||
ZoneSet zones,
|
||||
Size size,
|
||||
FindDelete findDelete,
|
||||
Bool high)
|
||||
|
||||
static Res ZonedCBSFindInZones(Range rangeReturn,
|
||||
Range oldRangeReturn,
|
||||
ZonedCBS zcbs,
|
||||
ZoneSet zones,
|
||||
Size size,
|
||||
FindDelete findDelete,
|
||||
Bool high)
|
||||
{
|
||||
CBSFindMethod find;
|
||||
Index i;
|
||||
RangeStruct restRange;
|
||||
Addr allocLimit, stripeLimit, oldLimit, limit;
|
||||
Res res;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(ZonedCBS, zcbs);
|
||||
AVER(size > 0);
|
||||
/* FIXME: findDelete? */
|
||||
/* FIXME: ZoneSet? */
|
||||
AVER(BoolCheck(high));
|
||||
|
||||
find = high ? CBSFindLast : CBSFindFirst;
|
||||
|
||||
/* Try the zone CBSs first. */
|
||||
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. */
|
||||
|
|
@ -263,6 +259,8 @@ static Res ZonedCBSFind(Range rangeReturn,
|
|||
|
||||
/* 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) &&
|
||||
|
|
@ -270,54 +268,100 @@ static Res ZonedCBSFind(Range rangeReturn,
|
|||
size, findDelete))
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
/* Try the free CBS. */
|
||||
|
||||
if (high)
|
||||
res = CBSFindLastInZones(rangeReturn, oldRangeReturn,
|
||||
ZonedCBSFreeCBS(zcbs), size, zcbs->arena, zones);
|
||||
else
|
||||
res = CBSFindFirstInZones(rangeReturn, oldRangeReturn,
|
||||
ZonedCBSFreeCBS(zcbs), size, zcbs->arena, zones);
|
||||
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, and we should fix it. Flush the zone CBSs
|
||||
back to the free 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 */
|
||||
/* Put it back. This should succeed. */
|
||||
if (res != ResOK) { /* disasterously short on memory, so put it back */
|
||||
res = CBSInsert(&oldRange, ZonedCBSFreeCBS(zcbs), &restRange);
|
||||
AVER(res == ResOK);
|
||||
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)
|
||||
|
|
@ -333,6 +377,7 @@ Bool ZonedCBSFindLast(Range rangeReturn, Range oldRangeReturn,
|
|||
return ZonedCBSFind(rangeReturn, oldRangeReturn, zcbs, zones, size,
|
||||
findDelete, TRUE);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
|
|
|
|||
|
|
@ -27,12 +27,23 @@ 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 */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue