Beispiel #1
0
static Res EPVMSegInit(Seg seg, Pool pool, Addr base, Size size,
                       Bool reservoirPermit, va_list args)
{
  SegClass super;
  EPVMSeg epvmSeg;
  EPVM epvm;
  EPVMSave save;
  Res res;

  AVERT(Seg, seg);
  epvmSeg = Seg2EPVMSeg(seg);
  AVERT(Pool, pool);
  epvm = Pool2EPVM(pool);
  AVERT(EPVM, epvm);
  /* no useful checks for base and size */
  AVER(BoolCheck(reservoirPermit));

  /* Initialize the superclass fields first via next-method call */
  super = SEG_SUPERCLASS(EPVMSegClass);
  res = super->init(seg, pool, base, size, reservoirPermit, args);
  if (res != ResOK)
    return res;

  save = EPVMCurrentSave(epvm);
  epvmSeg->save = save;
  save->size += SegSize(seg);
  /* The small*Seg flag can't be set here, because the rankset is not set. */

  epvmSeg->sig = EPVMSegSig;
  AVERT(EPVMSeg, epvmSeg);

  return ResOK;
}
Beispiel #2
0
static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size,
                     Bool withReservoirPermit, DebugInfo info)
{
  Res res;
  MVFF mvff;
  Addr base, limit;
  Bool foundBlock;

  AVERT(Pool, pool);
  mvff = Pool2MVFF(pool);
  AVERT(MVFF, mvff);

  AVER(aReturn != NULL);
  AVER(size > 0);
  AVER(BoolCheck(withReservoirPermit));
  UNUSED(info);

  size = SizeAlignUp(size, PoolAlignment(pool));

  foundBlock = MVFFFindFirstFree(&base, &limit, mvff, size);
  if (!foundBlock) {
    Seg seg;

    res = MVFFAddSeg(&seg, mvff, size, withReservoirPermit);
    if (res != ResOK)
      return res;
    foundBlock = MVFFFindFirstFree(&base, &limit, mvff, size);

    /* We know that the found range must intersect the new segment. */
    /* In particular, it doesn't necessarily lie entirely within it. */
    /* The next three AVERs test for intersection of two intervals. */
    AVER(base >= SegBase(seg) || limit <= SegLimit(seg));
    AVER(base < SegLimit(seg));
    AVER(SegBase(seg) < limit);

    /* We also know that the found range is no larger than the segment. */
    AVER(SegSize(seg) >= AddrOffset(base, limit));
  }
  AVER(foundBlock);
  AVER(AddrOffset(base, limit) == size);

  *aReturn = base;

  return ResOK;
}
Beispiel #3
0
Bool EPVMSegCheck(EPVMSeg epvmSeg)
{
  Seg seg;

  CHECKS(EPVMSeg, epvmSeg);
  CHECKL(AMSSegCheck(&epvmSeg->amsSegStruct));
  seg = EPVMSeg2Seg(epvmSeg);
  CHECKU(EPVMSave, epvmSeg->save);
  CHECKL(epvmSeg->save->size >= SegSize(seg));
  /* buffers only on the current save level */
  if (SegBuffer(seg) != NULL)
    CHECKL(EPVMCurrentSave(EPVMSegEPVM(epvmSeg)) == epvmSeg->save);
  /* See design.mps.poolepvm.protection.format and */
  /* d.m.p.protection.hack. */
  AVER(SegSummary(seg) == RefSetUNIV || SegSummary(seg) == RefSetEMPTY);

  return TRUE;
}
Beispiel #4
0
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);
}
Beispiel #5
0
static void EPVMSegFinish(Seg seg)
{
  EPVMSeg epvmSeg;
  EPVMSave save;
  Size size;

  AVERT(Seg, seg);
  epvmSeg = Seg2EPVMSeg(seg);
  AVERT(EPVMSeg, epvmSeg);

  size = SegSize(seg);
  save = epvmSeg->save;
  AVERT(EPVMSave, save);
  epvmSeg->sig = SigInvalid;

  /* finish the superclass fields last */
  SEG_SUPERCLASS(EPVMSegClass)->finish(seg);

  /* save->size must be consistent when calling super, so update after */
  AVER(save->size >= size);
  save->size -= size;
}
Beispiel #6
0
/* AMSTBufferFill -- the pool class buffer fill method
 *
 * Calls next method - but possibly splits or merges the chosen
 * segment.
 *
 * .merge: A merge is performed when the next method returns the
 * entire segment, this segment had previously been split from the
 * segment below, and the segment below is appropriately similar
 * (i.e. not already attached to a buffer and similarly coloured)
 *
 * .split: If we're not merging, a split is performed if the next method
 * returns the entire segment, and yet lower half of the segment would
 * meet the request.
 */
static Res AMSTBufferFill(Addr *baseReturn, Addr *limitReturn,
                          Pool pool, Buffer buffer, Size size)
{
  Addr base, limit;
  Arena arena;
  AMS ams;
  AMST amst;
  Bool b;
  Seg seg;
  AMSTSeg amstseg;
  Res res;

  AVERT(Pool, pool);
  AVER(baseReturn != NULL);
  AVER(limitReturn != NULL);
  /* other parameters are checked by next method */
  arena = PoolArena(pool);
  ams = PoolAMS(pool);
  amst = PoolAMST(pool);

  /* call next method */
  res = NextMethod(Pool, AMSTPool, bufferFill)(&base, &limit, pool, buffer, size);
  if (res != ResOK)
    return res;

  b = SegOfAddr(&seg, arena, base);
  AVER(b);
  amstseg = Seg2AMSTSeg(seg);

  if (SegLimit(seg) == limit && SegBase(seg) == base) {
    if (amstseg->prev != NULL) {
      Seg segLo = AMSTSeg2Seg(amstseg->prev);
      if (!SegHasBuffer(segLo) &&
          SegGrey(segLo) == SegGrey(seg) &&
          SegWhite(segLo) == SegWhite(seg)) {
        /* .merge */
        Seg mergedSeg;
        Res mres;

        AMSUnallocateRange(ams, seg, base, limit);
        mres = SegMerge(&mergedSeg, segLo, seg);
        if (ResOK == mres) { /* successful merge */
          AMSAllocateRange(ams, mergedSeg, base, limit);
          /* leave range as-is */
        } else {            /* failed to merge */
          AVER(amst->failSegs); /* deliberate fails only */
          AMSAllocateRange(ams, seg, base, limit);
        }
      }

    } else {
      Size half = SegSize(seg) / 2;
      if (half >= size && SizeIsArenaGrains(half, arena)) {
        /* .split */
        Addr mid = AddrAdd(base, half);
        Seg segLo, segHi;
        Res sres;
        AMSUnallocateRange(ams, seg, mid, limit);
        sres = SegSplit(&segLo, &segHi, seg, mid);
        if (ResOK == sres) { /* successful split */
          limit = mid;  /* range is lower segment */
        } else {            /* failed to split */
          AVER(amst->failSegs); /* deliberate fails only */
          AMSAllocateRange(ams, seg, mid, limit);
        }

      }
    }
  }

  *baseReturn = base;
  *limitReturn = limit;
  return ResOK;
}