Esempio n. 1
0
/* If the segment is out of sync, either sync it, or ensure
 * depth > 0, and the arena is suspended.
 */
static void cache(Arena arena, Seg seg)
{
    /* <design/trace/#fix.noaver> */
    AVERT_CRITICAL(Arena, arena);
    AVERT_CRITICAL(Seg, seg);

    if (SegSM(seg) == SegPM(seg)) return;
    if (SegDepth(seg) > 0) {
        ShieldSuspend(arena);
        return;
    }
    if (ShieldCacheSIZE == 0 || !arena->suspended)
        shieldSync(arena, seg);
    else {
        SegSetDepth(seg, SegDepth(seg) + 1);
        ++arena->shDepth;
        AVER(arena->shDepth > 0);
        AVER(SegDepth(seg) > 0);
        AVER(arena->shCacheLimit <= ShieldCacheSIZE);
        AVER(arena->shCacheI < arena->shCacheLimit);
        flush(arena, arena->shCacheI);
        arena->shCache[arena->shCacheI] = seg;
        ++arena->shCacheI;
        if (arena->shCacheI == ShieldCacheSIZE)
            arena->shCacheI = 0;
        if (arena->shCacheI == arena->shCacheLimit)
            ++arena->shCacheLimit;
    }
}
Esempio n. 2
0
File: shield.c Progetto: bhanug/mps
static void shieldFlushEntry(Shield shield, Index i)
{
  Seg seg = shieldDequeue(shield, i);

  if (!SegIsExposed(seg))
    shieldSync(shield, seg);
}
Esempio n. 3
0
static void flush(Arena arena, Size i)
{
    Seg seg;
    AVERT(Arena, arena);
    AVER(i < arena->shCacheLimit);

    seg = arena->shCache[i];
    if (seg == NULL) return;
    AVERT(Seg, seg);

    AVER(arena->shDepth > 0);
    AVER(SegDepth(seg) > 0);
    --arena->shDepth;
    SegSetDepth(seg, SegDepth(seg) - 1);

    if (SegDepth(seg) == 0)
        shieldSync(arena, seg);

    arena->shCache[i] = NULL;
}
Esempio n. 4
0
File: shield.c Progetto: bhanug/mps
static void shieldQueue(Arena arena, Seg seg)
{
  Shield shield;
  
  /* <design/trace/#fix.noaver> */
  AVERT_CRITICAL(Arena, arena);
  shield = ArenaShield(arena);
  SHIELD_AVERT_CRITICAL(Seg, seg);

  if (SegIsSynced(seg) || seg->queued)
    return;

  if (SegIsExposed(seg)) {
    /* This can occur if the mutator isn't suspended, we expose a
       segment, then raise the shield on it.  In this case, the
       mutator isn't allowed to see the segment, but we don't need to
       queue it until its covered. */
    shieldSuspend(arena);
    return;
  }

  /* Allocate or extend the shield queue if necessary. */
  if (shield->next >= shield->length) {
    void *p;
    Res res;
    Count length;

    AVER(shield->next == shield->length);

    if (shield->length == 0)
      length = ShieldQueueLENGTH;
    else
      length = shield->length * 2;
    
    res = ControlAlloc(&p, arena, length * sizeof shield->queue[0]);
    if (res != ResOK) {
      AVER(ResIsAllocFailure(res));
      /* Carry on with the existing queue. */
    } else {
      if (shield->length > 0) {
        Size oldSize = shield->length * sizeof shield->queue[0];
        AVER(shield->queue != NULL);
        mps_lib_memcpy(p, shield->queue, oldSize);
        ControlFree(arena, shield->queue, oldSize);
      }
      shield->queue = p;
      shield->length = length;
    }
  }

  /* Queue unavailable, so synchronize now.  Or if the mutator is not
     yet suspended and the code raises the shield on a covered
     segment, protect it now, because that's probably better than
     suspending the mutator. */
  if (shield->length == 0 || !shield->suspended) {
    shieldSync(shield, seg);
    return;
  }

  AVER_CRITICAL(shield->limit <= shield->length);
  AVER_CRITICAL(shield->next <= shield->limit);

  /* If we failed to extend the shield queue array, degrade to an LRU
     circular buffer. */
  if (shield->next >= shield->length)
    shield->next = 0;
  AVER_CRITICAL(shield->next < shield->length);

  AVER_CRITICAL(shield->length > 0);

  /* If the limit is less than the length, then the queue array has
     yet to be filled, and next is an uninitialized entry.
     Otherwise it's the tail end from last time around, and needs to
     be flushed. */
  if (shield->limit >= shield->length) {
    AVER_CRITICAL(shield->limit == shield->length);
    shieldFlushEntry(shield, shield->next);
  }

  shield->queue[shield->next] = seg;
  ++shield->next;
  seg->queued = TRUE;

  if (shield->next >= shield->limit)
    shield->limit = shield->next;
}