private void RecordStore(T data, MemoryOrder mo, ShadowThread runningThread, bool isReleaseSequence) { var storeTarget = _history.GetNext(); storeTarget.RecordStore(runningThread.Id, runningThread.Clock, mo, data); bool isAtLeastRelease = mo == MemoryOrder.Release || mo == MemoryOrder.AcquireRelease || mo == MemoryOrder.SequentiallyConsistent; // Here 'sourceClock' is the clock that other threads must synchronize with if they read-acquire this data. // If this store is a release (or stronger), then those threads must synchronize with the latest clocks that // this thread has synchronized with (i.e. the releases it has acquired: runningThread.ReleasesAcquired). // Otherwise, if this store is relaxed, then those threads need only synchronize with the latest release fence of this thread // (i.e. runningThread.FenceReleasesAcquired) var sourceClock = isAtLeastRelease ? runningThread.ReleasesAcquired : runningThread.FenceReleasesAcquired; var previous = _history[_history.CurrentIndex - 1]; var targetClock = storeTarget.ReleasesToAcquire; if (isReleaseSequence) { targetClock.Assign(previous.ReleasesToAcquire); targetClock.Join(sourceClock); } else { targetClock.Assign(sourceClock); } }
public T Load(ShadowThread runningThread, Action <string> failTest) { if (_storeClock.AnyGreater(runningThread.ReleasesAcquired)) { failTest($"Data race detected in load on thread {runningThread.Id} @ {runningThread.Clock}"); return(default(T)); } runningThread.IncrementClock(); _loadClock[runningThread.Id] = runningThread.Clock; return(_data); }
public void Store(T data, ShadowThread runningThread, Action <string> failTest) { if (_loadClock.AnyGreater(runningThread.ReleasesAcquired) || _storeClock.AnyGreater(runningThread.ReleasesAcquired)) { failTest($"Data race detected in store on thread {runningThread.Id} @ {runningThread.Clock}"); return; } runningThread.IncrementClock(); _storeClock[runningThread.Id] = runningThread.Clock; _data = data; return; }
private T RecordLoad(MemoryOrder mo, ShadowThread runningThread, AccessData <T> loadData) { loadData.RecordLoad(runningThread.Id, runningThread.Clock); bool isAtLeastAcquire = mo == MemoryOrder.Acquire || mo == MemoryOrder.AcquireRelease || mo == MemoryOrder.SequentiallyConsistent; // Here 'destinationClock' is the clock that must synchronize with the last release to this data. // If this load is an acquire (or stronger), then this thread's clock must synchronize with the last release // (i.e. it should acquire the release to this data so runningThread.ReleasesAcquired must update). // Otherwise, if this load is relaxed, then other threads must only synchronize with the last release to this data // if an acquire fence is issued. So to allow for updating the releases acquired by this thread in the case of an acquire // fence being issued at some point, update runningThread.FenceReleasesToAcquire var destinationClock = isAtLeastAcquire ? runningThread.ReleasesAcquired : runningThread.FenceReleasesToAcquire; destinationClock.Join(loadData.ReleasesToAcquire); return(loadData.Payload); }
public T RecordPossibleLoad(MemoryOrder mo, ShadowThread runningThread) { var loadData = GetPossibleLoad(runningThread.ReleasesAcquired, runningThread.Id, mo); return(RecordLoad(mo, runningThread, loadData)); }
public T RecordRMWLoad(MemoryOrder mo, ShadowThread runningThread) { var loadData = _history[_history.CurrentIndex]; return(RecordLoad(mo, runningThread, loadData)); }
public void RecordStore(T data, MemoryOrder mo, ShadowThread runningThread) { var previous = _history[_history.CurrentIndex - 1]; RecordStore(data, mo, runningThread, previous.IsInitialized && previous.LastStoredThreadId == runningThread.Id); }
public void RecordRMWStore(T data, MemoryOrder mo, ShadowThread runningThread) { RecordStore(data, mo, runningThread, true); }