Exemple #1
0
/* AMSTStressBufferedSeg -- Stress test for a buffered seg
 *
 * Test splitting or merging a buffered seg.
 *
 * .bmerge: A merge is performed when the segment had previously
 * been split and the segment above meets the constraints (i.e. empty,
 * not already attached to a buffer and similar colour)
 *
 * .bsplit: Whether or not a merge happpened, a split is performed if
 * the limit of the buffered region is also the limit of an arena
 * grain, and yet does not correspond to the segment limit, provided
 * that the part of the segment above the buffer is all free.
 */
static void AMSTStressBufferedSeg(Seg seg, Buffer buffer)
{
  AMSTSeg amstseg;
  AMST amst;
  Arena arena;
  Addr limit;
  Buffer segBuf;

  AVERT(Seg, seg);
  AVERT(Buffer, buffer);
  AVER(SegBuffer(&segBuf, seg) && segBuf == buffer);
  amstseg = Seg2AMSTSeg(seg);
  AVERT(AMSTSeg, amstseg);
  limit = BufferLimit(buffer);
  arena = PoolArena(SegPool(seg));
  amst = PoolAMST(SegPool(seg));
  AVERT(AMST, amst);

  if (amstseg->next != NULL) {
    Seg segHi = AMSTSeg2Seg(amstseg->next);
    if (AMSSegIsFree(segHi) && SegGrey(segHi) == SegGrey(seg)) {
      /* .bmerge */
      Seg mergedSeg;
      Res res;
      res = SegMerge(&mergedSeg, seg, segHi);
      if (ResOK == res) {
        amst->bmerges++;
        printf("J");
      } else {
        /* deliberate fails only */
        AVER(amst->failSegs);
      }
    }
  }

  if (SegLimit(seg) != limit &&
      AddrIsArenaGrain(limit, arena) &&
      AMSSegRegionIsFree(seg, limit, SegLimit(seg))) {
    /* .bsplit */
    Seg segLo, segHi;
    Res res;
    res = SegSplit(&segLo, &segHi, seg, limit);
    if (ResOK == res) {
      amst->bsplits++;
      printf("C");
    } else {
      /* deliberate fails only */
      AVER(amst->failSegs);
    }
  }
}
Exemple #2
0
/* MVFFFreeSegs -- Free segments from given range
 *
 * Given a free range, attempts to find entire segments within
 * it, and returns them to the arena, updating total size counter.
 *
 * This is usually called immediately after MVFFAddToFreeList.
 * It is not combined with MVFFAddToFreeList because the latter
 * is also called when new segments are added under MVFFAlloc.
 */
