static Res EPVMSegInit(Seg seg, Pool pool, Addr base, Size size, Bool reservoirPermit, va_list args) { SegClass super; EPVMSeg epvmSeg; EPVM epvm; EPVMSave save; Res res; AVERT(Seg, seg); epvmSeg = Seg2EPVMSeg(seg); AVERT(Pool, pool); epvm = Pool2EPVM(pool); AVERT(EPVM, epvm); /* no useful checks for base and size */ AVER(BoolCheck(reservoirPermit)); /* Initialize the superclass fields first via next-method call */ super = SEG_SUPERCLASS(EPVMSegClass); res = super->init(seg, pool, base, size, reservoirPermit, args); if (res != ResOK) return res; save = EPVMCurrentSave(epvm); epvmSeg->save = save; save->size += SegSize(seg); /* The small*Seg flag can't be set here, because the rankset is not set. */ epvmSeg->sig = EPVMSegSig; AVERT(EPVMSeg, epvmSeg); return ResOK; }
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; }
Bool EPVMSegCheck(EPVMSeg epvmSeg) { Seg seg; CHECKS(EPVMSeg, epvmSeg); CHECKL(AMSSegCheck(&epvmSeg->amsSegStruct)); seg = EPVMSeg2Seg(epvmSeg); CHECKU(EPVMSave, epvmSeg->save); CHECKL(epvmSeg->save->size >= SegSize(seg)); /* buffers only on the current save level */ if (SegBuffer(seg) != NULL) CHECKL(EPVMCurrentSave(EPVMSegEPVM(epvmSeg)) == epvmSeg->save); /* See design.mps.poolepvm.protection.format and */ /* d.m.p.protection.hack. */ AVER(SegSummary(seg) == RefSetUNIV || SegSummary(seg) == RefSetEMPTY); return TRUE; }
void SegFree(Seg seg) { Arena arena; Pool pool; Addr base; Size size, structSize; AVERT(Seg, seg); pool = SegPool(seg); AVERT(Pool, pool); arena = PoolArena(pool); AVERT(Arena, arena); base = SegBase(seg); size = SegSize(seg); structSize = ClassOfPoly(Seg, seg)->size; SegFinish(seg); ControlFree(arena, seg, structSize); ArenaFree(base, size, pool); EVENT2(SegFree, arena, seg); }
static void EPVMSegFinish(Seg seg) { EPVMSeg epvmSeg; EPVMSave save; Size size; AVERT(Seg, seg); epvmSeg = Seg2EPVMSeg(seg); AVERT(EPVMSeg, epvmSeg); size = SegSize(seg); save = epvmSeg->save; AVERT(EPVMSave, save); epvmSeg->sig = SigInvalid; /* finish the superclass fields last */ SEG_SUPERCLASS(EPVMSegClass)->finish(seg); /* save->size must be consistent when calling super, so update after */ AVER(save->size >= size); save->size -= size; }
/* AMSTBufferFill -- the pool class buffer fill method * * Calls next method - but possibly splits or merges the chosen * segment. * * .merge: A merge is performed when the next method returns the * entire segment, this segment had previously been split from the * segment below, and the segment below is appropriately similar * (i.e. not already attached to a buffer and similarly coloured) * * .split: If we're not merging, a split is performed if the next method * returns the entire segment, and yet lower half of the segment would * meet the request. */ static Res AMSTBufferFill(Addr *baseReturn, Addr *limitReturn, Pool pool, Buffer buffer, Size size) { Addr base, limit; Arena arena; AMS ams; AMST amst; Bool b; Seg seg; AMSTSeg amstseg; Res res; AVERT(Pool, pool); AVER(baseReturn != NULL); AVER(limitReturn != NULL); /* other parameters are checked by next method */ arena = PoolArena(pool); ams = PoolAMS(pool); amst = PoolAMST(pool); /* call next method */ res = NextMethod(Pool, AMSTPool, bufferFill)(&base, &limit, pool, buffer, size); if (res != ResOK) return res; b = SegOfAddr(&seg, arena, base); AVER(b); amstseg = Seg2AMSTSeg(seg); if (SegLimit(seg) == limit && SegBase(seg) == base) { if (amstseg->prev != NULL) { Seg segLo = AMSTSeg2Seg(amstseg->prev); if (!SegHasBuffer(segLo) && SegGrey(segLo) == SegGrey(seg) && SegWhite(segLo) == SegWhite(seg)) { /* .merge */ Seg mergedSeg; Res mres; AMSUnallocateRange(ams, seg, base, limit); mres = SegMerge(&mergedSeg, segLo, seg); if (ResOK == mres) { /* successful merge */ AMSAllocateRange(ams, mergedSeg, base, limit); /* leave range as-is */ } else { /* failed to merge */ AVER(amst->failSegs); /* deliberate fails only */ AMSAllocateRange(ams, seg, base, limit); } } } else { Size half = SegSize(seg) / 2; if (half >= size && SizeIsArenaGrains(half, arena)) { /* .split */ Addr mid = AddrAdd(base, half); Seg segLo, segHi; Res sres; AMSUnallocateRange(ams, seg, mid, limit); sres = SegSplit(&segLo, &segHi, seg, mid); if (ResOK == sres) { /* successful split */ limit = mid; /* range is lower segment */ } else { /* failed to split */ AVER(amst->failSegs); /* deliberate fails only */ AMSAllocateRange(ams, seg, mid, limit); } } } } *baseReturn = base; *limitReturn = limit; return ResOK; }