static void MVFFFree(Pool pool, Addr old, Size size) { Res res; Addr base, limit; MVFF mvff; AVERT(Pool, pool); mvff = Pool2MVFF(pool); AVERT(MVFF, mvff); AVER(old != (Addr)0); AVER(AddrIsAligned(old, PoolAlignment(pool))); AVER(size > 0); size = SizeAlignUp(size, PoolAlignment(pool)); base = old; limit = AddrAdd(base, size); res = MVFFAddToFreeList(&base, &limit, mvff); AVER(res == ResOK); if (res == ResOK) MVFFFreeSegs(mvff, base, limit); return; }
static void MVFFFinish(Pool pool) { MVFF mvff; Arena arena; Seg seg; Ring ring, node, nextNode; AVERT(Pool, pool); mvff = Pool2MVFF(pool); AVERT(MVFF, mvff); ring = PoolSegRing(pool); RING_FOR(node, ring, nextNode) { seg = SegOfPoolRing(node); AVER(SegPool(seg) == pool); SegFree(seg); }
static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size, Bool withReservoirPermit, DebugInfo info) { Res res; MVFF mvff; Addr base, limit; Bool foundBlock; AVERT(Pool, pool); mvff = Pool2MVFF(pool); AVERT(MVFF, mvff); AVER(aReturn != NULL); AVER(size > 0); AVER(BoolCheck(withReservoirPermit)); UNUSED(info); size = SizeAlignUp(size, PoolAlignment(pool)); foundBlock = MVFFFindFirstFree(&base, &limit, mvff, size); if (!foundBlock) { Seg seg; res = MVFFAddSeg(&seg, mvff, size, withReservoirPermit); if (res != ResOK) return res; foundBlock = MVFFFindFirstFree(&base, &limit, mvff, size); /* We know that the found range must intersect the new segment. */ /* In particular, it doesn't necessarily lie entirely within it. */ /* The next three AVERs test for intersection of two intervals. */ AVER(base >= SegBase(seg) || limit <= SegLimit(seg)); AVER(base < SegLimit(seg)); AVER(SegBase(seg) < limit); /* We also know that the found range is no larger than the segment. */ AVER(SegSize(seg) >= AddrOffset(base, limit)); } AVER(foundBlock); AVER(AddrOffset(base, limit) == size); *aReturn = base; return ResOK; }
/* MVFFBufferFill -- Fill the buffer * * Fill it with the largest block we can find. */ static Res MVFFBufferFill(Addr *baseReturn, Addr *limitReturn, Pool pool, Buffer buffer, Size size, Bool withReservoirPermit) { Res res; MVFF mvff; Addr base, limit; Bool foundBlock; Seg seg = NULL; AVER(baseReturn != NULL); AVER(limitReturn != NULL); AVERT(Pool, pool); mvff = Pool2MVFF(pool); AVERT(MVFF, mvff); AVERT(Buffer, buffer); AVER(size > 0); AVER(SizeIsAligned(size, PoolAlignment(pool))); AVERT(Bool, withReservoirPermit); /* Hoping the largest is big enough, delete it and return if small. */ foundBlock = CBSFindLargest(&base, &limit, CBSOfMVFF(mvff), CBSFindDeleteENTIRE); if (foundBlock && AddrOffset(base, limit) < size) { foundBlock = FALSE; res = CBSInsert(CBSOfMVFF(mvff), base, limit); AVER(res == ResOK); } if (!foundBlock) { res = MVFFAddSeg(&seg, mvff, size, withReservoirPermit); if (res != ResOK) return res; foundBlock = CBSFindLargest(&base, &limit, CBSOfMVFF(mvff), CBSFindDeleteENTIRE); AVER(foundBlock); /* We will find the new segment. */ } AVER(AddrOffset(base, limit) >= size); mvff->free -= AddrOffset(base, limit); *baseReturn = base; *limitReturn = limit; return ResOK; }
static void MVFFBufferEmpty(Pool pool, Buffer buffer, Addr base, Addr limit) { MVFF mvff; AVERT(Pool, pool); mvff = Pool2MVFF(pool); AVERT(MVFF, mvff); AVERT(Buffer, buffer); AVER(BufferIsReady(buffer)); AVER(base <= limit); if (base == limit) return; MVFFAddToFreeList(&base, &limit, mvff); MVFFFreeSegs(mvff, base, limit); return; }
static void MVFFFinish(Pool pool) { MVFF mvff; Arena arena; Seg seg; Ring ring, node, nextNode; AVERT(Pool, pool); mvff = Pool2MVFF(pool); AVERT(MVFF, mvff); /* Do this first, because the free list can use the segs in an emergency. */ CBSFinish(CBSOfMVFF(mvff)); ring = PoolSegRing(pool); RING_FOR(node, ring, nextNode) { seg = SegOfPoolRing(node); AVER(SegPool(seg) == pool); SegFree(seg); }
static void MVFFFree(Pool pool, Addr old, Size size) { Addr base, limit; MVFF mvff; AVERT(Pool, pool); mvff = Pool2MVFF(pool); AVERT(MVFF, mvff); AVER(old != (Addr)0); AVER(size > 0); base = AddrAlignUp(old, PoolAlignment(pool)); size = size - AddrOffset(old, base); size = SizeAlignUp(size, PoolAlignment(pool)); limit = AddrAdd(base, size); MVFFAddToFreeList(&base, &limit, mvff); MVFFFreeSegs(mvff, base, limit); }
/* MVFFBufferFill -- Fill the buffer * * Fill it with the largest block we can find. */ static Res MVFFBufferFill(Addr *baseReturn, Addr *limitReturn, Pool pool, Buffer buffer, Size size, Bool withReservoirPermit) { Res res; MVFF mvff; RangeStruct range, oldRange; Bool found; Seg seg = NULL; AVER(baseReturn != NULL); AVER(limitReturn != NULL); AVERT(Pool, pool); mvff = Pool2MVFF(pool); AVERT(MVFF, mvff); AVERT(Buffer, buffer); AVER(size > 0); AVER(SizeIsAligned(size, PoolAlignment(pool))); AVERT(Bool, withReservoirPermit); found = MVFFFindLargest(&range, &oldRange, mvff, size, FindDeleteENTIRE); if (!found) { /* Add a new segment to the free list and try again. */ res = MVFFAddSeg(&seg, mvff, size, withReservoirPermit); if (res != ResOK) return res; found = MVFFFindLargest(&range, &oldRange, mvff, size, FindDeleteENTIRE); } AVER(found); AVER(RangeSize(&range) >= size); mvff->free -= RangeSize(&range); *baseReturn = RangeBase(&range); *limitReturn = RangeLimit(&range); return ResOK; }
static Res MVFFInit(Pool pool, ArgList args) { Size extendBy = MVFF_EXTEND_BY_DEFAULT; Size avgSize = MVFF_AVG_SIZE_DEFAULT; Size align = MVFF_ALIGN_DEFAULT; Bool slotHigh = MVFF_SLOT_HIGH_DEFAULT; Bool arenaHigh = MVFF_ARENA_HIGH_DEFAULT; Bool firstFit = MVFF_FIRST_FIT_DEFAULT; MVFF mvff; Arena arena; Res res; void *p; ArgStruct arg; AVERT(Pool, pool); arena = PoolArena(pool); /* .arg: class-specific additional arguments; see */ /* <design/poolmvff/#method.init> */ /* .arg.check: we do the same checks here and in MVFFCheck */ /* except for arenaHigh, which is stored only in the segPref. */ if (ArgPick(&arg, args, MPS_KEY_EXTEND_BY)) extendBy = arg.val.size; if (ArgPick(&arg, args, MPS_KEY_MEAN_SIZE)) avgSize = arg.val.size; if (ArgPick(&arg, args, MPS_KEY_ALIGN)) align = arg.val.align; if (ArgPick(&arg, args, MPS_KEY_MVFF_SLOT_HIGH)) slotHigh = arg.val.b; if (ArgPick(&arg, args, MPS_KEY_MVFF_ARENA_HIGH)) arenaHigh = arg.val.b; if (ArgPick(&arg, args, MPS_KEY_MVFF_FIRST_FIT)) firstFit = arg.val.b; AVER(extendBy > 0); /* .arg.check */ AVER(avgSize > 0); /* .arg.check */ AVER(avgSize <= extendBy); /* .arg.check */ AVER(SizeIsAligned(align, MPS_PF_ALIGN)); AVERT(Bool, slotHigh); AVERT(Bool, arenaHigh); AVERT(Bool, firstFit); mvff = Pool2MVFF(pool); mvff->extendBy = extendBy; if (extendBy < ArenaAlign(arena)) mvff->minSegSize = ArenaAlign(arena); else mvff->minSegSize = extendBy; mvff->avgSize = avgSize; pool->alignment = align; mvff->slotHigh = slotHigh; mvff->firstFit = firstFit; res = ControlAlloc(&p, arena, sizeof(SegPrefStruct), FALSE); if (res != ResOK) return res; mvff->segPref = (SegPref)p; SegPrefInit(mvff->segPref); SegPrefExpress(mvff->segPref, arenaHigh ? SegPrefHigh : SegPrefLow, NULL); mvff->total = 0; mvff->free = 0; res = FreelistInit(FreelistOfMVFF(mvff), align); if (res != ResOK) goto failInit; res = CBSInit(CBSOfMVFF(mvff), arena, (void *)mvff, align, /* fastFind */ TRUE, /* zoned */ FALSE, args); if (res != ResOK) goto failInit; mvff->sig = MVFFSig; AVERT(MVFF, mvff); EVENT8(PoolInitMVFF, pool, arena, extendBy, avgSize, align, BOOL(slotHigh), BOOL(arenaHigh), BOOL(firstFit)); return ResOK; failInit: ControlFree(arena, p, sizeof(SegPrefStruct)); return res; }
static Res MVFFInit(Pool pool, va_list arg) { Size extendBy, avgSize, align; Bool slotHigh, arenaHigh, firstFit; MVFF mvff; Arena arena; Res res; void *p; ZoneSet zones; AVERT(Pool, pool); /* .arg: class-specific additional arguments; see */ /* <design/poolmvff/#method.init> */ /* .arg.check: we do the same checks here and in MVFFCheck */ /* except for arenaHigh, which is stored only in the segPref. */ extendBy = va_arg(arg, Size); avgSize = va_arg(arg, Size); align = va_arg(arg, Size); slotHigh = va_arg(arg, Bool); arenaHigh = va_arg(arg, Bool); firstFit = va_arg(arg, Bool); AVER(extendBy > 0); /* .arg.check */ AVER(avgSize > 0); /* .arg.check */ AVER(avgSize <= extendBy); /* .arg.check */ AVER(BoolCheck(slotHigh)); AVER(BoolCheck(arenaHigh)); AVER(BoolCheck(firstFit)); mvff = Pool2MVFF(pool); arena = PoolArena(pool); mvff->extendBy = extendBy; if (extendBy < ArenaAlign(arena)) mvff->minSegSize = ArenaAlign(arena); else mvff->minSegSize = extendBy; mvff->avgSize = avgSize; pool->alignment = align; mvff->slotHigh = slotHigh; mvff->firstFit = firstFit; res = ControlAlloc(&p, arena, sizeof(SegPrefStruct), FALSE); if (res != ResOK) return res; mvff->segPref = (SegPref)p; *mvff->segPref = *SegPrefDefault(); SegPrefExpress(mvff->segPref, arenaHigh ? SegPrefHigh : SegPrefLow, NULL); /* If using zoneset placement, just put it apart from the others. */ zones = ZoneSetComp(ArenaDefaultZONESET); SegPrefExpress(mvff->segPref, SegPrefZoneSet, (void *)&zones); mvff->total = 0; mvff->free = 0; res = CBSInit(arena, CBSOfMVFF(mvff), (void *)mvff, NULL, NULL, NULL, NULL, mvff->extendBy, align, TRUE, TRUE); if (res != ResOK) goto failInit; mvff->sig = MVFFSig; AVERT(MVFF, mvff); EVENT8(PoolInitMVFF, pool, arena, extendBy, avgSize, align, slotHigh, arenaHigh, firstFit); return ResOK; failInit: ControlFree(arena, p, sizeof(SegPrefStruct)); return res; }