/* 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; } }
void (ShieldCover)(Arena arena, Seg seg) { /* <design/trace/#fix.noaver> */ AVERT_CRITICAL(Arena, arena); AVERT_CRITICAL(Seg, seg); AVER_CRITICAL(SegPM(seg) == AccessSetEMPTY); AVER_CRITICAL(arena->shDepth > 0); AVER_CRITICAL(SegDepth(seg) > 0); SegSetDepth(seg, SegDepth(seg) - 1); --arena->shDepth; /* ensure inv.unsynced.depth */ cache(arena, seg); }
static void shieldDebugCheck(Arena arena) { Shield shield; Seg seg; Count queued = 0; Count depth = 0; AVERT(Arena, arena); shield = ArenaShield(arena); AVER(shield->inside || shield->limit == 0); if (SegFirst(&seg, arena)) do { depth += SegDepth(seg); if (shield->limit == 0) { AVER(!seg->queued); AVER(SegIsSynced(seg)); /* You can directly set protections here to see if it makes a difference. */ /* ProtSet(SegBase(seg), SegLimit(seg), SegPM(seg)); */ } else { if (seg->queued) ++queued; } } while(SegNext(&seg, arena, seg)); AVER(depth == shield->depth); AVER(queued == shield->limit); }
void (ShieldCover)(Arena arena, Seg seg) { Shield shield; /* <design/trace/#fix.noaver> */ AVERT_CRITICAL(Arena, arena); shield = ArenaShield(arena); AVERT_CRITICAL(Seg, seg); AVER_CRITICAL(SegPM(seg) == AccessSetEMPTY); AVER_CRITICAL(SegDepth(seg) > 0); SegSetDepth(seg, SegDepth(seg) - 1); AVER_CRITICAL(shield->depth > 0); --shield->depth; /* Ensure design.mps.shield.inv.unsynced.depth. */ shieldQueue(arena, seg); }
void (ShieldExpose)(Arena arena, Seg seg) { AccessSet mode = AccessREAD | AccessWRITE; /* <design/trace/#fix.noaver> */ AVERT_CRITICAL(Arena, arena); AVER_CRITICAL(arena->insideShield); SegSetDepth(seg, SegDepth(seg) + 1); ++arena->shDepth; /* <design/trace/#fix.noaver> */ AVER_CRITICAL(arena->shDepth > 0); AVER_CRITICAL(SegDepth(seg) > 0); if (SegPM(seg) & mode) ShieldSuspend(arena); /* This ensures inv.expose.prot */ protLower(arena, seg, mode); }
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; }
void (ShieldExpose)(Arena arena, Seg seg) { Shield shield; AccessSet mode = AccessREAD | AccessWRITE; /* <design/trace/#fix.noaver> */ AVERT_CRITICAL(Arena, arena); shield = ArenaShield(arena); AVER_CRITICAL(shield->inside); SegSetDepth(seg, SegDepth(seg) + 1); AVER_CRITICAL(SegDepth(seg) > 0); /* overflow */ ++shield->depth; AVER_CRITICAL(shield->depth > 0); /* overflow */ if (BS_INTER(SegPM(seg), mode) != AccessSetEMPTY) shieldSuspend(arena); /* Ensure design.mps.shield.inv.expose.prot. */ /* TODO: Mass exposure -- see design.mps.shield.improv.mass-expose. */ shieldProtLower(shield, seg, mode); }