static void check(FBMState state) { CheckFBMClosureStruct closure; closure.state = state; closure.limit = addrOfIndex(state, ArraySize); closure.oldLimit = state->block; switch (state->type) { case FBMTypeCBS: CBSIterate(state->the.cbs, checkCBSCallback, (void *)&closure, 0); break; case FBMTypeFreelist: FreelistIterate(state->the.fl, checkFLCallback, (void *)&closure, 0); break; default: fail(); return; } if (closure.oldLimit == state->block) Insist(BTIsSetRange(state->allocTable, 0, indexOfAddr(state, closure.limit))); else if (closure.limit > closure.oldLimit) Insist(BTIsSetRange(state->allocTable, indexOfAddr(state, closure.oldLimit), indexOfAddr(state, closure.limit))); else Insist(closure.oldLimit == closure.limit); }
static void isSetRange(void) { if (checkDefaultRange(0)) { Bool b = BTIsSetRange(bt, args[0], args[1]); puts(b ? "TRUE" : "FALSE"); } }
static Bool checkCallback(Range range, void *closureP, Size closureS) { Addr base, limit; CheckFBMClosure cl = (CheckFBMClosure)closureP; UNUSED(closureS); Insist(cl != NULL); base = RangeBase(range); limit = RangeLimit(range); if (base > cl->oldLimit) { Insist(BTIsSetRange(cl->state->allocTable, indexOfAddr(cl->state, cl->oldLimit), indexOfAddr(cl->state, base))); } else { /* must be at start of table */ Insist(base == cl->oldLimit); Insist(cl->oldLimit == cl->state->block); } Insist(BTIsResRange(cl->state->allocTable, indexOfAddr(cl->state, base), indexOfAddr(cl->state, limit))); cl->oldLimit = limit; return TRUE; }
static Bool checkCBSAction(CBS cbs, CBSBlock cbsBlock, void *p) { Addr base, limit; CheckCBSClosure closure = (CheckCBSClosure)p; /* Don't need to check cbs every time */ UNUSED(cbs); Insist(closure != NULL); base = CBSBlockBase(cbsBlock); limit = CBSBlockLimit(cbsBlock); if (base > closure->oldLimit) { Insist(BTIsSetRange(closure->allocTable, indexOfAddr(closure->base, closure->oldLimit), indexOfAddr(closure->base, base))); } else { /* must be at start of table */ Insist(base == closure->oldLimit); Insist(closure->oldLimit == closure->base); } Insist(BTIsResRange(closure->allocTable, indexOfAddr(closure->base, base), indexOfAddr(closure->base, limit))); closure->oldLimit = limit; return TRUE; }
static void checkCBS(CBS cbs, BT allocTable, Addr dummyBlock) { CheckCBSClosureStruct closure; closure.allocTable = allocTable; closure.base = dummyBlock; closure.limit = addrOfIndex(closure.base, ArraySize); closure.oldLimit = closure.base; CBSIterate(cbs, checkCBSAction, (void *)&closure); if (closure.oldLimit == closure.base) Insist(BTIsSetRange(allocTable, 0, indexOfAddr(dummyBlock, closure.limit))); else if (closure.limit > closure.oldLimit) Insist(BTIsSetRange(allocTable, indexOfAddr(dummyBlock, closure.oldLimit), indexOfAddr(dummyBlock, closure.limit))); else Insist(closure.oldLimit == closure.limit); }
/* AMSUnallocateRange -- set a range to be unallocated * * Used as a means of overriding the behaviour of AMSBufferFill. * The code is similar to amsSegBufferEmpty. */ static void AMSUnallocateRange(AMS ams, Seg seg, Addr base, Addr limit) { AMSSeg amsseg; Index baseIndex, limitIndex; Count unallocatedGrains; /* parameters checked by caller */ amsseg = Seg2AMSSeg(seg); baseIndex = PoolIndexOfAddr(SegBase(seg), SegPool(seg), base); limitIndex = PoolIndexOfAddr(SegBase(seg), SegPool(seg), limit); if (amsseg->allocTableInUse) { /* check that it's allocated */ AVER(BTIsSetRange(amsseg->allocTable, baseIndex, limitIndex)); BTResRange(amsseg->allocTable, baseIndex, limitIndex); } else { /* check that it's allocated */ AVER(limitIndex <= amsseg->firstFree); if (limitIndex == amsseg->firstFree) /* is it at the end? */ { amsseg->firstFree = baseIndex; } else { /* start using allocTable */ amsseg->allocTableInUse = TRUE; BTSetRange(amsseg->allocTable, 0, amsseg->firstFree); if (amsseg->firstFree < amsseg->grains) BTResRange(amsseg->allocTable, amsseg->firstFree, amsseg->grains); BTResRange(amsseg->allocTable, baseIndex, limitIndex); } } unallocatedGrains = limitIndex - baseIndex; AVER(amsseg->bufferedGrains >= unallocatedGrains); amsseg->freeGrains += unallocatedGrains; amsseg->bufferedGrains -= unallocatedGrains; PoolGenAccountForEmpty(ams->pgen, 0, PoolGrainsSize(AMSPool(ams), unallocatedGrains), FALSE); }
static void deallocate(FBMState state, Addr base, Addr limit) { Res res; Index ib, il; Bool isAllocated; Addr outerBase = base, outerLimit = limit; /* interval containing [ib, il) */ RangeStruct range, freeRange; /* interval returned by the manager */ ib = indexOfAddr(state, base); il = indexOfAddr(state, limit); isAllocated = BTIsSetRange(state->allocTable, ib, il); NDeallocateTried++; if (isAllocated) { Size left, right, total; /* Sizes of block and two fragments */ /* Find the free blocks adjacent to the allocated block */ if (ib > 0 && !BTGet(state->allocTable, ib - 1)) { outerBase = addrOfIndex(state, lastEdge(state->allocTable, ArraySize, ib - 1)); } else { outerBase = base; } if (il < ArraySize && !BTGet(state->allocTable, il)) { outerLimit = addrOfIndex(state, nextEdge(state->allocTable, ArraySize, il)); } else { outerLimit = limit; } left = AddrOffset(outerBase, base); right = AddrOffset(limit, outerLimit); total = AddrOffset(outerBase, outerLimit); /* TODO: check these values */ UNUSED(left); UNUSED(right); UNUSED(total); } RangeInit(&range, base, limit); switch (state->type) { case FBMTypeCBS: res = CBSInsert(&freeRange, state->the.cbs, &range); break; case FBMTypeFreelist: res = FreelistInsert(&freeRange, state->the.fl, &range); break; default: fail(); return; } if (verbose) { printf("deallocate: [%p,%p) -- %s\n", (void *)base, (void *)limit, isAllocated ? "succeed" : "fail"); describe(state); } if (!isAllocated) { die_expect((mps_res_t)res, MPS_RES_FAIL, "succeeded in inserting non-allocated block"); } else { /* isAllocated */ die_expect((mps_res_t)res, MPS_RES_OK, "failed to insert allocated block"); NDeallocateSucceeded++; BTResRange(state->allocTable, ib, il); Insist(RangeBase(&freeRange) == outerBase); Insist(RangeLimit(&freeRange) == outerLimit); } }
static void deallocate(CBS cbs, Addr block, BT allocTable, Addr base, Addr limit) { Res res; Index ib, il; Bool isAllocated; Addr outerBase = base, outerLimit = limit; /* interval containing [ib, il) */ Addr freeBase, freeLimit; /* interval returned by CBS */ ib = indexOfAddr(block, base); il = indexOfAddr(block, limit); isAllocated = BTIsSetRange(allocTable, ib, il); /* printf("deallocate: [%p, %p) -- %s\n", base, limit, isAllocated ? "succeed" : "fail"); */ NDeallocateTried++; if (isAllocated) { Size left, right, total; /* Sizes of block and two fragments */ /* Find the free blocks adjacent to the allocated block */ if (ib > 0 && !BTGet(allocTable, ib - 1)) { outerBase = addrOfIndex(block, lastEdge(allocTable, ArraySize, ib - 1)); } else { outerBase = base; } if (il < ArraySize && !BTGet(allocTable, il)) { outerLimit = addrOfIndex(block, nextEdge(allocTable, ArraySize, il)); } else { outerLimit = limit; } left = AddrOffset(outerBase, base); right = AddrOffset(limit, outerLimit); total = AddrOffset(outerBase, outerLimit); /* based on detailed knowledge of CBS behaviour */ checkExpectations(); if (total >= MinSize && left < MinSize && right < MinSize) { if (left >= right) expectCallback(&CallbackNew, left, outerBase, outerLimit); else expectCallback(&CallbackNew, right, outerBase, outerLimit); } else if (left >= MinSize && right >= MinSize) { if (left >= right) { expectCallback(&CallbackDelete, right, (Addr)0, (Addr)0); expectCallback(&CallbackGrow, left, outerBase, outerLimit); } else { expectCallback(&CallbackDelete, left, (Addr)0, (Addr)0); expectCallback(&CallbackGrow, right, outerBase, outerLimit); } } else if (total >= MinSize) { if (left >= right) { Insist(left >= MinSize); Insist(right < MinSize); expectCallback(&CallbackGrow, left, outerBase, outerLimit); } else { Insist(left < MinSize); Insist(right >= MinSize); expectCallback(&CallbackGrow, right, outerBase, outerLimit); } } } res = CBSInsertReturningRange(&freeBase, &freeLimit, cbs, base, limit); if (!isAllocated) { die_expect((mps_res_t)res, MPS_RES_FAIL, "succeeded in inserting non-allocated block"); } else { /* isAllocated */ die_expect((mps_res_t)res, MPS_RES_OK, "failed to insert allocated block"); NDeallocateSucceeded++; BTResRange(allocTable, ib, il); checkExpectations(); Insist(freeBase == outerBase); Insist(freeLimit == outerLimit); } }