Example #1
0
/* AMSAllocateRange -- set a range to be allocated
 *
 * Used as a means of overriding the behaviour of AMSBufferFill.
 * The code is similar to AMSUnallocateRange.
 */
static void AMSAllocateRange(AMS ams, Seg seg, Addr base, Addr limit)
{
  AMSSeg amsseg;
  Index baseIndex, limitIndex;
  Count allocatedGrains;
  /* 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 not allocated */
    AVER(BTIsResRange(amsseg->allocTable, baseIndex, limitIndex));
    BTSetRange(amsseg->allocTable, baseIndex, limitIndex);
  } else {
    /* check that it's not allocated */
    AVER(baseIndex >= amsseg->firstFree);
    if (baseIndex == amsseg->firstFree) /* is it at the end? */ {
      amsseg->firstFree = limitIndex;
    } 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);
      BTSetRange(amsseg->allocTable, baseIndex, limitIndex);
    }
  }

  allocatedGrains = limitIndex - baseIndex;
  AVER(amsseg->freeGrains >= allocatedGrains);
  amsseg->freeGrains -= allocatedGrains;
  amsseg->bufferedGrains += allocatedGrains;
  PoolGenAccountForFill(ams->pgen, AddrOffset(base, limit));
}
Example #2
0
static void test(FBMState state, unsigned n) {
  Addr base, limit;
  unsigned i;
  Size size;
  Bool high;
  FindDelete findDelete = FindDeleteNONE;

  BTSetRange(state->allocTable, 0, ArraySize); /* Initially all allocated */
  check(state);
  for(i = 0; i < n; i++) {
    switch(fbmRnd(3)) {
    case 0:
      randomRange(&base, &limit, state);
      allocate(state, base, limit);
      break;
    case 1:
      randomRange(&base, &limit, state);
      deallocate(state, base, limit);
      break;
    case 2:
      size = fbmRnd(ArraySize / 10) + 1;
      high = fbmRnd(2) ? TRUE : FALSE;
      switch(fbmRnd(6)) {
      case 0:
      case 1:
      case 2: findDelete = FindDeleteNONE; break;
      case 3: findDelete = FindDeleteLOW; break;
      case 4: findDelete = FindDeleteHIGH; break;
      case 5: findDelete = FindDeleteENTIRE; break;
      }
      find(state, size, high, findDelete);
      break;
    default:
      fail();
      return;
    }
    if ((i + 1) % 1000 == 0)
      check(state);
  }
}
Example #3
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);
}
Example #4
0
static void setRange(void)
{
  if (checkDefaultRange(0))
    BTSetRange(bt, args[0], args[1]);
}
Example #5
0
static void find(FBMState state, Size size, Bool high, FindDelete findDelete)
{
  Bool expected, found;
  Index expectedBase, expectedLimit;
  RangeStruct foundRange, oldRange;
  Addr remainderBase, remainderLimit;
  Addr origBase, origLimit;
  Size oldSize, newSize;

  origBase = origLimit = NULL;
  expected = (high ? BTFindLongResRangeHigh : BTFindLongResRange)
               (&expectedBase, &expectedLimit, state->allocTable,
                (Index)0, (Index)ArraySize, (Count)size);

  if (expected) {
    oldSize = (expectedLimit - expectedBase) * state->align;
    remainderBase = origBase = addrOfIndex(state, expectedBase);
    remainderLimit = origLimit = addrOfIndex(state, expectedLimit);

    switch(findDelete) {
    case FindDeleteNONE: {
      /* do nothing */
    } break;
    case FindDeleteENTIRE: {
      remainderBase = remainderLimit;
    } break;
    case FindDeleteLOW: {
      expectedLimit = expectedBase + size;
      remainderBase = addrOfIndex(state, expectedLimit);
    } break;
    case FindDeleteHIGH: {
      expectedBase = expectedLimit - size;
      remainderLimit = addrOfIndex(state, expectedBase);
    } break;
    }

    if (findDelete != FindDeleteNONE) {
      newSize = AddrOffset(remainderBase, remainderLimit);
    }

    /* TODO: check these values */
    UNUSED(oldSize);
    UNUSED(newSize);
  }

  switch (state->type) {
  case FBMTypeCBS:
    found = (high ? CBSFindLast : CBSFindFirst)
      (&foundRange, &oldRange, state->the.cbs, size * state->align, findDelete);
    break;
  case FBMTypeFreelist:
    found = (high ? FreelistFindLast : FreelistFindFirst)
      (&foundRange, &oldRange, state->the.fl, size * state->align, findDelete);
    break;
  default:
    fail();
    return;
  }

  if (verbose) {
    printf("find %s %lu: ", high ? "last" : "first",
           (unsigned long)(size * state->align));
    if (expected) {
      printf("expecting [%p,%p)\n",
             (void *)addrOfIndex(state, expectedBase),
             (void *)addrOfIndex(state, expectedLimit));
    } else {
      printf("expecting this not to be found\n");
    }
    if (found) {
      printf("  found [%p,%p)\n", (void *)RangeBase(&foundRange),
             (void *)RangeLimit(&foundRange));
    } else {
      printf("  not found\n");
    }
  }

  Insist(found == expected);

  if (found) {
    Insist(expectedBase == indexOfAddr(state, RangeBase(&foundRange)));
    Insist(expectedLimit == indexOfAddr(state, RangeLimit(&foundRange)));

    if (findDelete != FindDeleteNONE) {
      Insist(RangeBase(&oldRange) == origBase);
      Insist(RangeLimit(&oldRange) == origLimit);
      BTSetRange(state->allocTable, expectedBase, expectedLimit);
    }
  }

  return;
}
Example #6
0
static void allocate(FBMState state, Addr base, Addr limit)
{
  Res res;
  Index ib, il;                  /* Indexed for base and limit */
  Bool isFree;
  RangeStruct range, oldRange;
  Addr outerBase, outerLimit;    /* interval containing [ib, il) */

  ib = indexOfAddr(state, base);
  il = indexOfAddr(state, limit);

  isFree = BTIsResRange(state->allocTable, ib, il);

  NAllocateTried++;

  if (isFree) {
    Size left, right, total;       /* Sizes of block and two fragments */

    outerBase =
      addrOfIndex(state, lastEdge(state->allocTable, ArraySize, ib));
    outerLimit =
      addrOfIndex(state, nextEdge(state->allocTable, ArraySize, il - 1));

    left = AddrOffset(outerBase, base);
    right = AddrOffset(limit, outerLimit);
    total = AddrOffset(outerBase, outerLimit);

    /* TODO: check these values */
    UNUSED(left);
    UNUSED(right);
    UNUSED(total);
  } else {
    outerBase = outerLimit = NULL;
  }

  RangeInit(&range, base, limit);
  switch (state->type) {
  case FBMTypeCBS:
    res = CBSDelete(&oldRange, state->the.cbs, &range);
    break;
  case FBMTypeFreelist:
    res = FreelistDelete(&oldRange, state->the.fl, &range);
    break;
  default:
    fail();
    return;
  }

  if (verbose) {
    printf("allocate: [%p,%p) -- %s\n",
           (void *)base, (void *)limit, isFree ? "succeed" : "fail");
    describe(state);
  }

  if (!isFree) {
    die_expect((mps_res_t)res, MPS_RES_FAIL,
               "Succeeded in deleting allocated block");
  } else { /* isFree */
    die_expect((mps_res_t)res, MPS_RES_OK,
               "failed to delete free block");
    Insist(RangeBase(&oldRange) == outerBase);
    Insist(RangeLimit(&oldRange) == outerLimit);
    NAllocateSucceeded++;
    BTSetRange(state->allocTable, ib, il);
  }
}
Example #7
0
extern int main(int argc, char *argv[])
{
  unsigned i;
  Addr base, limit;
  mps_arena_t mpsArena;
  Arena arena; /* the ANSI arena which we use to allocate the BT */
  CBSStruct cbsStruct;
  CBS cbs;
  void *p;
  Addr dummyBlock;
  BT allocTable;
  Size size;
  Bool high;
  CBSFindDelete findDelete = CBSFindDeleteNONE;

  randomize(argc, argv);

  NAllocateTried = NAllocateSucceeded = NDeallocateTried =
    NDeallocateSucceeded = NNewBlocks = NDeleteBlocks =
    NGrowBlocks = NShrinkBlocks = 0;

  clearExpectations();

  die(mps_arena_create(&mpsArena, mps_arena_class_vm(), testArenaSIZE),
      "mps_arena_create");
  arena = (Arena)mpsArena; /* avoid pun */

  die((mps_res_t)BTCreate(&allocTable, arena, ArraySize),
      "failed to create alloc table");

  die((mps_res_t)CBSInit(arena, &cbsStruct, NULL, &cbsNewCallback,
                         &cbsDeleteCallback, &cbsGrowCallback,
                         &cbsShrinkCallback, MinSize,
                         Alignment, TRUE, TRUE),
      "failed to initialise CBS");
  cbs = &cbsStruct;

  BTSetRange(allocTable, 0, ArraySize); /* Initially all allocated */

  /* We're not going to use this block, but I feel unhappy just */
  /* inventing addresses. */
  die((mps_res_t)ControlAlloc(&p, arena, ArraySize * Alignment,
                              /* withReservoirPermit */ FALSE),
      "failed to allocate block");
  dummyBlock = (Addr)p; /* avoid pun */

  printf("Allocated block [%p, %p)\n", (void*)dummyBlock,
         (char *)dummyBlock + ArraySize);

  checkCBS(cbs, allocTable, dummyBlock);
  for(i = 0; i < NOperations; i++) {
    switch(cbsRnd(3)) {
    case 0: {
      randomRange(&base, &limit, allocTable, dummyBlock);
      allocate(cbs, dummyBlock, allocTable, base, limit);
    } break;
    case 1: {
      randomRange(&base, &limit, allocTable, dummyBlock);
      deallocate(cbs, dummyBlock, allocTable, base, limit);
    } break;
    case 2: {
      size = cbsRnd(ArraySize / 10) + 1;
      high = cbsRnd(2) ? TRUE : FALSE;
      switch(cbsRnd(6)) {
      case 0:
      case 1:
      case 2: findDelete = CBSFindDeleteNONE; break;
      case 3: findDelete = CBSFindDeleteLOW; break;
      case 4: findDelete = CBSFindDeleteHIGH; break;
      case 5: findDelete = CBSFindDeleteENTIRE; break;
      }
      find(cbs, dummyBlock, allocTable, size, high, findDelete);
    } break;
    }
    if (i % 5000 == 0)
      checkCBS(cbs, allocTable, dummyBlock);
  }

  checkExpectations();

  /* CBSDescribe prints a very long line. */
  /* CBSDescribe(cbs, mps_lib_get_stdout()); */

  printf("\nNumber of allocations attempted: %ld\n", NAllocateTried);
  printf("Number of allocations succeeded: %ld\n", NAllocateSucceeded);
  printf("Number of deallocations attempted: %ld\n", NDeallocateTried);
  printf("Number of deallocations succeeded: %ld\n", NDeallocateSucceeded);
  printf("Number of new large blocks: %ld\n", NNewBlocks);
  printf("Number of deleted large blocks: %ld\n", NDeleteBlocks);
  printf("Number of grown large blocks: %ld\n", NGrowBlocks);
  printf("Number of shrunk large blocks: %ld\n", NShrinkBlocks);
  printf("\nNo problems detected.\n");
  return 0;
}
Example #8
0
static void find(CBS cbs, void *block, BT alloc, Size size, Bool high,
                 CBSFindDelete findDelete)
{
  Bool expected, found;
  Index expectedBase, expectedLimit;
  Addr foundBase, foundLimit, remainderBase, remainderLimit;
  Size oldSize, newSize;

  checkExpectations();

  expected = (high ? BTFindLongResRangeHigh : BTFindLongResRange)
               (&expectedBase, &expectedLimit, alloc,
                (Index)0, (Index)ArraySize, (Count)size);

  if (expected) {
    oldSize = (expectedLimit - expectedBase) * Alignment;
    remainderBase = addrOfIndex(block, expectedBase);
    remainderLimit = addrOfIndex(block, expectedLimit);

    switch(findDelete) {
    case CBSFindDeleteNONE: {
      /* do nothing */
    } break;
    case CBSFindDeleteENTIRE: {
      remainderBase = remainderLimit;
    } break;
    case CBSFindDeleteLOW: {
      expectedLimit = expectedBase + size;
      remainderBase = addrOfIndex(block, expectedLimit);
    } break;
    case CBSFindDeleteHIGH: {
      expectedBase = expectedLimit - size;
      remainderLimit = addrOfIndex(block, expectedBase);
    } break;
    }

    if (findDelete != CBSFindDeleteNONE) {
      newSize = AddrOffset(remainderBase, remainderLimit);

      if (oldSize >= MinSize) {
        if (newSize == 0)
          expectCallback(&CallbackDelete, oldSize, (Addr)0, (Addr)0);
        else if (newSize < MinSize)
          expectCallback(&CallbackDelete, oldSize,
                         remainderBase, remainderLimit);
        else
          expectCallback(&CallbackShrink, oldSize,
                         remainderBase, remainderLimit);
      }
    }
  }

  found = (high ? CBSFindLast : CBSFindFirst)
    (&foundBase, &foundLimit, cbs, size * Alignment, findDelete);

  Insist(found == expected);

  if (found) {
    Insist(expectedBase == indexOfAddr(block, foundBase));
    Insist(expectedLimit == indexOfAddr(block, foundLimit));
    checkExpectations();

    if (findDelete != CBSFindDeleteNONE)
      BTSetRange(alloc, expectedBase, expectedLimit);
  }

  return;
}
Example #9
0
static void allocate(CBS cbs, Addr block, BT allocTable,
                     Addr base, Addr limit)
{
  Res res;
  Index ib, il;                  /* Indexed for base and limit */
  Bool isFree;

  ib = indexOfAddr(block, base);
  il = indexOfAddr(block, limit);

  isFree = BTIsResRange(allocTable, ib, il);
 
  /*
  printf("allocate: [%p, %p) -- %s\n",
         base, limit, isFree ? "succeed" : "fail");
  */

  NAllocateTried++;

  if (isFree) {
    Addr outerBase, outerLimit;    /* interval containing [ib, il) */
    Size left, right, total;       /* Sizes of block and two fragments */

    outerBase =
      addrOfIndex(block, lastEdge(allocTable, ArraySize, ib));
    outerLimit =
      addrOfIndex(block, nextEdge(allocTable, ArraySize, il - 1));

    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 == (Size)0 && right == (Size)0) {
        expectCallback(&CallbackDelete, total, (Addr)0, (Addr)0);
      } else if (left >= right) {
        expectCallback(&CallbackDelete, total, outerBase, base);
      } else {
        expectCallback(&CallbackDelete, total, limit, outerLimit);
      }
    } else if (left >= MinSize && right >= MinSize) {
      if (left >= right) {
        expectCallback(&CallbackShrink, total, outerBase, base);
        expectCallback(&CallbackNew, (Size)0, limit, outerLimit);
      } else {
        expectCallback(&CallbackNew, (Size)0, outerBase, base);
        expectCallback(&CallbackShrink, total, limit, outerLimit);
      }
    } else if (total >= MinSize) {
      if (left >= right) {
        Insist(left >= MinSize);
        Insist(right < MinSize);
        expectCallback(&CallbackShrink, total, outerBase, base);
      } else {
        Insist(left < MinSize);
        Insist(right >= MinSize);
        expectCallback(&CallbackShrink, total, limit, outerLimit);
      }
    }
  }

  res = CBSDelete(cbs, base, limit);

  if (!isFree) {
    die_expect((mps_res_t)res, MPS_RES_FAIL,
               "Succeeded in deleting allocated block");
  } else { /* isFree */
    die_expect((mps_res_t)res, MPS_RES_OK,
               "failed to delete free block");
    NAllocateSucceeded++;
    BTSetRange(allocTable, ib, il);
    checkExpectations();
  }
}