Esempio n. 1
0
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);
}
Esempio n. 2
0
static void isSetRange(void)
{
  if (checkDefaultRange(0)) {
    Bool b = BTIsSetRange(bt, args[0], args[1]);
    puts(b ? "TRUE" : "FALSE");
  }
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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);
}
Esempio n. 6
0
/* 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);
}
Esempio n. 7
0
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);
  }
}
Esempio n. 8
0
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);
  }
}