static void MVFFFreeSegs(MVFF mvff, Addr base, Addr limit)
{
  Seg seg = NULL;       /* suppress "may be used uninitialized" */
  Arena arena;
  Bool b;
  Addr segLimit;  /* limit of the current segment when iterating */
  Addr segBase;   /* base of the current segment when iterating */
  Res res;

  AVERT(MVFF, mvff);
  AVER(base < limit);
  /* Could profitably AVER that the given range is free, */
  /* but the CBS doesn't provide that facility. */

  if (AddrOffset(base, limit) < mvff->minSegSize)
    return; /* not large enough for entire segments */

  arena = PoolArena(MVFF2Pool(mvff));
  b = SegOfAddr(&seg, arena, base);
  AVER(b);

  segBase = SegBase(seg);
  segLimit = SegLimit(seg);

  while(segLimit <= limit) { /* segment ends in range */
    if (segBase >= base) { /* segment starts in range */
      /* Must remove from free list first, in case free list */
      /* is using inline data structures. */
      res = CBSDelete(CBSOfMVFF(mvff), segBase, segLimit);
      AVER(res == ResOK);
      mvff->free -= AddrOffset(segBase, segLimit);
      mvff->total -= AddrOffset(segBase, segLimit);
      SegFree(seg);
    }

    /* Avoid calling SegNext if the next segment would fail */
    /* the loop test, mainly because there might not be a */
    /* next segment. */
    if (segLimit == limit) /* segment ends at end of range */
      break;

    b = SegNext(&seg, arena, segBase);
    AVER(b);
    segBase = SegBase(seg);
    segLimit = SegLimit(seg);
  }

  return;
}
Exemple #3
0
static void segBufAttach(Buffer buffer, Addr base, Addr limit,
                         Addr init, Size size)
{
  SegBuf segbuf = MustBeA(SegBuf, buffer);
  Seg seg = NULL;       /* suppress "may be used uninitialized" */
  Arena arena;
  Bool found;

  /* Other parameters are consistency checked in BufferAttach */
  UNUSED(init);
  UNUSED(size);

  arena = BufferArena(buffer);
  found = SegOfAddr(&seg, arena, base);
  AVER(found);
  AVER(segbuf->seg == NULL);
  AVER(!SegHasBuffer(seg));
  AVER(SegBase(seg) <= base);
  AVER(limit <= SegLimit(seg));

  /* attach the buffer to the segment */
  SegSetBuffer(seg, buffer);
  segbuf->seg = seg;

  AVERT(SegBuf, segbuf);
}
Exemple #4
0
static int ReadWrite( int (*r)(word,dword,char*), addr48_ptr *addr, char *data, int req ) {

    int         len;
    word        segment;
    dword       offset;

    offset = addr->offset;
    segment = addr->segment;
                                                                          _DBG2(("Read Write %4.4x:%8.8lx",segment,offset));
    if( SegLimit( segment ) >= offset + req - 1 ) {
                                                                          _DBG2(("Read Write Ok for %d", req));
        if( !r( segment, offset, data ) ) {
            segment = AltSegment( segment );
        }
        if( SegLimit( segment ) < offset + req - 1 ) {
                                                                          _DBG3(("Gosh, we're in trouble dudes"));
            if( SegLimit( segment ) == 0 ) {
                                                                          _DBG3(("Gosh, we're in SERIOUS trouble dudes"));
            }
        } else {
            len = req;
            while( --len >= 0 ) {
                if( !r( segment, offset++, data++ ) ) {
                                                                          _DBG3(("failed for %4.4x:%8.8lx", segment, offset-1));
                }
            }
                                                                          _DBG2(("Read Write Done"));
            return( req );
        }
    }
    len = 0;
                                                                          _DBG2(("Read Write One byte at a time for %d", req));
    while( --req >= 0 ) {
        if( SegLimit( segment ) < offset ) break;
        if( !r( segment, offset, data ) ) {
            segment = AltSegment( segment );
        }
        if( !r( segment, offset++, data++ ) ) {
                                                                          _DBG3(("failed for %4.4x:%8.8lx", segment, offset-1));
        }
        ++len;
    }
                                                                          _DBG2(("Read Write Done"));
    return( len );
}
Exemple #5
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;
}
Exemple #6
0
static void shieldSync(Shield shield, Seg seg)
{
  SHIELD_AVERT_CRITICAL(Seg, seg);

  if (!SegIsSynced(seg)) {
    shieldSetPM(shield, seg, SegSM(seg));
    ProtSet(SegBase(seg), SegLimit(seg), SegPM(seg));
  }
}
Exemple #7
0
void BufferReassignSeg(Buffer buffer, Seg seg)
{
  AVERT(Buffer, buffer);
  AVERT(Seg, seg);
  AVER(!BufferIsReset(buffer));
  AVER(BufferBase(buffer) >= SegBase(seg));
  AVER(BufferLimit(buffer) <= SegLimit(seg));
  AVER(BufferPool(buffer) == SegPool(seg));
  Method(Buffer, buffer, reassignSeg)(buffer, seg);
}
Exemple #8
0
Res PoolAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr)
{
  AVER(pReturn != NULL);
  AVERT(Pool, pool);
  AVERT(Seg, seg);
  AVER(pool == SegPool(seg));
  AVER(SegBase(seg) <= addr);
  AVER(addr < SegLimit(seg));
  return Method(Pool, pool, addrObject)(pReturn, pool, seg, addr);
}
Exemple #9
0
int init_once(RP rp)
{
	switch (done_init) {
	case 2:	/* fatal error */
		return 2;
	case 0:	/* must init */
		Device_Help = rp->pk.init.devhlp;

		/* read cmd line params */
		read_args(rp->pk.init.args);

		done_init = 1;	

		/* allocate memory */
		buf1 = AllocBuf(32l * sizeof(struct tty));
		buf2 = AllocBuf(32l * sizeof(struct tty));

		if (!buf1 || !buf2)
		{
			/* fatal */
			rp->pk.initexit.cs = 0;
			rp->pk.initexit.ds = 0;
			done_init = 2;
			return 2;
		}

		DosPutMessage(1, sizeof(version_msg) - 1, version_msg);
		DosPutMessage(1, sizeof(once_msg) - 1, once_msg);
		if (dbgflag)
		{
			DosPutMessage(1, sizeof(dbg_msg) - 1, dbg_msg);
			int3();
		}

		/* fall thru */
	case 1: /* ok */
#define GETSEL(ptr) ((USHORT)(((ULONG)((void far*)ptr)>>16)&0xffff))
		SegLimit(GETSEL(DiscardProc),&rp->pk.initexit.cs);
		SegLimit(GETSEL(&DiscardData),&rp->pk.initexit.ds);
	}
	return 1;
}
Exemple #10
0
static void shieldProtLower(Shield shield, Seg seg, AccessSet mode)
{
  /* <design/trace/#fix.noaver> */
  SHIELD_AVERT_CRITICAL(Seg, seg);
  AVERT_CRITICAL(AccessSet, mode);

  if (BS_INTER(SegPM(seg), mode) != AccessSetEMPTY) {
    shieldSetPM(shield, seg, BS_DIFF(SegPM(seg), mode));
    ProtSet(SegBase(seg), SegLimit(seg), SegPM(seg));
  }
}
Exemple #11
0
static void shieldSync(Arena arena, Seg seg)
{
    AVERT(Arena, arena);
    AVERT(Seg, seg);

    if (SegPM(seg) != SegSM(seg)) {
        ProtSet(SegBase(seg), SegLimit(seg), SegSM(seg));
        SegSetPM(seg, SegSM(seg));
        /* inv.prot.shield */
    }
}
Exemple #12
0
Res PoolAccess(Pool pool, Seg seg, Addr addr,
               AccessSet mode, MutatorFaultContext context)
{
  AVERT(Pool, pool);
  AVERT(Seg, seg);
  AVER(SegBase(seg) <= addr);
  AVER(addr < SegLimit(seg));
  AVERT(AccessSet, mode);
  /* Can't check MutatorFaultContext as there is no check method */

  return Method(Pool, pool, access)(pool, seg, addr, mode, context);
}
Exemple #13
0
/* This ensures actual prot mode does not include mode */
static void protLower(Arena arena, Seg seg, AccessSet mode)
{
    /* <design/trace/#fix.noaver> */
    AVERT_CRITICAL(Arena, arena);
    UNUSED(arena);
    AVERT_CRITICAL(Seg, seg);

    if (SegPM(seg) & mode) {
        SegSetPM(seg, SegPM(seg) & ~mode);
        ProtSet(SegBase(seg), SegLimit(seg), SegPM(seg));
    }
}
Exemple #14
0
static  word    LookUp( word sdtseg, word seg, word global )
{
    dword       sdtoff;
    dword       sdtlim;
    dword       linear;
    word        otherseg;

    sdtlim = SegLimit( sdtseg );
    linear = GetLinear( seg, 0 );
    for( sdtoff = 0; sdtoff < sdtlim; sdtoff += 8 ) {
        if( sdtoff == ( seg & 0xfff8 ) ) continue;
        otherseg = sdtoff + ( global ? 0 : 4 );
        if( !WriteOk( otherseg ) ) continue;
        if( GetLinear( otherseg, 0 ) != linear ) continue;
                                                                          _DBG3(("lookup %4.4x", otherseg));
        return( otherseg );
    }
    return( 0 );
}
Exemple #15
0
static void shieldFlushEntries(Shield shield)
{
  Addr base = NULL, limit;
  AccessSet mode;
  Index i;

  if (shield->length == 0) {
    AVER(shield->queue == NULL);
    return;
  }

  QuickSort((void *)shield->queue, shield->limit,
            shieldQueueEntryCompare, UNUSED_POINTER,
            &shield->sortStruct);

  mode = AccessSetEMPTY;
  limit = NULL;
  for (i = 0; i < shield->limit; ++i) {
    Seg seg = shieldDequeue(shield, i);
    if (!SegIsSynced(seg)) {
      shieldSetPM(shield, seg, SegSM(seg));
      if (SegSM(seg) != mode || SegBase(seg) != limit) {
        if (base != NULL) {
          AVER(base < limit);
          ProtSet(base, limit, mode);
        }
        base = SegBase(seg);
        mode = SegSM(seg);
      }
      limit = SegLimit(seg);
    }
  }
  if (base != NULL) {
    AVER(base < limit);
    ProtSet(base, limit, mode);
  }

  shieldQueueReset(shield);
}
Exemple #16
0
/* MVFFFreeSegs -- Free segments from given range
 *
 * Given a free range, attempts to find entire segments within
 * it, and returns them to the arena, updating total size counter.
 *
 * This is usually called immediately after MVFFAddToFreeList.
 * It is not combined with MVFFAddToFreeList because the latter
 * is also called when new segments are added under MVFFAlloc.
 */
