ATTRIBUTE_UNUSED static Bool MVTCheck(MVT mvt) { CHECKS(MVT, mvt); CHECKC(MVTPool, mvt); CHECKD(Pool, MVTPool(mvt)); CHECKC(MVTPool, mvt); CHECKD(CBS, &mvt->cbsStruct); CHECKD(ABQ, &mvt->abqStruct); CHECKD(Freelist, &mvt->flStruct); CHECKD(Failover, &mvt->foStruct); CHECKL(mvt->reuseSize >= 2 * mvt->fillSize); CHECKL(mvt->fillSize >= mvt->maxSize); CHECKL(mvt->maxSize >= mvt->meanSize); CHECKL(mvt->meanSize >= mvt->minSize); CHECKL(mvt->minSize > 0); CHECKL(mvt->fragLimit <= 100); CHECKL(mvt->availLimit == mvt->size * mvt->fragLimit / 100); CHECKL(BoolCheck(mvt->abqOverflow)); CHECKL(BoolCheck(mvt->splinter)); if (mvt->splinter) { CHECKL(AddrOffset(mvt->splinterBase, mvt->splinterLimit) >= mvt->minSize); CHECKL(mvt->splinterBase < mvt->splinterLimit); } CHECKL(mvt->size == mvt->allocated + mvt->available + mvt->unavailable); /* --- could check that sum of segment sizes == mvt->size */ /* --- check meters? */ return TRUE; }
Bool ThreadCheck(Thread thread) { CHECKS(Thread, thread); CHECKU(Arena, thread->arena); CHECKL(thread->serial < thread->arena->threadSerial); CHECKD_NOSIG(Ring, &thread->arenaRing); CHECKL(BoolCheck(thread->alive)); CHECKL(BoolCheck(thread->forking)); CHECKL(MACH_PORT_VALID(thread->port)); return TRUE; }
static Bool EPVMSaveCheck(EPVMSave save) { CHECKS(EPVMSave, save); CHECKU(EPVM, save->epvm); CHECKL(save->level <= save->epvm->maxSaveLevel); CHECKL(save->size <= PoolManagedSize(EPVM2Pool(save->epvm))); if (save->level > save->epvm->saveLevel) /* nothing at this level */ CHECKL(save->size == 0); CHECKL(SizeIsAligned(save->size, ArenaAlign(PoolArena(EPVM2Pool(save->epvm))))); CHECKL(BoolCheck(save->smallStringSeg)); CHECKL(BoolCheck(save->smallObjectSeg)); CHECKL(RingCheck(&save->segRing)); return TRUE; }
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; }
Bool ThreadCheck(Thread thread) { CHECKS(Thread, thread); CHECKU(Arena, thread->arena); CHECKL(thread->serial < thread->arena->threadSerial); CHECKD_NOSIG(Ring, &thread->arenaRing); CHECKL(BoolCheck(thread->alive)); CHECKD(PThreadext, &thread->thrextStruct); return TRUE; }
static Res BufferAbsInit(Buffer buffer, Pool pool, Bool isMutator, ArgList args) { Arena arena; AVER(buffer != NULL); AVERT(Pool, pool); AVER(BoolCheck(isMutator)); AVERT(ArgList, args); /* Superclass init */ InstInit(CouldBeA(Inst, buffer)); arena = PoolArena(pool); /* Initialize the buffer. See <code/mpmst.h> for a definition of the structure. sig and serial comes later .init.sig-serial */ buffer->arena = arena; buffer->pool = pool; RingInit(&buffer->poolRing); buffer->isMutator = isMutator; if (ArenaGlobals(arena)->bufferLogging) { buffer->mode = BufferModeLOGGED; } else { buffer->mode = 0; } buffer->fillSize = 0.0; buffer->emptySize = 0.0; buffer->alignment = PoolAlignment(pool); buffer->base = (Addr)0; buffer->initAtFlip = (Addr)0; /* In the next three assignments we really mean zero, not NULL, because the bit pattern is compared. It's pretty unlikely we'll encounter a platform where this makes a difference. */ buffer->ap_s.init = (mps_addr_t)0; buffer->ap_s.alloc = (mps_addr_t)0; buffer->ap_s.limit = (mps_addr_t)0; buffer->poolLimit = (Addr)0; buffer->rampCount = 0; /* .init.sig-serial: Now the vanilla stuff is initialized, sign the buffer and give it a serial number. It can then be safely checked in subclass methods. */ buffer->serial = pool->bufferSerial; /* .trans.mod */ ++pool->bufferSerial; SetClassOfPoly(buffer, CLASS(Buffer)); buffer->sig = BufferSig; AVERT(Buffer, buffer); /* Attach the initialized buffer to the pool. */ RingAppend(&pool->bufferRing, &buffer->poolRing); EVENT3(BufferInit, buffer, pool, BOOLOF(buffer->isMutator)); return ResOK; }
/* MVFFAddSeg -- Allocates a new segment from the arena * * Allocates a new segment from the arena (with the given * withReservoirPermit flag) of at least the specified size. The * specified size should be pool-aligned. Adds it to the free list. */ static Res MVFFAddSeg(Seg *segReturn, MVFF mvff, Size size, Bool withReservoirPermit) { Pool pool; Arena arena; Size segSize; Seg seg; Res res; Align align; Addr base, limit; AVERT(MVFF, mvff); AVER(size > 0); AVER(BoolCheck(withReservoirPermit)); pool = MVFF2Pool(mvff); arena = PoolArena(pool); align = ArenaAlign(arena); AVER(SizeIsAligned(size, PoolAlignment(pool))); /* Use extendBy unless it's too small (see */ /* <design/poolmvff/#design.seg-size>). */ if (size <= mvff->extendBy) segSize = mvff->extendBy; else segSize = size; segSize = SizeAlignUp(segSize, align); res = SegAlloc(&seg, SegClassGet(), mvff->segPref, segSize, pool, withReservoirPermit); if (res != ResOK) { /* try again for a seg just large enough for object */ /* see <design/poolmvff/#design.seg-fail> */ segSize = SizeAlignUp(size, align); res = SegAlloc(&seg, SegClassGet(), mvff->segPref, segSize, pool, withReservoirPermit); if (res != ResOK) { return res; } } mvff->total += segSize; base = SegBase(seg); limit = AddrAdd(base, segSize); DebugPoolFreeSplat(pool, base, limit); MVFFAddToFreeList(&base, &limit, mvff); AVER(base <= SegBase(seg)); if (mvff->minSegSize > segSize) mvff->minSegSize = segSize; /* Don't call MVFFFreeSegs; that would be silly. */ *segReturn = seg; return ResOK; }
static Res NAlloc(Addr *pReturn, Pool pool, Size size, Bool withReservoirPermit) { PoolN poolN; AVERT(Pool, pool); poolN = PoolPoolN(pool); AVERT(PoolN, poolN); AVER(pReturn != NULL); AVER(size > 0); AVER(BoolCheck(withReservoirPermit)); return ResLIMIT; /* limit of nil blocks exceeded */ }
ATTRIBUTE_UNUSED static Bool SACCheck(SAC sac) { Index i, j; Bool b; Size prevSize; mps_sac_t esac; CHECKS(SAC, sac); esac = ExternalSACOfSAC(sac); CHECKU(Pool, sac->pool); CHECKL(sac->classesCount > 0); CHECKL(sac->classesCount > sac->middleIndex); CHECKL(BoolCheck(esac->_trapped)); CHECKL(esac->_middle > 0); /* check classes above middle */ prevSize = esac->_middle; for (j = sac->middleIndex + 1, i = 0; j < sac->classesCount; ++j, i += 2) { CHECKL(prevSize < esac->_freelists[i]._size); b = sacFreeListBlockCheck(&(esac->_freelists[i])); if (!b) return b; prevSize = esac->_freelists[i]._size; } /* check overlarge class */ CHECKL(prevSize < esac->_freelists[i]._size); b = sacFreeListBlockCheck(&(esac->_freelists[i])); if (!b) return b; CHECKL(esac->_freelists[i]._size == SizeMAX); CHECKL(esac->_freelists[i]._count == 0); CHECKL(esac->_freelists[i]._count_max == 0); CHECKL(esac->_freelists[i]._blocks == NULL); /* check classes below middle */ prevSize = esac->_middle; for (j = sac->middleIndex, i = 1; j > 0; --j, i += 2) { CHECKL(prevSize > esac->_freelists[i]._size); b = sacFreeListBlockCheck(&(esac->_freelists[i])); if (!b) return b; prevSize = esac->_freelists[i]._size; } /* check smallest class */ CHECKL(prevSize > esac->_freelists[i]._size); CHECKL(esac->_freelists[i]._size == 0); b = sacFreeListBlockCheck(&(esac->_freelists[i])); return b; }
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; }
static Res NBufferFill(Addr *baseReturn, Addr *limitReturn, Pool pool, Buffer buffer, Size size, Bool withReservoirPermit) { PoolN poolN; AVERT(Pool, pool); poolN = PoolPoolN(pool); AVERT(PoolN, poolN); AVER(baseReturn != NULL); AVER(limitReturn != NULL); AVERT(Buffer, buffer); AVER(BufferIsReset(buffer)); AVER(size > 0); AVER(BoolCheck(withReservoirPermit)); NOTREACHED; /* can't create buffers, so shouldn't fill them */ return ResUNIMPL; }
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; }
Bool ArgCheckBool(Arg arg) { CHECKL(BoolCheck(arg->val.b)); return TRUE; }
Bool BufferCheck(Buffer buffer) { CHECKS(Buffer, buffer); CHECKC(Buffer, buffer); CHECKL(buffer->serial < buffer->pool->bufferSerial); /* .trans.mod */ CHECKU(Arena, buffer->arena); CHECKU(Pool, buffer->pool); CHECKL(buffer->arena == buffer->pool->arena); CHECKD_NOSIG(Ring, &buffer->poolRing); CHECKL(BoolCheck(buffer->isMutator)); CHECKL(buffer->fillSize >= 0.0); CHECKL(buffer->emptySize >= 0.0); CHECKL(buffer->emptySize <= buffer->fillSize); CHECKL(buffer->alignment == buffer->pool->alignment); CHECKL(AlignCheck(buffer->alignment)); /* If any of the buffer's fields indicate that it is reset, make */ /* sure it is really reset. Otherwise, check various properties */ /* of the non-reset fields. */ if (buffer->mode & BufferModeTRANSITION) { /* nothing to check */ } else if ((buffer->mode & BufferModeATTACHED) == 0 || buffer->base == (Addr)0 || buffer->ap_s.init == (Addr)0 || buffer->ap_s.alloc == (Addr)0 || buffer->poolLimit == (Addr)0) { CHECKL((buffer->mode & BufferModeATTACHED) == 0); CHECKL(buffer->base == (Addr)0); CHECKL(buffer->initAtFlip == (Addr)0); CHECKL(buffer->ap_s.init == (Addr)0); CHECKL(buffer->ap_s.alloc == (Addr)0); CHECKL(buffer->ap_s.limit == (Addr)0); /* Nothing reliable to check for lightweight frame state */ CHECKL(buffer->poolLimit == (Addr)0); } else { /* The buffer is attached to a region of memory. */ /* Check consistency. */ CHECKL(buffer->mode & BufferModeATTACHED); /* These fields should obey the ordering */ /* base <= init <= alloc <= poolLimit */ CHECKL((mps_addr_t)buffer->base <= buffer->ap_s.init); CHECKL(buffer->ap_s.init <= buffer->ap_s.alloc); CHECKL(buffer->ap_s.alloc <= (mps_addr_t)buffer->poolLimit); /* Check that the fields are aligned to the buffer alignment. */ CHECKL(AddrIsAligned(buffer->base, buffer->alignment)); CHECKL(AddrIsAligned(buffer->initAtFlip, buffer->alignment)); CHECKL(AddrIsAligned(buffer->ap_s.init, buffer->alignment)); CHECKL(AddrIsAligned(buffer->ap_s.alloc, buffer->alignment)); CHECKL(AddrIsAligned(buffer->ap_s.limit, buffer->alignment)); CHECKL(AddrIsAligned(buffer->poolLimit, buffer->alignment)); /* If the buffer isn't trapped then "limit" should be the limit */ /* set by the owning pool. Otherwise, "init" is either at the */ /* same place it was at flip (.commit.before) or has been set */ /* to "alloc" (.commit.after). Also, when the buffer is */ /* flipped, initAtFlip should hold the init at flip, which is */ /* between the base and current init. Otherwise, initAtFlip */ /* is kept at zero to avoid misuse (see */ /* request.dylan.170429.sol.zero_). */ /* .. _request.dylan.170429.sol.zero: https://info.ravenbrook.com/project/mps/import/2001-11-05/mmprevol/request/dylan/170429 */ if (BufferIsTrapped(buffer)) { /* .check.use-trapped: This checking function uses BufferIsTrapped, */ /* So BufferIsTrapped can't do checking as that would cause an */ /* infinite loop. */ if (buffer->mode & BufferModeFLIPPED) { CHECKL(buffer->ap_s.init == buffer->initAtFlip || buffer->ap_s.init == buffer->ap_s.alloc); CHECKL(buffer->base <= buffer->initAtFlip); CHECKL(buffer->initAtFlip <= (Addr)buffer->ap_s.init); } /* Nothing special to check in the logged mode. */ } else { CHECKL(buffer->initAtFlip == (Addr)0); } } return TRUE; }
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; }