public void PlayBack(IEnumerable <Trace> traces) { foreach (var t in traces) { SimThread thread = GetThread(t); SimLock lk = GetLock(t); string frame = t.GetUsefullTopTrace(this.syms); switch (t.record) { case Record.MustNotHoldAny: case Record.MustNotHoldOne: case Record.MustHoldOne: throw new Exception("not supported"); case Record.LockAcquired: thread.Lock(lk, frame); break; case Record.LockReleased: thread.Release(lk, frame); break; default: throw new Exception("Invalid trace record: " + t.record); } } }
public bool IsValid(SimThread thread, SimLock locked) { bool warn; string msg; return(Compare(thread, locked, out warn, out msg)); }
/*locked is already owned by the thread, 'this' is the new one*/ bool Compare(SimThread thread, SimLock locked, out bool isWarning, out string msg) { isWarning = false; msg = null; if (locked != this) { if (!IsParent(locked)) { if (IsGlobalLock) /*acquiring a global lock*/ { if (!thread.HoldsLock(this)) /*does the thread alread hold it?*/ { msg = "Acquired a global lock after a regular lock without having it before."; return(false); } } else { msg = "Hierarchy violation."; return(false); } } } else if (IsSimpleLock) { msg = "Avoid taking simple locks recursively"; isWarning = true; return(false); } return(true); }
public string GetErrorMessage(SimThread thread, SimLock locked) { bool warn; string msg; bool res = Compare(thread, locked, out warn, out msg); return(!res && !warn ? msg : null); }
public string GetWarningMessage(SimThread thread, SimLock locked) { bool warn; string msg; Compare(thread, locked, out warn, out msg); return(warn ? msg : null); }
public bool WarnAbout(SimThread thread, SimLock locked) { bool warn; string msg; Compare(thread, locked, out warn, out msg); return(warn); }
public bool HoldsLock(SimLock lk) { foreach (var l in locks) { if (l.lk == lk) { return(true); } } return(false); }
public int HoldCount(SimLock lk) { int res = 0; foreach (var l in locks) { if (l.lk == lk) { ++res; } } return(res); }
public void Lock(SimLock lk, string frame) { foreach (LockRecord lr in locks) { if (lk.WarnAbout(this, lr.lk)) { Console.WriteLine("WARNING: tried to acquire lock {0} at {1} while holding {2} at {3}: {4}", lk, frame, lr.lk, lr.frame, lk.GetWarningMessage(this, lr.lk)); } else if (!lk.IsValid(this, lr.lk)) { Console.WriteLine("ERROR: tried to acquire lock {0} at {1} while holding {2} at {3}: {4}", lk, frame, lr.lk, lr.frame, lk.GetErrorMessage(this, lr.lk)); } } locks.Add(new LockRecord(lk, frame)); }
public void Release(SimLock lk, string frame) { if (locks.Count == 0) { Console.WriteLine("ERROR: released lock {0} at {1} while holding no locks!", lk, frame); return; } LockRecord top = locks [locks.Count - 1]; if (top.lk != lk && !(lk.IsGlobalLock && HoldCount(lk) > 1)) { Console.WriteLine("WARNING: released lock {0} at {1} out of order with {2} at {3}!", lk, frame, top.lk, top.frame); } for (int i = locks.Count - 1; i >= 0; --i) { if (locks [i].lk == lk) { locks.RemoveAt(i); break; } } }
public LockRecord(SimLock lk, string frame) { this.lk = lk; this.frame = frame; }
bool IsParent(SimLock other) { return(GetLockOrder(kind) > GetLockOrder(other.kind)); }