Res SegAlloc(Seg *segReturn, SegClass klass, LocusPref pref, Size size, Pool pool, ArgList args) { Res res; Arena arena; Seg seg; Addr base; void *p; AVER(segReturn != NULL); AVERT(SegClass, klass); AVERT(LocusPref, pref); AVER(size > (Size)0); AVERT(Pool, pool); arena = PoolArena(pool); AVERT(Arena, arena); AVER(SizeIsArenaGrains(size, arena)); /* allocate the memory from the arena */ res = ArenaAlloc(&base, pref, size, pool); if (res != ResOK) goto failArena; /* allocate the segment object from the control pool */ res = ControlAlloc(&p, arena, klass->size); if (res != ResOK) goto failControl; seg = p; res = SegInit(seg, klass, pool, base, size, args); if (res != ResOK) goto failInit; EVENT5(SegAlloc, arena, seg, SegBase(seg), size, pool); *segReturn = seg; return ResOK; failInit: ControlFree(arena, seg, klass->size); failControl: ArenaFree(base, size, pool); failArena: EVENT3(SegAllocFail, arena, size, pool); return res; }
static Res SegAbsInit(Seg seg, Pool pool, Addr base, Size size, ArgList args) { Arena arena; Addr addr, limit; Tract tract; AVER(seg != NULL); AVERT(Pool, pool); arena = PoolArena(pool); AVER(AddrIsArenaGrain(base, arena)); AVER(SizeIsArenaGrains(size, arena)); AVERT(ArgList, args); NextMethod(Inst, Seg, init)(CouldBeA(Inst, seg)); limit = AddrAdd(base, size); seg->limit = limit; seg->rankSet = RankSetEMPTY; seg->white = TraceSetEMPTY; seg->nailed = TraceSetEMPTY; seg->grey = TraceSetEMPTY; seg->pm = AccessSetEMPTY; seg->sm = AccessSetEMPTY; seg->defer = WB_DEFER_INIT; seg->depth = 0; seg->queued = FALSE; seg->firstTract = NULL; RingInit(SegPoolRing(seg)); TRACT_FOR(tract, addr, arena, base, limit) { AVERT(Tract, tract); AVER(TractP(tract) == NULL); AVER(!TractHasSeg(tract)); AVER(TractPool(tract) == pool); AVER(TractWhite(tract) == TraceSetEMPTY); TRACT_SET_SEG(tract, seg); if (addr == base) { AVER(seg->firstTract == NULL); seg->firstTract = tract; } AVER(seg->firstTract != NULL); }
Bool MFSCheck(MFS mfs) { Arena arena; CHECKS(MFS, mfs); CHECKC(MFSPool, mfs); CHECKD(Pool, MFSPool(mfs)); CHECKC(MFSPool, mfs); CHECKL(mfs->unitSize >= UNIT_MIN); CHECKL(mfs->extendBy >= UNIT_MIN); CHECKL(BoolCheck(mfs->extendSelf)); arena = PoolArena(MFSPool(mfs)); CHECKL(SizeIsArenaGrains(mfs->extendBy, arena)); CHECKL(SizeAlignUp(mfs->unroundedUnitSize, PoolAlignment(MFSPool(mfs))) == mfs->unitSize); if(mfs->tractList != NULL) { CHECKD_NOSIG(Tract, mfs->tractList); } CHECKL(mfs->free <= mfs->total); CHECKL((mfs->total - mfs->free) % mfs->unitSize == 0); return TRUE; }
/* 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; }