Bool MPMCheck(void) { CHECKL(sizeof(Word) * CHAR_BIT == MPS_WORD_WIDTH); CHECKL((Word)1 << MPS_WORD_SHIFT == MPS_WORD_WIDTH); CHECKL(AlignCheck(MPS_PF_ALIGN)); /* Check that trace ids will fit in the TraceId type. */ CHECKL(TraceLIMIT <= UINT_MAX); /* Check that there are enough bits in */ /* a TraceSet to store all possible trace ids. */ CHECKL(sizeof(TraceSet) * CHAR_BIT >= TraceLIMIT); CHECKL((SizeAlignUp(0, 2048) == 0)); CHECKL(!SizeIsAligned(64, (unsigned) -1)); CHECKL(SizeIsAligned(0, 32)); CHECKL((SizeAlignUp(1024, 16) == 1024)); /* .prime: 31051 is prime */ CHECKL(SizeIsAligned(SizeAlignUp(31051, 256), 256)); CHECKL(SizeIsAligned(SizeAlignUp(31051, 512), 512)); CHECKL(!SizeIsAligned(31051, 1024)); CHECKL(!SizeIsP2(0)); CHECKL(SizeIsP2(128)); CHECKL(SizeLog2((Size)1) == 0); CHECKL(SizeLog2((Size)256) == 8); CHECKL(SizeLog2((Size)65536) == 16); CHECKL(SizeLog2((Size)131072) == 17); /* .check.writef: We check that various types will fit in a Word; */ /* See .writef.check. Don't need to check WriteFS or WriteFF as they */ /* should not be cast to Word. */ CHECKL(sizeof(WriteFA) <= sizeof(Word)); CHECKL(sizeof(WriteFP) <= sizeof(Word)); CHECKL(sizeof(WriteFW) <= sizeof(Word)); /* Should be trivial*/ CHECKL(sizeof(WriteFU) <= sizeof(Word)); CHECKL(sizeof(WriteFB) <= sizeof(Word)); CHECKL(sizeof(WriteFC) <= sizeof(Word)); /* .check.write.double: See .write.double.check */ { int e, DBL_EXP_DIG = 1; for (e = DBL_MAX_10_EXP; e > 0; e /= 10) DBL_EXP_DIG++; CHECKL(DBL_EXP_DIG < DBL_DIG); CHECKL(-(DBL_MIN_10_EXP) <= DBL_MAX_10_EXP); } return TRUE; }
Res ChunkInit(Chunk chunk, Arena arena, Addr base, Addr limit, Size reserved, BootBlock boot) { Size size; Count pages; Shift pageShift; Size pageTableSize; Addr allocBase; void *p; Res res; /* chunk is supposed to be uninitialized, so don't check it. */ AVERT(Arena, arena); AVER(base != NULL); AVER(AddrIsAligned(base, ArenaGrainSize(arena))); AVER(base < limit); AVER(AddrIsAligned(limit, ArenaGrainSize(arena))); AVERT(BootBlock, boot); chunk->serial = (arena->chunkSerial)++; chunk->arena = arena; RingInit(&chunk->arenaRing); chunk->pageSize = ArenaGrainSize(arena); chunk->pageShift = pageShift = SizeLog2(chunk->pageSize); chunk->base = base; chunk->limit = limit; chunk->reserved = reserved; size = ChunkSize(chunk); /* .overhead.pages: Chunk overhead for the page allocation table. */ chunk->pages = pages = size >> pageShift; res = BootAlloc(&p, boot, (size_t)BTSize(pages), MPS_PF_ALIGN); if (res != ResOK) goto failAllocTable; chunk->allocTable = p; pageTableSize = SizeAlignUp(pages * sizeof(PageUnion), chunk->pageSize); chunk->pageTablePages = pageTableSize >> pageShift; res = Method(Arena, arena, chunkInit)(chunk, boot); if (res != ResOK) goto failClassInit; /* @@@@ Is BootAllocated always right? */ /* Last thing we BootAlloc'd is pageTable. We requested pageSize */ /* alignment, and pageTableSize is itself pageSize aligned, so */ /* BootAllocated should also be pageSize aligned. */ AVER(AddrIsAligned(BootAllocated(boot), chunk->pageSize)); chunk->allocBase = (Index)(BootAllocated(boot) >> pageShift); /* Init allocTable after class init, because it might be mapped there. */ BTResRange(chunk->allocTable, 0, pages); /* Check that there is some usable address space remaining in the chunk. */ allocBase = PageIndexBase(chunk, chunk->allocBase); AVER(allocBase < chunk->limit); /* Add the chunk's free address space to the arena's freeLand, so that we can allocate from it. */ if (arena->hasFreeLand) { res = ArenaFreeLandInsert(arena, allocBase, chunk->limit); if (res != ResOK) goto failLandInsert; } TreeInit(&chunk->chunkTree); chunk->sig = ChunkSig; AVERT(Chunk, chunk); ArenaChunkInsert(arena, chunk); return ResOK; failLandInsert: Method(Arena, arena, chunkFinish)(chunk); /* .no-clean: No clean-ups needed past this point for boot, as we will discard the chunk. */ failClassInit: failAllocTable: return res; }
static Res MVTInit(Pool pool, Arena arena, PoolClass klass, ArgList args) { Size align = MVT_ALIGN_DEFAULT; Size minSize = MVT_MIN_SIZE_DEFAULT; Size meanSize = MVT_MEAN_SIZE_DEFAULT; Size maxSize = MVT_MAX_SIZE_DEFAULT; Count reserveDepth = MVT_RESERVE_DEPTH_DEFAULT; Count fragLimit = MVT_FRAG_LIMIT_DEFAULT; Size reuseSize, fillSize; Count abqDepth; MVT mvt; Res res; ArgStruct arg; AVER(pool != NULL); AVERT(Arena, arena); AVERT(ArgList, args); UNUSED(klass); /* used for debug pools only */ if (ArgPick(&arg, args, MPS_KEY_ALIGN)) align = arg.val.align; if (ArgPick(&arg, args, MPS_KEY_MIN_SIZE)) minSize = arg.val.size; if (ArgPick(&arg, args, MPS_KEY_MEAN_SIZE)) meanSize = arg.val.size; if (ArgPick(&arg, args, MPS_KEY_MAX_SIZE)) maxSize = arg.val.size; if (ArgPick(&arg, args, MPS_KEY_MVT_RESERVE_DEPTH)) reserveDepth = arg.val.count; if (ArgPick(&arg, args, MPS_KEY_MVT_FRAG_LIMIT)) { /* pending complete fix for job003319 */ AVER(0 <= arg.val.d); AVER(arg.val.d <= 1); fragLimit = (Count)(arg.val.d * 100); } AVERT(Align, align); /* This restriction on the alignment is necessary because of the use of a Freelist to store the free address ranges in low-memory situations. <design/freelist#.impl.grain.align>. */ AVER(AlignIsAligned(align, FreelistMinimumAlignment)); AVER(align <= ArenaGrainSize(arena)); AVER(0 < minSize); AVER(minSize <= meanSize); AVER(meanSize <= maxSize); AVER(reserveDepth > 0); AVER(fragLimit <= 100); /* TODO: More parameter checks possible? */ /* see <design/poolmvt#.arch.parameters> */ fillSize = SizeArenaGrains(maxSize, arena); /* see <design/poolmvt#.arch.fragmentation.internal> */ reuseSize = 2 * fillSize; abqDepth = (reserveDepth * meanSize + reuseSize - 1) / reuseSize; /* keep the abq from being useless */ if (abqDepth < 3) abqDepth = 3; res = NextMethod(Pool, MVTPool, init)(pool, arena, klass, args); if (res != ResOK) goto failNextInit; mvt = CouldBeA(MVTPool, pool); res = LandInit(MVTFreePrimary(mvt), CLASS(CBSFast), arena, align, mvt, mps_args_none); if (res != ResOK) goto failFreePrimaryInit; res = LandInit(MVTFreeSecondary(mvt), CLASS(Freelist), arena, align, mvt, mps_args_none); if (res != ResOK) goto failFreeSecondaryInit; MPS_ARGS_BEGIN(foArgs) { MPS_ARGS_ADD(foArgs, FailoverPrimary, MVTFreePrimary(mvt)); MPS_ARGS_ADD(foArgs, FailoverSecondary, MVTFreeSecondary(mvt)); res = LandInit(MVTFreeLand(mvt), CLASS(Failover), arena, align, mvt, foArgs); } MPS_ARGS_END(foArgs); if (res != ResOK) goto failFreeLandInit; res = ABQInit(arena, MVTABQ(mvt), (void *)mvt, abqDepth, sizeof(RangeStruct)); if (res != ResOK) goto failABQInit; pool->alignment = align; pool->alignShift = SizeLog2(pool->alignment); mvt->reuseSize = reuseSize; mvt->fillSize = fillSize; mvt->abqOverflow = FALSE; mvt->minSize = minSize; mvt->meanSize = meanSize; mvt->maxSize = maxSize; mvt->fragLimit = fragLimit; mvt->splinter = FALSE; mvt->splinterBase = (Addr)0; mvt->splinterLimit = (Addr)0; /* accounting */ mvt->size = 0; mvt->allocated = 0; mvt->available = 0; mvt->availLimit = 0; mvt->unavailable = 0; /* meters*/ METER_INIT(mvt->segAllocs, "segment allocations", (void *)mvt); METER_INIT(mvt->segFrees, "segment frees", (void *)mvt); METER_INIT(mvt->bufferFills, "buffer fills", (void *)mvt); METER_INIT(mvt->bufferEmpties, "buffer empties", (void *)mvt); METER_INIT(mvt->poolFrees, "pool frees", (void *)mvt); METER_INIT(mvt->poolSize, "pool size", (void *)mvt); METER_INIT(mvt->poolAllocated, "pool allocated", (void *)mvt); METER_INIT(mvt->poolAvailable, "pool available", (void *)mvt); METER_INIT(mvt->poolUnavailable, "pool unavailable", (void *)mvt); METER_INIT(mvt->poolUtilization, "pool utilization", (void *)mvt); METER_INIT(mvt->finds, "ABQ finds", (void *)mvt); METER_INIT(mvt->overflows, "ABQ overflows", (void *)mvt); METER_INIT(mvt->underflows, "ABQ underflows", (void *)mvt); METER_INIT(mvt->refills, "ABQ refills", (void *)mvt); METER_INIT(mvt->refillPushes, "ABQ refill pushes", (void *)mvt); METER_INIT(mvt->returns, "ABQ returns", (void *)mvt); METER_INIT(mvt->perfectFits, "perfect fits", (void *)mvt); METER_INIT(mvt->firstFits, "first fits", (void *)mvt); METER_INIT(mvt->secondFits, "second fits", (void *)mvt); METER_INIT(mvt->failures, "failures", (void *)mvt); METER_INIT(mvt->emergencyContingencies, "emergency contingencies", (void *)mvt); METER_INIT(mvt->fragLimitContingencies, "fragmentation limit contingencies", (void *)mvt); METER_INIT(mvt->contingencySearches, "contingency searches", (void *)mvt); METER_INIT(mvt->contingencyHardSearches, "contingency hard searches", (void *)mvt); METER_INIT(mvt->splinters, "splinters", (void *)mvt); METER_INIT(mvt->splintersUsed, "splinters used", (void *)mvt); METER_INIT(mvt->splintersDropped, "splinters dropped", (void *)mvt); METER_INIT(mvt->sawdust, "sawdust", (void *)mvt); METER_INIT(mvt->exceptions, "exceptions", (void *)mvt); METER_INIT(mvt->exceptionSplinters, "exception splinters", (void *)mvt); METER_INIT(mvt->exceptionReturns, "exception returns", (void *)mvt); SetClassOfPoly(pool, CLASS(MVTPool)); mvt->sig = MVTSig; AVERC(MVT, mvt); EVENT6(PoolInitMVT, pool, minSize, meanSize, maxSize, reserveDepth, fragLimit); return ResOK; failABQInit: LandFinish(MVTFreeLand(mvt)); failFreeLandInit: LandFinish(MVTFreeSecondary(mvt)); failFreeSecondaryInit: LandFinish(MVTFreePrimary(mvt)); failFreePrimaryInit: NextMethod(Inst, MVTPool, finish)(MustBeA(Inst, pool)); failNextInit: AVER(res != ResOK); return res; }