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 */ } }
void (ShieldLower)(Arena arena, Seg seg, AccessSet mode) { /* Don't check seg or arena, see .seg.broken */ AVER((SegSM(seg) & mode) == mode); /* synced(seg) is not changed by the following * preserving inv.unsynced.suspended * Also inv.prot.shield preserved */ SegSetSM(seg, SegSM(seg) & ~mode); protLower(arena, seg, mode); AVERT(Arena, arena); AVERT(Seg, seg); }
void (ShieldRaise) (Arena arena, Seg seg, AccessSet mode) { /* .seg.broken: Seg's shield invariants may not be true at */ /* this point (this function is called to enforce them) so we */ /* can't check seg. Nor can we check arena as that checks the */ /* segs in the cache. */ AVER((SegSM(seg) & mode) == AccessSetEMPTY); SegSetSM(seg, SegSM(seg) | mode); /* inv.prot.shield preserved */ /* ensure inv.unsynced.suspended & inv.unsynced.depth */ cache(arena, seg); AVERT(Arena, arena); AVERT(Seg, seg); }
/* 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; } }
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)); } }
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); }
static void shieldSetSM(Shield shield, Seg seg, AccessSet mode) { if (SegSM(seg) != mode) { if (SegIsSynced(seg)) { SegSetSM(seg, mode); ++shield->unsynced; } else { SegSetSM(seg, mode); if (SegIsSynced(seg)) { AVER(shield->unsynced > 0); --shield->unsynced; } } } }
void (ShieldLower)(Arena arena, Seg seg, AccessSet mode) { Shield shield; AVERT(Arena, arena); shield = ArenaShield(arena); SHIELD_AVERT(Seg, seg); AVERT(AccessSet, mode); /* SegIsSynced(seg) is not changed by the following preserving design.mps.shield.inv.unsynced.suspended and design.mps.shield.inv.prot.shield. */ shieldSetSM(shield, seg, BS_DIFF(SegSM(seg), mode)); /* TODO: Do we need to promptly call shieldProtLower here? It loses the opportunity to coalesce the protection call. It would violate design.mps.shield.prop.inside.access. */ /* shieldQueue(arena, seg); */ shieldProtLower(shield, seg, mode); /* Check queue and segment consistency. */ AVERT(Arena, arena); AVERT(Seg, seg); }
void (ShieldRaise)(Arena arena, Seg seg, AccessSet mode) { Shield shield; SHIELD_AVERT(Arena, arena); SHIELD_AVERT(Seg, seg); AVERT(AccessSet, mode); shield = ArenaShield(arena); AVER(!shield->queuePending); shield->queuePending = TRUE; /* design.mps.shield.inv.prot.shield preserved */ shieldSetSM(ArenaShield(arena), seg, BS_UNION(SegSM(seg), mode)); /* Ensure design.mps.shield.inv.unsynced.suspended and design.mps.shield.inv.unsynced.depth */ shieldQueue(arena, seg); shield->queuePending = FALSE; /* Check queue and segment consistency. */ AVERT(Arena, arena); AVERT(Seg, seg); }
/* ArenaExposeRemember -- park arena and then lift all protection barriers. Parameter 'remember' specifies whether to remember the protection state or not (for later restoration with ArenaRestoreProtection). */ void ArenaExposeRemember(Globals globals, Bool remember) { Seg seg; Arena arena; AVERT(Globals, globals); AVERT(Bool, remember); ArenaPark(globals); arena = GlobalsArena(globals); if(SegFirst(&seg, arena)) { Addr base; do { base = SegBase(seg); if (IsA(GCSeg, seg)) { if(remember) { RefSet summary; summary = SegSummary(seg); if(summary != RefSetUNIV) { Res res = arenaRememberSummaryOne(globals, base, summary); if(res != ResOK) { /* If we got an error then stop trying to remember any protections. */ remember = 0; } } } SegSetSummary(seg, RefSetUNIV); AVER(SegSM(seg) == AccessSetEMPTY); } } while(SegNext(&seg, arena, seg)); } }
static Bool SegIsSynced(Seg seg) { SHIELD_AVERT_CRITICAL(Seg, seg); return SegSM(seg) == SegPM(seg); }