Ejemplo n.º 1
0
static Index nextEdge(BT bt, Size size, Index base)
{
  Index end;
  Bool baseValue;

  Insist(bt != NULL);
  Insist(base < size);

  baseValue = BTGet(bt, base);

  for(end = base + 1; end < size && BTGet(bt, end) == baseValue; end++)
    NOOP;

  return end;
}
Ejemplo n.º 2
0
static Index lastEdge(BT bt, Size size, Index base)
{
  Index end;
  Bool baseValue;

  Insist(bt != NULL);
  Insist(base < size);

  baseValue = BTGet(bt, base);

  for(end = base; end > (Index)0 && BTGet(bt, end - 1) == baseValue; end--)
    NOOP;

  return end;
}
Ejemplo n.º 3
0
Bool TractOfAddr(Tract *tractReturn, Arena arena, Addr addr)
{
  Bool b;
  Index i;
  Chunk chunk;
 
  /* <design/trace/#fix.noaver> */
  AVER_CRITICAL(tractReturn != NULL); /* .tract.critical */
  AVERT_CRITICAL(Arena, arena);

  b = ChunkOfAddr(&chunk, arena, addr);
  if (!b)
    return FALSE;
  /* <design/trace/#fix.tractofaddr> */
  i = INDEX_OF_ADDR(chunk, addr);
  /* .addr.free: If the page is recorded as being free then */
  /* either the page is free or it is */
  /* part of the arena tables (see .ullagepages). */
  if (BTGet(chunk->allocTable, i)) {
    *tractReturn = PageTract(ChunkPage(chunk, i));
    return TRUE;
  }

  return FALSE;
}
Ejemplo n.º 4
0
static void showBT(void) {
  Index i;
  char c;
  if (bt == NULL)
    return;
  i = 0;
  while((i < btSize) && (i < 50)) {
    if (i % 10 == 0)
      c = (char)(((i / 10) % 10) + '0');
    else
      c = ' ';
    putchar(c);
    ++ i;
  }
  putchar('\n');
  i = 0;
  while((i < btSize) && (i < 50)) {
    c = (char)((i % 10) +'0');
    putchar(c);
    ++ i;
  }
  putchar('\n');
  i = 0;
  while(i < btSize) {
    if (BTGet(bt,i))
      c = 'O';
    else
      c = '.';
    putchar(c);
    ++ i;
    if (i % 50 == 0)
      putchar('\n');
  }
  putchar('\n');
}
Ejemplo n.º 5
0
Bool (BTGet)(BT t, Index i)
{
  AVERT(BT, t);
  /* Can't check i */

  /* see macro in <code/mpm.h> */
  return BTGet(t, i);
}
Ejemplo n.º 6
0
void PageFree(Chunk chunk, Index pi)
{
  AVERT(Chunk, chunk);
  AVER(pi >= chunk->allocBase);
  AVER(pi < chunk->pages);
  AVER(BTGet(chunk->allocTable, pi));

  PageInit(chunk, pi);
}
Ejemplo n.º 7
0
Count BTCountResRange(BT bt, Index base, Index limit)
{
  Count c = 0;
  Index bit;

  AVERT(BT, bt);
  AVER(base < limit);

  for (bit = base; bit < limit; ++bit)
    if (!BTGet(bt, bit)) ++c;
  return c;
}
Ejemplo n.º 8
0
void PageAlloc(Chunk chunk, Index pi, Pool pool)
{
  Tract tract;
  Addr base;
  Page page;

  AVERT_CRITICAL(Chunk, chunk);
  AVER_CRITICAL(pi >= chunk->allocBase);
  AVER_CRITICAL(pi < chunk->pages);
  AVER_CRITICAL(!BTGet(chunk->allocTable, pi));
  AVERT_CRITICAL(Pool, pool);

  page = ChunkPage(chunk, pi);
  tract = PageTract(page);
  base = PageIndexBase(chunk, pi);
  BTSet(chunk->allocTable, pi);
  TractInit(tract, pool, base);
}
Ejemplo n.º 9
0
void BTCopyOffsetRange(BT fromBT, BT toBT,
                       Index fromBase, Index fromLimit,
                       Index toBase, Index toLimit)
{
  Index fromBit, toBit;

  AVERT(BT, fromBT);
  AVERT(BT, toBT);
  AVER(fromBT != toBT);
  AVER(fromBase < fromLimit);
  AVER(toBase < toLimit);
  AVER((fromLimit - fromBase) == (toLimit - toBase));

  for (fromBit = fromBase, toBit = toBase;
       fromBit < fromLimit;
       ++fromBit, ++toBit) {
    if (BTGet(fromBT, fromBit))
      BTSet(toBT, toBit);
    else
      BTRes(toBT, toBit);
  }
}
Ejemplo n.º 10
0
static void test(mps_arena_t arena)
{
  BT bt;
  Nailboard board;
  Align align;
  Count nails;
  Addr base, limit;
  Index i, j, k;

  align = (Align)1 << (rnd() % 10);
  nails = (Count)1 << (rnd() % 16);
  nails += rnd() % nails;
  base = AddrAlignUp(0, align);
  limit = AddrAdd(base, nails * align);

  die(BTCreate(&bt, arena, nails), "BTCreate");
  BTResRange(bt, 0, nails);
  die(NailboardCreate(&board, arena, align, base, limit), "NailboardCreate");

  for (i = 0; i <= nails / 8; ++i) {
    Bool old;
    j = rnd() % nails;
    old = BTGet(bt, j);
    BTSet(bt, j);
    cdie(NailboardSet(board, AddrAdd(base, j * align)) == old, "NailboardSet");
    for (k = 0; k < nails / 8; ++k) {
      Index b, l;
      b = rnd() % nails;
      l = b + rnd() % (nails - b) + 1;
      cdie(BTIsResRange(bt, b, l)
           == NailboardIsResRange(board, AddrAdd(base, b * align),
                                  AddrAdd(base, l * align)),
           "NailboardIsResRange");
    }
  }

  die(NailboardDescribe(board, mps_lib_get_stdout(), 0), "NailboardDescribe");
}
Ejemplo n.º 11
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);
  }
}
Ejemplo n.º 12
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);
  }
}