static void MVFFFreeSegs(MVFF mvff, Addr base, Addr limit)
{
  Seg seg = NULL;       /* suppress "may be used uninitialized" */
  Arena arena;
  Bool b;
  Addr segLimit;  /* limit of the current segment when iterating */
  Addr segBase;   /* base of the current segment when iterating */
  Res res;

  AVERT(MVFF, mvff);
  AVER(base < limit);
  /* Could profitably AVER that the given range is free, */
  /* but the CBS doesn't provide that facility. */

  if (AddrOffset(base, limit) < mvff->minSegSize)
    return; /* not large enough for entire segments */

  arena = PoolArena(MVFF2Pool(mvff));
  b = SegOfAddr(&seg, arena, base);
  AVER(b);

  segBase = SegBase(seg);
  segLimit = SegLimit(seg);

  while(segLimit <= limit) { /* segment ends in range */
    if (segBase >= base) { /* segment starts in range */
      RangeStruct range, oldRange;
      RangeInit(&range, segBase, segLimit);

      res = CBSDelete(&oldRange, CBSOfMVFF(mvff), &range);
      if (res == ResOK) {
        mvff->free -= RangeSize(&range);
      } else if (ResIsAllocFailure(res)) {
        /* CBS ran out of memory for splay nodes, which must mean that
         * there were fragments on both sides: see
         * <design/cbs/#function.cbs.delete.fail>. Handle this by
         * deleting the whole of oldRange (which requires no
         * allocation) and re-inserting the fragments. */
        RangeStruct oldRange2;
        res = CBSDelete(&oldRange2, CBSOfMVFF(mvff), &oldRange);
        AVER(res == ResOK);
        AVER(RangesEqual(&oldRange2, &oldRange));
        mvff->free -= RangeSize(&oldRange);
        AVER(RangeBase(&oldRange) != segBase);
        {
          Addr leftBase = RangeBase(&oldRange);
          Addr leftLimit = segBase;
          res = MVFFAddToFreeList(&leftBase, &leftLimit, mvff);
        }
        AVER(RangeLimit(&oldRange) != segLimit);
        {
          Addr rightBase = segLimit;
          Addr rightLimit = RangeLimit(&oldRange);
          res = MVFFAddToFreeList(&rightBase, &rightLimit, mvff);
        }
      } else if (res == ResFAIL) {
        /* Not found in the CBS: must be found in the Freelist. */
        res = FreelistDelete(&oldRange, FreelistOfMVFF(mvff), &range);
        AVER(res == ResOK);
        mvff->free -= RangeSize(&range);
      }

      AVER(res == ResOK);
      AVER(RangesNest(&oldRange, &range));

      /* Can't free the segment earlier, because if it was on the
       * Freelist rather than the CBS then it likely contains data
       * that needs to be read in order to update the Freelist. */
      SegFree(seg);
      mvff->total -= RangeSize(&range);
    }

    /* Avoid calling SegNext if the next segment would fail */
    /* the loop test, mainly because there might not be a */
    /* next segment. */
    if (segLimit == limit) /* segment ends at end of range */
      break;

    b = SegFindAboveAddr(&seg, arena, segBase);
    AVER(b);
    segBase = SegBase(seg);
    segLimit = SegLimit(seg);
  }

  return;
}
Exemple #17
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;
}