Res PoolCreate(Pool *poolReturn, Arena arena, PoolClass klass, ArgList args) { Res res; Pool pool; void *base; AVER(poolReturn != NULL); AVERT(Arena, arena); AVERT(PoolClass, klass); /* .space.alloc: Allocate the pool instance structure with the size */ /* requested in the pool class. See .space.free */ res = ControlAlloc(&base, arena, klass->size); if (res != ResOK) goto failControlAlloc; pool = (Pool)base; /* Initialize the pool. */ res = PoolInit(pool, arena, klass, args); if (res != ResOK) goto failPoolInit; *poolReturn = pool; return ResOK; failPoolInit: ControlFree(arena, base, klass->size); failControlAlloc: return res; }
Res BufferCreate(Buffer *bufferReturn, BufferClass klass, Pool pool, Bool isMutator, ArgList args) { Res res; Buffer buffer; Arena arena; void *p; AVER(bufferReturn != NULL); AVERT(BufferClass, klass); AVERT(Pool, pool); arena = PoolArena(pool); /* Allocate memory for the buffer descriptor structure. */ res = ControlAlloc(&p, arena, klass->size); if (res != ResOK) goto failAlloc; buffer = p; /* Initialize the buffer descriptor structure. */ res = BufferInit(buffer, klass, pool, isMutator, args); if (res != ResOK) goto failInit; *bufferReturn = buffer; return ResOK; failInit: ControlFree(arena, buffer, klass->size); failAlloc: return res; }
void SACDestroy(SAC sac) { AVERT(SAC, sac); SACFlush(sac); sac->sig = SigInvalid; ControlFree(PoolArena(sac->pool), sac, sacSize(sac->middleIndex, sac->classesCount)); }
void BTDestroy(BT bt, Arena arena, Count length) { AVER(bt != NULL); AVERT(Arena, arena); AVER(length > 0); ControlFree(arena, bt, BTSize(length)); }
void BufferDestroy(Buffer buffer) { Arena arena; Size size; AVERT(Buffer, buffer); arena = buffer->arena; size = ClassOfPoly(Buffer, buffer)->size; BufferFinish(buffer); ControlFree(arena, buffer, size); }
void ShieldDestroyQueue(Shield shield, Arena arena) { AVER(shield->limit == 0); /* queue must be empty */ if (shield->length != 0) { AVER(shield->queue != NULL); ControlFree(arena, shield->queue, shield->length * sizeof shield->queue[0]); shield->queue = NULL; shield->length = 0; } }
void PoolDestroy(Pool pool) { Arena arena; Size size; AVERT(Pool, pool); arena = pool->arena; size = ClassOfPoly(Pool, pool)->size; PoolFinish(pool); /* .space.free: Free the pool instance structure. See .space.alloc */ ControlFree(arena, pool, size); }
void ThreadDeregister(Thread thread, Arena arena) { AVERT(Thread, thread); AVERT(Arena, arena); RingRemove(&thread->arenaRing); thread->sig = SigInvalid; RingFinish(&thread->arenaRing); ControlFree(arena, thread, sizeof(ThreadStruct)); }
static void TraceStartMessageDelete(Message message) { TraceStartMessage tsMessage; Arena arena; AVERT(Message, message); tsMessage = MessageTraceStartMessage(message); AVERT(TraceStartMessage, tsMessage); arena = MessageArena(message); tsMessage->sig = SigInvalid; MessageFinish(message); ControlFree(arena, (void *)tsMessage, sizeof(TraceStartMessageStruct)); }
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; }
void ThreadDeregister(Thread thread, Arena arena) { Bool b; AVERT(Thread, thread); AVERT(Arena, arena); RingRemove(&thread->arenaRing); thread->sig = SigInvalid; RingFinish(&thread->arenaRing); b = CloseHandle(thread->handle); AVER(b); /* .error.close-handle */ ControlFree(arena, thread, sizeof(ThreadStruct)); }
Res TraceIdMessagesCreate(Arena arena, TraceId ti) { void *p; TraceStartMessage tsMessage; TraceMessage tMessage; Res res; /* Ensure we don't leak memory */ AVER(!arena->tsMessage[ti]); AVER(!arena->tMessage[ti]); res = ControlAlloc(&p, arena, sizeof(TraceStartMessageStruct)); if(res != ResOK) goto failTraceStartMessage; tsMessage = p; res = ControlAlloc(&p, arena, sizeof(TraceMessageStruct)); if(res != ResOK) goto failTraceMessage; tMessage = p; traceStartMessageInit(arena, tsMessage); AVERT(TraceStartMessage, tsMessage); traceMessageInit(arena, tMessage); AVERT(TraceMessage, tMessage); arena->tsMessage[ti] = tsMessage; arena->tMessage[ti] = tMessage; AVER(TraceIdMessagesCheck(arena, ti)); return ResOK; failTraceMessage: ControlFree(arena, tsMessage, sizeof(TraceStartMessageStruct)); failTraceStartMessage: AVER(TraceIdMessagesCheck(arena, ti)); return res; }
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 shieldQueue(Arena arena, Seg seg) { Shield shield; /* <design/trace/#fix.noaver> */ AVERT_CRITICAL(Arena, arena); shield = ArenaShield(arena); SHIELD_AVERT_CRITICAL(Seg, seg); if (SegIsSynced(seg) || seg->queued) return; if (SegIsExposed(seg)) { /* This can occur if the mutator isn't suspended, we expose a segment, then raise the shield on it. In this case, the mutator isn't allowed to see the segment, but we don't need to queue it until its covered. */ shieldSuspend(arena); return; } /* Allocate or extend the shield queue if necessary. */ if (shield->next >= shield->length) { void *p; Res res; Count length; AVER(shield->next == shield->length); if (shield->length == 0) length = ShieldQueueLENGTH; else length = shield->length * 2; res = ControlAlloc(&p, arena, length * sizeof shield->queue[0]); if (res != ResOK) { AVER(ResIsAllocFailure(res)); /* Carry on with the existing queue. */ } else { if (shield->length > 0) { Size oldSize = shield->length * sizeof shield->queue[0]; AVER(shield->queue != NULL); mps_lib_memcpy(p, shield->queue, oldSize); ControlFree(arena, shield->queue, oldSize); } shield->queue = p; shield->length = length; } } /* Queue unavailable, so synchronize now. Or if the mutator is not yet suspended and the code raises the shield on a covered segment, protect it now, because that's probably better than suspending the mutator. */ if (shield->length == 0 || !shield->suspended) { shieldSync(shield, seg); return; } AVER_CRITICAL(shield->limit <= shield->length); AVER_CRITICAL(shield->next <= shield->limit); /* If we failed to extend the shield queue array, degrade to an LRU circular buffer. */ if (shield->next >= shield->length) shield->next = 0; AVER_CRITICAL(shield->next < shield->length); AVER_CRITICAL(shield->length > 0); /* If the limit is less than the length, then the queue array has yet to be filled, and next is an uninitialized entry. Otherwise it's the tail end from last time around, and needs to be flushed. */ if (shield->limit >= shield->length) { AVER_CRITICAL(shield->limit == shield->length); shieldFlushEntry(shield, shield->next); } shield->queue[shield->next] = seg; ++shield->next; seg->queued = TRUE; if (shield->next >= shield->limit) shield->limit = shield->next; }
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 void dfMessageDelete(Message message) { Arena arena; arena = MessageArena(message); ControlFree(arena, (void *)message, sizeof(MessageStruct)); }
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; }